@litfamily/lithermes 1.0.28 → 1.0.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -9
- package/README_Ko-KR.md +12 -9
- package/assets/lithermes-plugin/README.md +15 -2
- package/assets/lithermes-plugin/__init__.py +49 -10
- package/assets/lithermes-plugin/adhd_stack.py +228 -0
- package/assets/lithermes-plugin/core.py +30 -4
- package/assets/lithermes-plugin/core_commands.py +99 -0
- package/assets/lithermes-plugin/core_contexts.py +54 -4
- package/assets/lithermes-plugin/core_contract.py +2 -2
- package/assets/lithermes-plugin/core_routing.py +126 -0
- package/assets/lithermes-plugin/diagnostics.py +3 -2
- package/assets/lithermes-plugin/lit_mark.py +75 -0
- package/assets/lithermes-plugin/payload-version.json +472 -60
- package/assets/lithermes-plugin/plugin.yaml +1 -1
- package/assets/lithermes-plugin/scientific_visualization.py +23 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/SKILL.md +7 -7
- package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/components.css +414 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/fonts.json +42 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/layouts/landing.html +164 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/layouts/settings.html +114 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/layouts/workspace.html +115 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/styles/computational-brutalism.json +227 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/styles/field-notes.json +205 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/styles/graphite.json +200 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/styles/meadow.json +199 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/styles/neo-brutalism.json +222 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/ui.js +226 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/README.md +2 -4
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/complete-contract.md +4 -4
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/craft-floor.md +10 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/scripts/design-lock.mjs +400 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/scripts/probe-rules.json +6 -1
- package/assets/lithermes-plugin/skills/frontend-ui-ux/scripts/probe.mjs +76 -4
- package/assets/lithermes-plugin/skills/lit-adhd/SKILL.md +194 -0
- package/assets/lithermes-plugin/skills/lit-adhd/references/brief-contract.md +55 -0
- package/assets/lithermes-plugin/skills/lit-adhd/references/card-examples.md +86 -0
- package/assets/lithermes-plugin/skills/lit-adhd/references/status-taxonomy.md +40 -0
- package/assets/lithermes-plugin/skills/lit-adhd/scripts/adhd.mjs +11 -0
- package/assets/lithermes-plugin/skills/lit-adhd/scripts/lib/collect.mjs +554 -0
- package/assets/lithermes-plugin/skills/lit-adhd/scripts/lib/gauge.mjs +89 -0
- package/assets/lithermes-plugin/skills/lit-adhd/scripts/lib/hermes-sessions.mjs +219 -0
- package/assets/lithermes-plugin/skills/lit-adhd/scripts/lib/next-step.mjs +101 -0
- package/assets/lithermes-plugin/skills/lit-adhd/scripts/lib/plan-task-rows.mjs +32 -0
- package/assets/lithermes-plugin/skills/lit-adhd/scripts/lib/redact.mjs +42 -0
- package/assets/lithermes-plugin/skills/lit-adhd/scripts/lib/secret-shapes.mjs +59 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/SKILL.md +7 -4
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/style-guide.md +20 -11
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-architecture.md +3 -3
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-dependency.md +1 -1
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-tree.md +3 -3
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-wardley.md +1 -1
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/verifier-guide.md +5 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/diagram_quality.py +4 -4
- package/assets/lithermes-plugin/skills/lit-docx/SKILL.md +1 -1
- package/assets/lithermes-plugin/skills/lit-hijack/SKILL.md +239 -0
- package/assets/lithermes-plugin/skills/lit-hijack/references/capture-and-provenance.md +123 -0
- package/assets/lithermes-plugin/skills/lit-hijack/references/clean-room-build.md +128 -0
- package/assets/lithermes-plugin/skills/lit-hijack/references/distil-and-licence.md +128 -0
- package/assets/lithermes-plugin/skills/lit-hijack/references/gap-and-port-design.md +152 -0
- package/assets/lithermes-plugin/skills/lit-hijack/references/parity-and-report.md +131 -0
- package/assets/lithermes-plugin/skills/lit-hijack/scripts/hijack.mjs +995 -0
- package/assets/lithermes-plugin/skills/lit-plan/SKILL.md +1 -0
- package/assets/lithermes-plugin/skills/lit-pptx/SKILL.md +11 -6
- package/assets/lithermes-plugin/skills/lit-pptx/fonts/jetbrains-mono/JetBrainsMono-Bold.ttf +0 -0
- package/assets/lithermes-plugin/skills/lit-pptx/fonts/jetbrains-mono/JetBrainsMono-Regular.ttf +0 -0
- package/assets/lithermes-plugin/skills/lit-pptx/fonts/jetbrains-mono/OFL.txt +93 -0
- package/assets/lithermes-plugin/skills/lit-pptx/fonts/provenance.json +1 -0
- package/assets/lithermes-plugin/skills/lit-pptx/references/anti-slop-checklist.md +3 -0
- package/assets/lithermes-plugin/skills/lit-pptx/references/authoring-guide.md +1 -1
- package/assets/lithermes-plugin/skills/lit-pptx/references/consensus-protocol.md +1 -1
- package/assets/lithermes-plugin/skills/lit-pptx/references/direction-step.md +8 -2
- package/assets/lithermes-plugin/skills/lit-pptx/references/examples/13-engineering-review-computational-brutalism-ko.md +175 -0
- package/assets/lithermes-plugin/skills/lit-pptx/references/examples/14-launch-pitch-neo-brutalism-ko.md +156 -0
- package/assets/lithermes-plugin/skills/lit-pptx/references/examples/15-design-lecture-bauhaus-ko.md +141 -0
- package/assets/lithermes-plugin/skills/lit-pptx/references/examples/16-community-programme-riso-ko.md +160 -0
- package/assets/lithermes-plugin/skills/lit-pptx/references/examples/17-public-data-briefing-newsroom-ko.md +183 -0
- package/assets/lithermes-plugin/skills/lit-pptx/references/layout-families.md +1 -1
- package/assets/lithermes-plugin/skills/lit-pptx/references/tonalities/bauhaus.md +105 -0
- package/assets/lithermes-plugin/skills/lit-pptx/references/tonalities/computational-brutalism.md +111 -0
- package/assets/lithermes-plugin/skills/lit-pptx/references/tonalities/neo-brutalism.md +114 -0
- package/assets/lithermes-plugin/skills/lit-pptx/references/tonalities/newsroom.md +106 -0
- package/assets/lithermes-plugin/skills/lit-pptx/references/tonalities/riso.md +101 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/craft_extras.py +49 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/deck_output.py +4 -2
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/lib/render-pack.js +96 -10
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/lib/template-registry.js +50 -6
- package/assets/lithermes-plugin/skills/lit-pptx/templates/tonalities/bauhaus/pack.yaml +103 -0
- package/assets/lithermes-plugin/skills/lit-pptx/templates/tonalities/computational-brutalism/pack.yaml +99 -0
- package/assets/lithermes-plugin/skills/lit-pptx/templates/tonalities/neo-brutalism/pack.yaml +107 -0
- package/assets/lithermes-plugin/skills/lit-pptx/templates/tonalities/newsroom/pack.yaml +99 -0
- package/assets/lithermes-plugin/skills/lit-pptx/templates/tonalities/riso/pack.yaml +99 -0
- package/assets/lithermes-plugin/skills/lit-recap/SKILL.md +1 -1
- package/assets/lithermes-plugin/skills/lit-schematic/SKILL.md +144 -0
- package/assets/lithermes-plugin/skills/lit-schematic/examples/iso-heat-exchanger/build.mjs +38 -0
- package/assets/lithermes-plugin/skills/lit-schematic/examples/iso-heat-exchanger/scene.mjs +133 -0
- package/assets/lithermes-plugin/skills/lit-schematic/examples/journal-adsorption-rig/build.mjs +87 -0
- package/assets/lithermes-plugin/skills/lit-schematic/examples/pid-dosing-skid/build.mjs +85 -0
- package/assets/lithermes-plugin/skills/lit-schematic/references/cutaway-outputs.md +70 -0
- package/assets/lithermes-plugin/skills/lit-schematic/references/isometric-craft.md +101 -0
- package/assets/lithermes-plugin/skills/lit-schematic/references/journal-figures.md +72 -0
- package/assets/lithermes-plugin/skills/lit-schematic/references/kit-api.md +134 -0
- package/assets/lithermes-plugin/skills/lit-schematic/references/pfd-and-layout.md +53 -0
- package/assets/lithermes-plugin/skills/lit-schematic/references/pid-drafting.md +103 -0
- package/assets/lithermes-plugin/skills/lit-schematic/references/pid-symbols.md +163 -0
- package/assets/lithermes-plugin/skills/lit-schematic/references/verification.md +100 -0
- package/assets/lithermes-plugin/skills/lit-schematic/scripts/doctor.mjs +57 -0
- package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/figure.mjs +81 -0
- package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/fonts.mjs +27 -0
- package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/geom.mjs +113 -0
- package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/interactive.mjs +292 -0
- package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/isa.mjs +115 -0
- package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/iso.mjs +719 -0
- package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/legend-sheet.mjs +162 -0
- package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/pid.mjs +937 -0
- package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/png.mjs +132 -0
- package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/qa-core.mjs +658 -0
- package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/route.mjs +218 -0
- package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/sheet.mjs +890 -0
- package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/svg.mjs +82 -0
- package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/theme.mjs +115 -0
- package/assets/lithermes-plugin/skills/lit-schematic/scripts/motion.mjs +129 -0
- package/assets/lithermes-plugin/skills/lit-schematic/scripts/qa.mjs +92 -0
- package/assets/lithermes-plugin/skills/lit-schematic/scripts/render.mjs +233 -0
- package/assets/lithermes-plugin/skills/lit-schematic/scripts/scaffold.mjs +60 -0
- package/assets/lithermes-plugin/skills/lit-scientific-visualization/SKILL.md +19 -1
- package/assets/lithermes-plugin/skills/lit-typographic-motion/SKILL.md +12 -11
- package/assets/lithermes-plugin/skills/lit-typographic-motion/bin/motion.mjs +56 -2
- package/assets/lithermes-plugin/skills/lit-typographic-motion/bin/runtime.mjs +129 -4
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/THIRD_PARTY_NOTICES +9 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/blender/runner.py +218 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/blender.mjs +154 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/board.mjs +132 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/completion.mjs +48 -5
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/gate.mjs +13 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/house.mjs +44 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/scaffold.mjs +238 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/score.mjs +643 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/sound-dsp.mjs +21 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/sound.mjs +171 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/stage-qa.mjs +23 -3
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/stage.mjs +124 -17
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/styles.mjs +240 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/treatment.mjs +152 -10
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/vendor/three/LICENSE +21 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/vendor/three/addons/environments/RoomEnvironment.js +144 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/vendor/three/addons/geometries/RoundedBoxGeometry.js +155 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/vendor/three/three.module.js +54571 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/recipes/hero-3d/expected.json +67 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/recipes/hero-3d/index.html +139 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/references/depth.md +74 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/references/studio.md +87 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/references/style-bibles.md +9 -2
- package/assets/lithermes-plugin/skills/lit-typographic-motion/references/treatment.md +24 -8
- package/assets/lithermes-plugin/skills/lit-typographic-motion/styles/paper.json +41 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/styles/swiss-signal.json +41 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/styles/terminalcore.json +42 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/styles/tidal.json +41 -0
- package/assets/lithermes-plugin/skills/litresearch/SKILL.md +4 -0
- package/assets/lithermes-plugin/skills/readme-studio/SKILL.md +1 -1
- package/assets/lithermes-plugin/skills/readme-studio/templates/hyperframes/package-lock.json +3 -3
- package/assets/lithermes-plugin/skills/readme-studio/templates/remotion/package-lock.json +3 -3
- package/assets/lithermes-plugin/skills/review-work/SKILL.md +2 -0
- package/assets/lithermes-plugin/skills/start-work/SKILL.md +2 -1
- package/assets/lithermes-plugin/skills/visual-qa/references/complete-contract.md +3 -3
- package/package.json +1 -1
- package/readme-assets/badge-version.svg +1 -1
- package/src/lib/skillPayload.js +1 -1
|
@@ -122,25 +122,79 @@ function packText(slide, S, text, box, o = {}) {
|
|
|
122
122
|
|
|
123
123
|
function packRect(slide, S, box, o = {}) {
|
|
124
124
|
const radius = o.radius || 0;
|
|
125
|
+
// In a pack with hard edges a block of the field (a band, a plate, a rail) carries the border too.
|
|
126
|
+
if (S.pack.shadow && o.fill === "field" && !o.line && box.w >= 24 && box.h >= 24) o = { ...o, line: S.pack["edge-colour"] || "line", lineWidth: S.pack["edge-weight"] };
|
|
125
127
|
slide.addShape(radius ? "roundRect" : "rect", {
|
|
126
128
|
x: IN(box.x), y: IN(box.y), w: IN(box.w), h: IN(box.h),
|
|
127
129
|
...(radius ? { rectRadius: IN(radius) } : {}),
|
|
128
130
|
fill: o.fill ? { color: S.colour(o.fill), transparency: o.alpha || 0 } : { type: "none" },
|
|
129
131
|
line: o.line ? { color: S.colour(o.line), width: o.lineWidth || 0.75 } : { type: "none" },
|
|
132
|
+
// A hard offset shadow: no blur, fully opaque, down and to the right.
|
|
133
|
+
...(o.shadow && S.pack.shadow ? { shadow: { type: "outer", blur: 0, offset: S.pack.shadow.offset, angle: 45, color: S.colour(S.pack.shadow.colour).replace("#", ""), opacity: 1 } } : {}),
|
|
130
134
|
...(o.name ? { objectName: o.name } : {}),
|
|
131
135
|
});
|
|
132
136
|
}
|
|
133
137
|
|
|
134
138
|
/** A surface (card, box, panel) in the pack's edge treatment and radius. */
|
|
135
|
-
function surfaceRect(slide, S, box, fill = "surface") {
|
|
139
|
+
function surfaceRect(slide, S, box, fill = "surface", shadow = false) {
|
|
136
140
|
const edge = S.pack.edge;
|
|
141
|
+
// A shadowed surface is filled, so its shadow never shows through it.
|
|
142
|
+
const packShadow = shadow && S.pack.shadow ? S.pack.shadow : null;
|
|
137
143
|
packRect(slide, S, box, {
|
|
138
|
-
fill: edge === "border" ? null : fill,
|
|
139
|
-
line: edge === "fill" ? null : "line",
|
|
144
|
+
fill: edge === "border" && !packShadow ? null : edge === "border" ? "ground" : fill,
|
|
145
|
+
line: edge === "fill" ? null : S.pack["edge-colour"] || "line",
|
|
146
|
+
lineWidth: S.pack["edge-weight"],
|
|
140
147
|
radius: S.pack.radius,
|
|
148
|
+
shadow: packShadow,
|
|
141
149
|
});
|
|
142
150
|
}
|
|
143
151
|
|
|
152
|
+
/** A pack with a hard shadow draws every box with its border and shadow (filled, `fill` when given). */
|
|
153
|
+
function hardEdge(S, fill) {
|
|
154
|
+
if (!S.pack.shadow) return {};
|
|
155
|
+
return { line: S.pack["edge-colour"] || "line", lineWidth: S.pack["edge-weight"], shadow: S.pack.shadow, ...(fill ? { fill } : {}) };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* The slide's column marks in the top margin on the ground: one tick per column
|
|
160
|
+
* with its number, and the slide index at the right. The marks read on the ground;
|
|
161
|
+
* a band or a filled rail there would cover them.
|
|
162
|
+
*/
|
|
163
|
+
function gridMarks(slide, S, n, total) {
|
|
164
|
+
const g = S.grid;
|
|
165
|
+
const size = S.sizes.source;
|
|
166
|
+
const y = 12;
|
|
167
|
+
for (let a = 1; a <= 12; a++) {
|
|
168
|
+
const x = g.colX(a);
|
|
169
|
+
packRect(slide, S, { x, y, w: 0.75, h: size * 1.2 }, { fill: "line", name: "grid-mark", shadow: false });
|
|
170
|
+
if (a < 11) packText(slide, S, String(a).padStart(2, "0"), { x: x + 4, y, w: g.col - 4, h: size * 1.2 }, { face: "label", size, colour: S.colour("ink-muted"), lineSpacing: 1.2, name: "grid-mark" });
|
|
171
|
+
}
|
|
172
|
+
const index = `[${String(n).padStart(2, "0")}/${String(total).padStart(2, "0")}]`;
|
|
173
|
+
const right = g.span(11, 12);
|
|
174
|
+
packText(slide, S, index, { ...right, y, h: size * 1.2 }, { face: "label", size, colour: S.colour("ink"), align: "right", lineSpacing: 1.2, name: "grid-mark index" });
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Elementary geometry in the primaries, in a region of the page that holds no text: a square in the
|
|
179
|
+
* surface colour, a circle in the accent, a bar in the ink and a triangle in the field, one per cell
|
|
180
|
+
* of a two-by-two grid, so no shape overlaps another or the text.
|
|
181
|
+
*/
|
|
182
|
+
function geometry(slide, S, region) {
|
|
183
|
+
const cw = region.w / 2;
|
|
184
|
+
const ch = region.h / 2;
|
|
185
|
+
const d = Math.min(cw, ch);
|
|
186
|
+
const cell = (i, j) => ({ x: region.x + i * cw, y: region.y + j * ch });
|
|
187
|
+
const shape = (kind, box, fill) => slide.addShape(kind, { x: IN(box.x), y: IN(box.y), w: IN(box.w), h: IN(box.h), fill: { color: S.colour(fill) }, line: { type: "none" } });
|
|
188
|
+
const a = cell(0, 0);
|
|
189
|
+
shape("rect", { x: a.x, y: a.y, w: cw, h: ch }, "accent-tint");
|
|
190
|
+
const b = cell(1, 0);
|
|
191
|
+
shape("ellipse", { x: b.x + (cw - d) / 2, y: b.y + (ch - d) / 2, w: d, h: d }, "accent");
|
|
192
|
+
const c = cell(0, 1);
|
|
193
|
+
shape("rect", { x: c.x + cw * 0.38, y: c.y, w: cw * 0.24, h: ch }, "ink");
|
|
194
|
+
const e = cell(1, 1);
|
|
195
|
+
shape("triangle", { x: e.x, y: e.y + (ch - d), w: cw, h: d }, "field");
|
|
196
|
+
}
|
|
197
|
+
|
|
144
198
|
// ── Content atoms ───────────────────────────────────────────────────────────
|
|
145
199
|
|
|
146
200
|
/** Body paragraphs of a list, in reading order. */
|
|
@@ -1772,7 +1826,8 @@ function drawPlaced(slide, S, p, ctx) {
|
|
|
1772
1826
|
if (p.kind === "kpi") {
|
|
1773
1827
|
p.cards.forEach((card, i) => {
|
|
1774
1828
|
const x = p.x + i * (p.cardW + S.grid.gutter);
|
|
1775
|
-
|
|
1829
|
+
// Card rows stand as surfaces with the pack's edge; on the compact step they cast its shadow.
|
|
1830
|
+
surfaceRect(slide, S, { x, y: p.y, w: p.cardW, h: p.cardH }, "surface", Boolean(S.tok.tight));
|
|
1776
1831
|
const inner = p.cardW - p.pad * 2;
|
|
1777
1832
|
const valueH = p.value * 1.15;
|
|
1778
1833
|
packText(slide, S, plainText(card.value), { x: x + p.pad, y: p.y + p.pad, w: inner, h: valueH },
|
|
@@ -2696,6 +2751,13 @@ function statementDevice(slide, S, f, supportH) {
|
|
|
2696
2751
|
packRect(slide, S, { x: full.x, y: below, w: full.w, h: 0.75 }, { fill: "line" });
|
|
2697
2752
|
return t.colour;
|
|
2698
2753
|
}
|
|
2754
|
+
if (device === "geometry") {
|
|
2755
|
+
// The composition stands beside the sentence when the title leaves room; otherwise the
|
|
2756
|
+
// sentence stands alone and the device reads as open.
|
|
2757
|
+
const right = g.W - (t.x + t.w);
|
|
2758
|
+
if (right >= g.pitch * 3) geometry(slide, S, { x: t.x + t.w + g.gutter, y: t.y, w: right - g.gutter, h: G.ZONE.floor - t.y });
|
|
2759
|
+
return t.colour;
|
|
2760
|
+
}
|
|
2699
2761
|
if (device === "offset") {
|
|
2700
2762
|
// The rail stops a column short of the sentence and at the body floor, so both gaps belong to the grid.
|
|
2701
2763
|
packRect(slide, S, { x: 0, y: 0, w: t.x - g.gutter / 2 - g.pitch, h: G.ZONE.floor }, { fill: S.pack.rail === "field" ? "field" : "surface" });
|
|
@@ -2798,6 +2860,13 @@ const TYPE_COVERS = {
|
|
|
2798
2860
|
if (line) packText(slide, S, line, { ...g.span(1, 6), y: 438, h: 24 }, { size: S.sizes.label, colour: S.colour("ink-muted"), lineSpacing: 1.2 });
|
|
2799
2861
|
packText(slide, S, spec.title, { ...span, y: 144, h }, { face: "display", size, lineSpacing: 1.1, title: true, balance: true, name: "title@cover" });
|
|
2800
2862
|
},
|
|
2863
|
+
geometry(slide, spec, S, meta) {
|
|
2864
|
+
// The composition stands in the free side columns; the words keep the plain frames.
|
|
2865
|
+
const g = S.grid;
|
|
2866
|
+
const side = g.span(10, 12);
|
|
2867
|
+
geometry(slide, S, { x: side.x, y: G.ZONE.top, w: side.w, h: G.ZONE.floor - G.ZONE.top });
|
|
2868
|
+
return TYPE_COVERS.plain(slide, spec, S, meta);
|
|
2869
|
+
},
|
|
2801
2870
|
};
|
|
2802
2871
|
|
|
2803
2872
|
const COVERS = {
|
|
@@ -3257,19 +3326,36 @@ async function renderPack(resolved, templateObj, outputPath) {
|
|
|
3257
3326
|
// Nothing unnamed was drawn (a statement alone): an empty marker carries the family.
|
|
3258
3327
|
slide.addShape("rect", { x: IN(S.grid.margin), y: IN(G.ZONE.top), w: 0, h: 0, fill: { type: "none" }, line: { type: "none" }, objectName: `family@${spec.family}` });
|
|
3259
3328
|
}
|
|
3329
|
+
// The marks read on the ground; a statement page may be drenched in the field, so it goes without.
|
|
3330
|
+
if (spec.kind === "content" && chosenBy[spec.index] !== "statement" && S.deco.has("grid-marks")) gridMarks(slide, S, spec.index + 1, (resolved.slides || []).length);
|
|
3260
3331
|
if (notice) packNotice(slide, S, notice);
|
|
3261
3332
|
}
|
|
3262
3333
|
for (const line of log) console.log(line);
|
|
3263
3334
|
console.log(`Treatments: ${Object.entries(chosenBy).map(([i, t]) => `${Number(i) + 1}:${t}`).join(" ")}`);
|
|
3264
|
-
await writeWithEastAsianFaces(pptx, S.faces.body.font, outputPath);
|
|
3335
|
+
await writeWithEastAsianFaces(pptx, S.faces.body.font, outputPath, Object.values(S.faces).filter((f) => f.ea), Boolean(S.pack.shadow));
|
|
3265
3336
|
return outputPath;
|
|
3266
3337
|
}
|
|
3267
3338
|
|
|
3268
|
-
/**
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3339
|
+
/**
|
|
3340
|
+
* Write the deck with the pack's body face also named for East Asian text in charts and the theme.
|
|
3341
|
+
* Chart text otherwise carries only a Latin face, and a renderer sets Hangul axis labels in
|
|
3342
|
+
* whatever system font it finds. Korean runs are tagged ko-KR on the way (see writeTagged).
|
|
3343
|
+
*/
|
|
3344
|
+
async function writeWithEastAsianFaces(pptx, face, outputPath, latinOnly = [], hardShadows = false) {
|
|
3345
|
+
await shared().writeTagged(pptx, outputPath, (name, xml) => {
|
|
3346
|
+
if (/^ppt\/(charts\/chart\d+|theme\/theme\d+)\.xml$/u.test(name)) {
|
|
3347
|
+
xml = xml.replace(/<a:ea typeface=""\/>/gu, `<a:ea typeface="${face}"/>`).replace(/(<a:latin typeface="([^"]*)"\/>)(?!<a:ea)/gu, `$1<a:ea typeface="$2"/>`);
|
|
3348
|
+
}
|
|
3349
|
+
// A Latin-only face names its East Asian face for the Hangul in its runs.
|
|
3350
|
+
if (/^ppt\/(slides\/slide\d+|charts\/chart\d+)\.xml$/u.test(name)) {
|
|
3351
|
+
for (const f of latinOnly) xml = xml.split(`<a:ea typeface="${f.font}"`).join(`<a:ea typeface="${f.ea}"`);
|
|
3352
|
+
}
|
|
3353
|
+
// pptxgenjs reads a blur of 0 as "unset" and writes its default; a pack's shadow is drawn with none.
|
|
3354
|
+
if (hardShadows && /^ppt\/slides\/slide\d+\.xml$/u.test(name)) {
|
|
3355
|
+
xml = xml.replace(/(<a:outerShdw\b[^>]*?\bblurRad=")\d+"/gu, '$10"');
|
|
3356
|
+
}
|
|
3357
|
+
return xml;
|
|
3358
|
+
});
|
|
3273
3359
|
}
|
|
3274
3360
|
|
|
3275
3361
|
module.exports = { renderPack, PLANS, COVERS, SECTIONS };
|
|
@@ -428,17 +428,28 @@ const FACES = {
|
|
|
428
428
|
"A2Z Medium": { font: "에이투지체 5 Medium", bold: false },
|
|
429
429
|
"A2Z Bold": { font: "에이투지체 7 Bold", bold: false },
|
|
430
430
|
"A2Z Black": { font: "에이투지체 9 Black", bold: false },
|
|
431
|
+
// A Latin-only face: Hangul and other East Asian text in its runs is set in Pretendard.
|
|
432
|
+
"JetBrains Mono Regular": { font: "JetBrains Mono", bold: false, ea: "Pretendard" },
|
|
433
|
+
"JetBrains Mono Bold": { font: "JetBrains Mono", bold: true, ea: "Pretendard" },
|
|
431
434
|
};
|
|
432
|
-
const DECORATIONS = ["accent-rule", "hairline-rule", "header-band", "rail-fill", "colour-field", "caption-band", "column-hairlines", "box-outline", "mark-underline", "numeral"];
|
|
435
|
+
const DECORATIONS = ["accent-rule", "hairline-rule", "header-band", "rail-fill", "colour-field", "caption-band", "column-hairlines", "box-outline", "mark-underline", "numeral", "grid-marks"];
|
|
433
436
|
const SLIDE_ROLES = ["content", "data", "data-takeaway", "sequence", "image", "statement", "reference", "definition"];
|
|
434
437
|
const FILL_POLICIES = ["distribute", "step-up", "anchor-visual", "change-family"];
|
|
435
|
-
// How a pack carries its display slides
|
|
438
|
+
// How a pack carries its display slides: the device on a type-led cover, around a statement,
|
|
439
|
+
// behind a big number and under a closing's next step.
|
|
436
440
|
const DISPLAY_DEVICES = {
|
|
437
|
-
cover: ["plain", "drench", "plate", "rail", "band", "figures", "rules", "numeral"],
|
|
438
|
-
statement: ["open", "drench", "rules", "plate", "offset"],
|
|
441
|
+
cover: ["plain", "drench", "plate", "rail", "band", "figures", "rules", "numeral", "geometry"],
|
|
442
|
+
statement: ["open", "drench", "rules", "plate", "offset", "geometry"],
|
|
439
443
|
number: ["field", "tint", "outline"],
|
|
440
444
|
closing: ["band", "box", "rules"],
|
|
441
445
|
};
|
|
446
|
+
// Allowances a pack may claim from the gate, each a bounded value (see craft_extras.py). The accent
|
|
447
|
+
// limits only widen: four hue families pass every slide by default, so a pack may allow five or six.
|
|
448
|
+
const QA_ALLOWANCES = {
|
|
449
|
+
"accent-families": (v) => Number.isInteger(v) && v >= 5 && v <= 6,
|
|
450
|
+
"display-accent-families": (v) => Number.isInteger(v) && v >= 5 && v <= 6,
|
|
451
|
+
"offset-shadow": (v) => typeof v === "boolean",
|
|
452
|
+
};
|
|
442
453
|
// Contrast pairs every pack must meet (text pairs 4.5:1, large marks 3:1).
|
|
443
454
|
const CONTRAST_PAIRS = [["ink", "ground", 4.5], ["ink", "surface", 4.5], ["ink-muted", "ground", 4.5], ["ink-muted", "surface", 4.5],
|
|
444
455
|
["accent", "ground", 3.0], ["accent-deep", "accent-tint", 4.5], ["ink", "accent-tint", 4.5], ["on-field", "field", 4.5],
|
|
@@ -471,9 +482,12 @@ function validatePack(pack, file) {
|
|
|
471
482
|
for (const key of ["faces", "faces-a2z"]) {
|
|
472
483
|
if (key === "faces-a2z" && pack[key] == null) continue;
|
|
473
484
|
const faces = pack[key] || {};
|
|
485
|
+
// A Latin-only face may set the display roles; body text always stays in a Korean face.
|
|
474
486
|
for (const role of FACE_KEYS) {
|
|
475
|
-
|
|
487
|
+
const own = key === "faces-a2z" || /^Pretendard /u.test(faces[role]) || (role !== "body" && FACES[faces[role]] && FACES[faces[role]].ea);
|
|
488
|
+
need(FACES[faces[role]] && own, `${key}.${role} must name a bundled face${key === "faces-a2z" ? "" : role === "body" ? " (Pretendard Regular or Bold)" : " (Pretendard Regular or Bold, or JetBrains Mono Regular or Bold)"}`);
|
|
476
489
|
}
|
|
490
|
+
need(!(FACES[faces.body] && FACES[faces.body].ea), `${key}.body must be a face that sets Hangul`);
|
|
477
491
|
const distinct = new Set(FACE_KEYS.map((r) => faces[r]));
|
|
478
492
|
need(distinct.size <= 3, `${key} uses ${distinct.size} faces; at most 3`);
|
|
479
493
|
need(new Set([...distinct].map((f) => String(f).split(" ")[0])).size <= 2, `${key} mixes more than two families`);
|
|
@@ -495,10 +509,32 @@ function validatePack(pack, file) {
|
|
|
495
509
|
}
|
|
496
510
|
need(["presented", "reading"].includes(pack.ramp), "ramp must be presented or reading");
|
|
497
511
|
need(typeof pack.hero === "boolean", "hero must be true or false");
|
|
512
|
+
// A report pack reads at its density step; a bold pack (a pitch, a launch, a campaign) may set presented type.
|
|
513
|
+
// Any pack may take the hero step on its cover and statements. Either way the words stay in the slide grid's
|
|
514
|
+
// zones: the register and the hero step change size, never place.
|
|
515
|
+
const register = pack.register == null ? "report" : pack.register;
|
|
516
|
+
need(["report", "bold"].includes(register), "register must be report or bold");
|
|
517
|
+
need(register === "bold" || pack.ramp === "reading", "presented type needs register: bold; a report pack keeps ramp: reading");
|
|
498
518
|
need(Number.isInteger(pack.density) && pack.density >= 1 && pack.density <= 10, "density must be an integer 1-10");
|
|
499
519
|
need(Number.isInteger(pack.variance) && pack.variance >= 4 && pack.variance <= 10, "variance must be an integer 4-10");
|
|
500
520
|
need(pack.radius === 0 || pack.radius === 6, "radius must be 0 or 6");
|
|
501
521
|
need(["border", "fill", "fill+border"].includes(pack.edge), "edge must be border, fill or fill+border");
|
|
522
|
+
// A heavier border and a hard offset shadow (zero blur) under surfaces; the shadow needs the border.
|
|
523
|
+
const weight = pack["edge-weight"];
|
|
524
|
+
need(weight == null || (typeof weight === "number" && weight >= 0.5 && weight <= 4), "edge-weight must be 0.5-4 pt");
|
|
525
|
+
const shadow = pack.shadow;
|
|
526
|
+
if (shadow != null) {
|
|
527
|
+
need(typeof shadow === "object" && typeof shadow.offset === "number" && shadow.offset >= 3 && shadow.offset <= 10, "shadow.offset must be 3-10 pt");
|
|
528
|
+
need(shadow && PALETTE_ROLES.includes(shadow.colour), "shadow.colour must name a palette role");
|
|
529
|
+
need(pack.edge !== "fill", "a shadow needs a bordered edge (border or fill+border)");
|
|
530
|
+
}
|
|
531
|
+
need(pack["edge-colour"] == null || PALETTE_ROLES.includes(pack["edge-colour"]), "edge-colour must name a palette role");
|
|
532
|
+
// What the gate allows this pack beyond the default craft floor (read by craft_extras.py).
|
|
533
|
+
const qa = pack.qa || {};
|
|
534
|
+
need(typeof qa === "object" && !Array.isArray(qa), "qa must be a map");
|
|
535
|
+
for (const k of Object.keys(qa)) need(QA_ALLOWANCES[k], `unknown qa allowance "${k}" (known: ${Object.keys(QA_ALLOWANCES).join(", ")})`);
|
|
536
|
+
for (const [k, ok] of Object.entries(QA_ALLOWANCES)) if (qa[k] != null) need(ok(qa[k]), `qa.${k} is out of range`);
|
|
537
|
+
need(!qa["offset-shadow"] || shadow != null, "qa.offset-shadow needs a shadow");
|
|
502
538
|
const treatments = isList(pack.treatments) ? pack.treatments : [];
|
|
503
539
|
need(treatments.length >= 3 && treatments.length <= 5, "treatments must list 3-5 title treatments");
|
|
504
540
|
for (const t of treatments) need(grid.TREATMENTS.includes(t), `unknown treatment "${t}" (known: ${grid.TREATMENTS.join(", ")})`);
|
|
@@ -512,6 +548,10 @@ function validatePack(pack, file) {
|
|
|
512
548
|
need(treatments.includes(t) && grid.FAMILIES[f] && grid.FAMILIES[f].allow.includes(t), `structure.${f} must be a treatment of the pack that the family allows`);
|
|
513
549
|
}
|
|
514
550
|
for (const d of pack.decoration || []) need(DECORATIONS.includes(d), `unknown decoration "${d}"`);
|
|
551
|
+
// Grid marks sit in the top margin on the ground: a band or a filled rail there would cover them.
|
|
552
|
+
if ((pack.decoration || []).includes("grid-marks")) {
|
|
553
|
+
need(!treatments.includes("band") && !(pack.decoration || []).includes("rail-fill"), "grid-marks needs the top margin on the ground (no band treatment, no rail-fill)");
|
|
554
|
+
}
|
|
515
555
|
need(pack.rail == null || ["surface", "field"].includes(pack.rail), "rail must be surface or field");
|
|
516
556
|
const display = pack.display || {};
|
|
517
557
|
need(typeof display === "object" && !Array.isArray(display), "display must be a map");
|
|
@@ -630,7 +670,11 @@ function loadTonality(id, options = {}) {
|
|
|
630
670
|
if (!pack.canvas.includes(canvas)) {
|
|
631
671
|
throw new Error(`Tonality "${pack.id}" supports ${pack.canvas.join(", ")}, not canvas ${canvas}`);
|
|
632
672
|
}
|
|
633
|
-
|
|
673
|
+
// Only a bold register sets presented type; a report pack reads at its density step.
|
|
674
|
+
const tok = grid.densityTokens(density, pack.register === "bold" ? pack.ramp : "reading");
|
|
675
|
+
if ((pack.decoration || []).includes("grid-marks") && (pack.treatments.includes("band") || (pack.decoration || []).includes("rail-fill"))) {
|
|
676
|
+
throw new Error(`grid-marks needs the top margin on the ground (no band treatment, no rail-fill); tonality "${pack.id}" has one`);
|
|
677
|
+
}
|
|
634
678
|
const g = grid.makeGrid(canvas, tok.grid);
|
|
635
679
|
// Pretendard by default; the A2Z map only when the source asks for it (`faces: a2z`).
|
|
636
680
|
const wantsA2z = String(options.faces || "").toLowerCase() === "a2z" && pack["faces-a2z"];
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Bauhaus: primary colours and elementary geometry, kept to the display slides. The cover and the
|
|
2
|
+
# statements carry a composition of a square, a circle, a bar and a triangle; content slides stay
|
|
3
|
+
# quiet, on an off-white ground with black type and one red accent. Wrong for data-heavy business
|
|
4
|
+
# reviews, finance, public-sector reports and sombre topics.
|
|
5
|
+
id: bauhaus
|
|
6
|
+
name: Bauhaus
|
|
7
|
+
version: "1.0.0"
|
|
8
|
+
intent: "Design, architecture and culture lectures: primary colours and geometry on the display slides."
|
|
9
|
+
canvas: ["16:9", "4:3"]
|
|
10
|
+
|
|
11
|
+
# Pretendard by default; the A2Z map below applies only when the source asks (faces: a2z).
|
|
12
|
+
faces:
|
|
13
|
+
display: Pretendard Bold
|
|
14
|
+
title: Pretendard Bold
|
|
15
|
+
body: Pretendard Regular
|
|
16
|
+
label: Pretendard Bold
|
|
17
|
+
numeral: Pretendard Bold
|
|
18
|
+
faces-a2z:
|
|
19
|
+
display: A2Z Black
|
|
20
|
+
title: A2Z Black
|
|
21
|
+
body: Pretendard Regular
|
|
22
|
+
label: Pretendard Bold
|
|
23
|
+
numeral: A2Z Black
|
|
24
|
+
|
|
25
|
+
palette:
|
|
26
|
+
ground: "#F4F1EA"
|
|
27
|
+
surface: "#E8E3D6"
|
|
28
|
+
ink: "#141414"
|
|
29
|
+
ink-muted: "#4A4740"
|
|
30
|
+
line: "#141414"
|
|
31
|
+
accent: "#C8261C"
|
|
32
|
+
accent-deep: "#7A140E"
|
|
33
|
+
# The yellow of the geometry: the square on a display slide, the notice and a highlighted table row.
|
|
34
|
+
accent-tint: "#F2C230"
|
|
35
|
+
field: "#1F3C99"
|
|
36
|
+
on-field: "#FFFFFF"
|
|
37
|
+
positive: "#1E6B3A"
|
|
38
|
+
# The accent is red, so a loss keeps the ink colour and carries its ▼ sign instead.
|
|
39
|
+
negative: "#141414"
|
|
40
|
+
# Red, blue, black, then an ochre: the geometry's yellow darkened so a bar holds 3:1 on the ground.
|
|
41
|
+
series: ["#C8261C", "#1F3C99", "#141414", "#9E7700"]
|
|
42
|
+
|
|
43
|
+
ramp: reading
|
|
44
|
+
hero: true
|
|
45
|
+
type-voice:
|
|
46
|
+
title-tracking: -1
|
|
47
|
+
display-tracking: -2
|
|
48
|
+
|
|
49
|
+
density: 10
|
|
50
|
+
variance: 7
|
|
51
|
+
radius: 0
|
|
52
|
+
edge: fill
|
|
53
|
+
|
|
54
|
+
treatments: [top-rule, side-rail, kicker-numeral, statement, bottom-anchor]
|
|
55
|
+
role-defaults:
|
|
56
|
+
content: top-rule
|
|
57
|
+
data: top-rule
|
|
58
|
+
data-takeaway: side-rail
|
|
59
|
+
sequence: kicker-numeral
|
|
60
|
+
image: bottom-anchor
|
|
61
|
+
statement: statement
|
|
62
|
+
reference: top-rule
|
|
63
|
+
definition: side-rail
|
|
64
|
+
|
|
65
|
+
decoration: [accent-rule, numeral, colour-field]
|
|
66
|
+
layout-families: [asymmetric-feature, big-number, image-split, text-two-column, comparison, process, step-diagram, timeline, chart-insight, table-insight, kpi-row, quote, statement, agenda]
|
|
67
|
+
# Display slides: the device a type-led cover, a statement, a big number and a closing's next step
|
|
68
|
+
# are drawn with (see references/layout-families.md, "Display slides"). Geometry lives here only.
|
|
69
|
+
display:
|
|
70
|
+
cover: geometry
|
|
71
|
+
statement: geometry
|
|
72
|
+
number: field
|
|
73
|
+
closing: rules
|
|
74
|
+
covers: [cover-typographic, cover-split-field, cover-numeral]
|
|
75
|
+
sections: [section-field, section-numeral]
|
|
76
|
+
closings: [closing-ask, closing-summary-list, closing-statement]
|
|
77
|
+
|
|
78
|
+
table:
|
|
79
|
+
header: none
|
|
80
|
+
header-ink: ink
|
|
81
|
+
rules: header-rule
|
|
82
|
+
banding: none
|
|
83
|
+
totals: bold
|
|
84
|
+
chart:
|
|
85
|
+
gridlines: none
|
|
86
|
+
labels: direct
|
|
87
|
+
highlight: accent-on-muted
|
|
88
|
+
image:
|
|
89
|
+
frame: none
|
|
90
|
+
|
|
91
|
+
fill-order: [change-family, step-up, anchor-visual, distribute]
|
|
92
|
+
# What the gate allows this pack beyond the default craft floor (see references/anti-slop-checklist.md).
|
|
93
|
+
# The big-number slide legitimately shows three families (blue panel, red bullets, yellow notice tag),
|
|
94
|
+
# so OF-101 fails this pack at six, not three.
|
|
95
|
+
qa:
|
|
96
|
+
accent-families: 5
|
|
97
|
+
# The composition on a display slide sets red, blue and yellow beside one another; content slides keep one accent.
|
|
98
|
+
avoid:
|
|
99
|
+
- geometry on content slides (it belongs to the cover and the statements)
|
|
100
|
+
- a circle, square or triangle used as a bullet or an icon
|
|
101
|
+
- more than one accent colour on a content slide
|
|
102
|
+
- yellow text on the off-white ground
|
|
103
|
+
- this look for grief, safety or financial-loss topics
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Computational Brutalism: retro-futurist computing with its structure left in view. A monospaced
|
|
2
|
+
# Latin face for titles, labels and figures, the twelve-column grid marked in the top margin, ruled
|
|
3
|
+
# tables, a black terminal field with phosphor text and one electric-blue signal. Wrong for boards,
|
|
4
|
+
# finance or public-sector reports and for long Korean reading: the mono face tires over paragraphs.
|
|
5
|
+
id: computational-brutalism
|
|
6
|
+
name: Computational Brutalism
|
|
7
|
+
version: "1.0.0"
|
|
8
|
+
intent: "Engineering reviews and developer launches: the grid, the numbers and the system shown."
|
|
9
|
+
canvas: ["16:9", "4:3"]
|
|
10
|
+
|
|
11
|
+
# JetBrains Mono sets the Latin of titles, labels and figures; Hangul in those runs is set in
|
|
12
|
+
# Pretendard. Body text stays Pretendard. There is no A2Z map: the mono face is the look.
|
|
13
|
+
faces:
|
|
14
|
+
display: JetBrains Mono Bold
|
|
15
|
+
title: JetBrains Mono Bold
|
|
16
|
+
body: Pretendard Regular
|
|
17
|
+
label: JetBrains Mono Regular
|
|
18
|
+
numeral: JetBrains Mono Bold
|
|
19
|
+
|
|
20
|
+
palette:
|
|
21
|
+
ground: "#EEEDE7"
|
|
22
|
+
surface: "#E2E1D9"
|
|
23
|
+
ink: "#111111"
|
|
24
|
+
ink-muted: "#4D4C47"
|
|
25
|
+
line: "#9A988F"
|
|
26
|
+
accent: "#1F43E0"
|
|
27
|
+
accent-deep: "#14267A"
|
|
28
|
+
accent-tint: "#D9DEF2"
|
|
29
|
+
# The terminal: a black field with phosphor-green text.
|
|
30
|
+
field: "#111111"
|
|
31
|
+
on-field: "#8CF5A6"
|
|
32
|
+
positive: "#1C6B35"
|
|
33
|
+
negative: "#B3261E"
|
|
34
|
+
series: ["#1F43E0", "#111111", "#7A786F"]
|
|
35
|
+
|
|
36
|
+
ramp: reading
|
|
37
|
+
hero: true
|
|
38
|
+
type-voice:
|
|
39
|
+
title-tracking: 0
|
|
40
|
+
display-tracking: -1
|
|
41
|
+
|
|
42
|
+
density: 10
|
|
43
|
+
variance: 7
|
|
44
|
+
radius: 0
|
|
45
|
+
edge: border
|
|
46
|
+
edge-weight: 1
|
|
47
|
+
edge-colour: ink
|
|
48
|
+
|
|
49
|
+
treatments: [top-rule, top-plain-large, side-rail, bottom-anchor, statement]
|
|
50
|
+
role-defaults:
|
|
51
|
+
content: top-rule
|
|
52
|
+
data: top-rule
|
|
53
|
+
data-takeaway: bottom-anchor
|
|
54
|
+
sequence: top-rule
|
|
55
|
+
image: bottom-anchor
|
|
56
|
+
statement: statement
|
|
57
|
+
reference: top-rule
|
|
58
|
+
definition: side-rail
|
|
59
|
+
# A family's own title in this pack: a chart under a ruled title, a table read up to its title, a
|
|
60
|
+
# comparison set as a spec sheet beside its rail, a sequence under a large mono headline.
|
|
61
|
+
structure:
|
|
62
|
+
chart-insight: top-rule
|
|
63
|
+
table-insight: bottom-anchor
|
|
64
|
+
comparison: side-rail
|
|
65
|
+
step-diagram: top-plain-large
|
|
66
|
+
# The grid and its numbers are the decoration; nothing is filled for ornament.
|
|
67
|
+
decoration: [hairline-rule, column-hairlines, box-outline, grid-marks, numeral]
|
|
68
|
+
layout-families: [dashboard-grid, kpi-row, chart-insight, full-chart, table-insight, ledger-table, method, step-diagram, matrix-2x2, comparison, text-two-column, references-appendix, quote, statement]
|
|
69
|
+
# Display slides: the device a type-led cover, a statement, a big number and a closing's next step
|
|
70
|
+
# are drawn with (see references/layout-families.md, "Display slides").
|
|
71
|
+
display:
|
|
72
|
+
cover: drench
|
|
73
|
+
statement: drench
|
|
74
|
+
number: outline
|
|
75
|
+
closing: box
|
|
76
|
+
covers: [cover-typographic, cover-index, cover-figures]
|
|
77
|
+
sections: [section-numeral, section-rule]
|
|
78
|
+
closings: [closing-decision-box, closing-ask, closing-summary-list]
|
|
79
|
+
|
|
80
|
+
table:
|
|
81
|
+
header: none
|
|
82
|
+
header-ink: ink
|
|
83
|
+
rules: grid
|
|
84
|
+
banding: none
|
|
85
|
+
totals: bold
|
|
86
|
+
protagonist: accent-tint
|
|
87
|
+
chart:
|
|
88
|
+
gridlines: hairline
|
|
89
|
+
labels: direct
|
|
90
|
+
highlight: accent-on-muted
|
|
91
|
+
image:
|
|
92
|
+
frame: hairline
|
|
93
|
+
|
|
94
|
+
fill-order: [change-family, distribute, anchor-visual, step-up]
|
|
95
|
+
avoid:
|
|
96
|
+
- mono body paragraphs (body text stays Pretendard)
|
|
97
|
+
- the accent as decoration (it marks the protagonist number or series)
|
|
98
|
+
- rounded corners, shadows, gradients
|
|
99
|
+
- a green other than the phosphor text on the terminal field
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Neo-Brutalism: loud on purpose. Thick black borders, hard offset shadows with no blur, flat
|
|
2
|
+
# saturated fills (yellow cards, a pink accent, a blue band) and heavy type on a warm cream ground.
|
|
3
|
+
# Wrong for formal reports, academic talks, sensitive topics, dense reviews and decks under a
|
|
4
|
+
# corporate brand guide.
|
|
5
|
+
id: neo-brutalism
|
|
6
|
+
name: Neo-Brutalism
|
|
7
|
+
version: "1.0.0"
|
|
8
|
+
intent: "Pitches, launches and demo days: bold fills, black borders, hard shadows."
|
|
9
|
+
canvas: ["16:9", "4:3"]
|
|
10
|
+
|
|
11
|
+
# Pretendard by default; the A2Z map below applies only when the source asks (faces: a2z).
|
|
12
|
+
faces:
|
|
13
|
+
display: Pretendard Bold
|
|
14
|
+
title: Pretendard Bold
|
|
15
|
+
body: Pretendard Regular
|
|
16
|
+
label: Pretendard Bold
|
|
17
|
+
numeral: Pretendard Bold
|
|
18
|
+
faces-a2z:
|
|
19
|
+
display: A2Z Black
|
|
20
|
+
title: A2Z Black
|
|
21
|
+
body: Pretendard Regular
|
|
22
|
+
label: Pretendard Bold
|
|
23
|
+
numeral: A2Z Black
|
|
24
|
+
|
|
25
|
+
palette:
|
|
26
|
+
ground: "#FFF5E1"
|
|
27
|
+
surface: "#FFD43B"
|
|
28
|
+
ink: "#111111"
|
|
29
|
+
ink-muted: "#3A3A3A"
|
|
30
|
+
line: "#111111"
|
|
31
|
+
accent: "#D81B5C"
|
|
32
|
+
accent-deep: "#6B0F2E"
|
|
33
|
+
accent-tint: "#FFC9DA"
|
|
34
|
+
field: "#2F4BFF"
|
|
35
|
+
on-field: "#FFFFFF"
|
|
36
|
+
positive: "#137A43"
|
|
37
|
+
# The accent is pink-red, so a loss keeps the ink colour and carries its ▼ sign instead.
|
|
38
|
+
negative: "#111111"
|
|
39
|
+
series: ["#D81B5C", "#2F4BFF", "#111111", "#137A43"]
|
|
40
|
+
|
|
41
|
+
# A bold register: presented type and the hero step, filling the same zones every pack uses.
|
|
42
|
+
register: bold
|
|
43
|
+
ramp: presented
|
|
44
|
+
hero: true
|
|
45
|
+
type-voice:
|
|
46
|
+
title-tracking: -2
|
|
47
|
+
display-tracking: -3
|
|
48
|
+
|
|
49
|
+
density: 10
|
|
50
|
+
variance: 7
|
|
51
|
+
radius: 0
|
|
52
|
+
# Every surface: a filled card with a 2.5 pt black border and a 6 pt black shadow, no blur.
|
|
53
|
+
edge: fill+border
|
|
54
|
+
edge-weight: 2.5
|
|
55
|
+
edge-colour: ink
|
|
56
|
+
shadow:
|
|
57
|
+
offset: 6
|
|
58
|
+
colour: ink
|
|
59
|
+
|
|
60
|
+
treatments: [top-plain-large, band, kicker-numeral, statement, bottom-anchor]
|
|
61
|
+
role-defaults:
|
|
62
|
+
content: top-plain-large
|
|
63
|
+
data: band
|
|
64
|
+
data-takeaway: top-plain-large
|
|
65
|
+
sequence: band
|
|
66
|
+
image: bottom-anchor
|
|
67
|
+
statement: statement
|
|
68
|
+
reference: band
|
|
69
|
+
definition: band
|
|
70
|
+
|
|
71
|
+
decoration: [colour-field, numeral]
|
|
72
|
+
layout-families: [big-number, kpi-row, comparison, process, step-diagram, chart-insight, table-insight, image-split, summary-box-list, agenda, quote, statement]
|
|
73
|
+
# Display slides: the device a type-led cover, a statement, a big number and a closing's next step
|
|
74
|
+
# are drawn with (see references/layout-families.md, "Display slides").
|
|
75
|
+
display:
|
|
76
|
+
cover: plate
|
|
77
|
+
statement: drench
|
|
78
|
+
number: field
|
|
79
|
+
closing: box
|
|
80
|
+
covers: [cover-typographic, cover-split-field, cover-numeral]
|
|
81
|
+
sections: [section-field, section-numeral]
|
|
82
|
+
closings: [closing-ask, closing-decision-box, closing-statement]
|
|
83
|
+
|
|
84
|
+
table:
|
|
85
|
+
header: surface
|
|
86
|
+
header-ink: ink
|
|
87
|
+
rules: grid
|
|
88
|
+
banding: none
|
|
89
|
+
totals: bold
|
|
90
|
+
protagonist: accent-tint
|
|
91
|
+
chart:
|
|
92
|
+
gridlines: none
|
|
93
|
+
labels: direct
|
|
94
|
+
highlight: series-order
|
|
95
|
+
image:
|
|
96
|
+
frame: hairline
|
|
97
|
+
|
|
98
|
+
fill-order: [step-up, change-family, anchor-visual, distribute]
|
|
99
|
+
# What the gate allows this pack beyond the default craft floor (see references/anti-slop-checklist.md).
|
|
100
|
+
qa:
|
|
101
|
+
offset-shadow: true
|
|
102
|
+
avoid:
|
|
103
|
+
- blurred or soft shadows (the shadow is a hard offset or nothing)
|
|
104
|
+
- thin hairlines beside the 2.5 pt borders
|
|
105
|
+
- more than three fill colours on one slide
|
|
106
|
+
- muted grey text on the yellow surface below 4.5:1
|
|
107
|
+
- this look for grief, safety, HR or financial-loss topics
|