@taloswork/ose-shared 0.1.5 → 0.1.7
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/package.json +3 -3
- package/skills/document/SKILL.md +32 -17
- package/skills/document/art-directions/base.css +23 -0
- package/skills/document/art-directions/cinematic-depth.css +6 -0
- package/skills/document/art-directions/collage-paper.css +8 -0
- package/skills/document/art-directions/editorial-cut.css +8 -0
- package/skills/document/art-directions/geometric-pop.css +9 -0
- package/skills/document/art-directions/gradient-mesh.css +6 -0
- package/skills/document/art-directions/illustrated-doodle.css +8 -0
- package/skills/document/art-directions/luxury-ornament.css +6 -0
- package/skills/document/art-directions/maximalist-blocks.css +9 -0
- package/skills/document/art-directions/technical-grid.css +6 -0
- package/skills/document/assets/fonts/fonts.json +2 -2
- package/skills/document/bin/deck-build.cjs +266 -10
- package/skills/document/bin/doc-convert.cjs +66 -28
- package/skills/document/bin/doc-gen.cjs +6 -4
- package/skills/document/bin/html2pptx.cjs +243 -22
- package/skills/document/catalog.json +11 -0
- package/skills/document/components/base.css +45 -0
- package/skills/document/components/profiles/clean.css +2 -0
- package/skills/document/components/profiles/editorial.css +3 -0
- package/skills/document/components/profiles/glass.css +2 -0
- package/skills/document/components/profiles/luxury.css +3 -0
- package/skills/document/components/profiles/organic.css +2 -0
- package/skills/document/components/profiles/poster.css +3 -0
- package/skills/document/content-pipeline.md +55 -48
- package/skills/document/deck-design.md +24 -15
- package/skills/document/layouts/README.md +33 -12
- package/skills/document/layouts/business-model.tpl +6 -0
- package/skills/document/layouts/customer-proof.tpl +6 -0
- package/skills/document/layouts/funding-ask.tpl +5 -0
- package/skills/document/layouts/market-rings.tpl +5 -0
- package/skills/document/layouts/pitch-problem.tpl +6 -0
- package/skills/document/layouts/pitch-solution.tpl +5 -0
- package/skills/document/layouts/pricing-tiers.tpl +5 -0
- package/skills/document/layouts/product-device.tpl +6 -0
- package/skills/document/layouts/profiles.json +24 -0
- package/skills/document/layouts/slots.json +1 -1
- package/skills/document/layouts/team-founders.tpl +5 -0
- package/skills/document/layouts/traction-milestones.tpl +6 -0
- package/skills/document/media-styles/cinematic.css +2 -0
- package/skills/document/media-styles/clean-product.css +2 -0
- package/skills/document/media-styles/cutout-collage.css +3 -0
- package/skills/document/media-styles/device-stage.css +3 -0
- package/skills/document/media-styles/editorial-photo.css +3 -0
- package/skills/document/media-styles/illustrated.css +2 -0
- package/skills/document/media-styles/spatial-3d.css +3 -0
- package/skills/document/motion/mckinsey-photo.json +22 -0
- package/skills/document/motion/prismatic-3d.json +31 -0
- package/skills/document/packs/README.md +7 -3
- package/skills/document/packs/mckinsey-photo/backdrop.html +6 -0
- package/skills/document/packs/mckinsey-photo/layouts/cover-image.tpl +5 -0
- package/skills/document/packs/mckinsey-photo/layouts/cover.tpl +5 -0
- package/skills/document/packs/mckinsey-photo/layouts/image-left.tpl +5 -0
- package/skills/document/packs/mckinsey-photo/layouts/numbered-brief.tpl +5 -0
- package/skills/document/packs/mckinsey-photo/pack.css +27 -0
- package/skills/document/packs/prismatic-3d/backdrop.html +4 -0
- package/skills/document/packs/prismatic-3d/layouts/big-stat.tpl +6 -0
- package/skills/document/packs/prismatic-3d/layouts/cover.tpl +9 -0
- package/skills/document/packs/prismatic-3d/layouts/section-image.tpl +6 -0
- package/skills/document/packs/prismatic-3d/pack.css +28 -0
- package/skills/document/recipes/agency-pitch.json +13 -0
- package/skills/document/recipes/product-launch.json +13 -0
- package/skills/document/recipes/startup-fundraising.json +19 -0
- package/skills/document/styles/README.md +13 -6
- package/skills/document/styles/_contract-defaults.css +1 -1
- package/skills/document/styles/_samples/_groups/biz-premium.webp +0 -0
- package/skills/document/styles/_samples/_groups/creative.webp +0 -0
- package/skills/document/styles/_samples/_groups/editorial.webp +0 -0
- package/skills/document/styles/_samples/_groups/minimal.webp +0 -0
- package/skills/document/styles/_samples/_groups/natural.webp +0 -0
- package/skills/document/styles/_samples/_groups/tech-future.webp +0 -0
- package/skills/document/styles/_samples/bistro-warm.webp +0 -0
- package/skills/document/styles/_samples/board-brief.webp +0 -0
- package/skills/document/styles/_samples/bold-clash.webp +0 -0
- package/skills/document/styles/_samples/campus-teal.webp +0 -0
- package/skills/document/styles/_samples/clinic-care.webp +0 -0
- package/skills/document/styles/_samples/dark-glass.webp +0 -0
- package/skills/document/styles/_samples/gov-brief.webp +0 -0
- package/skills/document/styles/_samples/grid-tech.webp +0 -0
- package/skills/document/styles/_samples/legal-slate.webp +0 -0
- package/skills/document/styles/_samples/mckinsey-photo.webp +0 -0
- package/skills/document/styles/_samples/memphis.webp +0 -0
- package/skills/document/styles/_samples/neon-cyber.webp +0 -0
- package/skills/document/styles/_samples/organic-earth.webp +0 -0
- package/skills/document/styles/_samples/pastel-saas.webp +0 -0
- package/skills/document/styles/_samples/portfolio-noir.webp +0 -0
- package/skills/document/styles/_samples/press-room.webp +0 -0
- package/skills/document/styles/_samples/prismatic-3d.webp +0 -0
- package/skills/document/styles/_samples/retro-press.webp +0 -0
- package/skills/document/styles/_samples/sport-arena.webp +0 -0
- package/skills/document/styles/_samples/wedding-blush.webp +0 -0
- package/skills/document/styles/dark-glass/backdrop.html +7 -3
- package/skills/document/styles/dark-glass/skin.css +1 -0
- package/skills/document/styles/portfolio-noir/skin.css +3 -0
- package/skills/document/theme-system.json +68 -0
- package/skills/document/theme-system.md +101 -0
- package/skills/{image-compose → image-layout}/SKILL.md +17 -2
- package/skills/{image-compose → image-layout}/bin/html2img.cjs +2 -2
- /package/skills/{image-compose → image-layout}/LICENSE.txt +0 -0
|
@@ -69412,7 +69412,7 @@ var require_dir_writer = __commonJS({
|
|
|
69412
69412
|
module2.exports = DirWriter;
|
|
69413
69413
|
var Writer = require_writer();
|
|
69414
69414
|
var inherits2 = require_inherits();
|
|
69415
|
-
var
|
|
69415
|
+
var mkdir2 = require_mkdirp();
|
|
69416
69416
|
var path = require("path");
|
|
69417
69417
|
var collect = require_collect();
|
|
69418
69418
|
inherits2(DirWriter, Writer);
|
|
@@ -69428,7 +69428,7 @@ var require_dir_writer = __commonJS({
|
|
|
69428
69428
|
}
|
|
69429
69429
|
DirWriter.prototype._create = function() {
|
|
69430
69430
|
var self2 = this;
|
|
69431
|
-
|
|
69431
|
+
mkdir2(self2._path, Writer.dirmode, function(er) {
|
|
69432
69432
|
if (er) return self2.error(er);
|
|
69433
69433
|
self2.ready = true;
|
|
69434
69434
|
self2.emit("ready");
|
|
@@ -69773,7 +69773,7 @@ var require_writer = __commonJS({
|
|
|
69773
69773
|
var fs = require_graceful_fs();
|
|
69774
69774
|
var inherits2 = require_inherits();
|
|
69775
69775
|
var rimraf = require_rimraf();
|
|
69776
|
-
var
|
|
69776
|
+
var mkdir2 = require_mkdirp();
|
|
69777
69777
|
var path = require("path");
|
|
69778
69778
|
var umask = process.platform === "win32" ? 0 : process.umask();
|
|
69779
69779
|
var getType = require_get_type();
|
|
@@ -69879,7 +69879,7 @@ var require_writer = __commonJS({
|
|
|
69879
69879
|
}
|
|
69880
69880
|
};
|
|
69881
69881
|
function create(self2) {
|
|
69882
|
-
|
|
69882
|
+
mkdir2(path.dirname(self2._path), Writer.dirmode, function(er, made) {
|
|
69883
69883
|
if (er) return self2.error(er);
|
|
69884
69884
|
self2._madeDir = made;
|
|
69885
69885
|
return self2._create();
|
|
@@ -147660,6 +147660,7 @@ async function imagesToPptx(imagesBase64Png) {
|
|
|
147660
147660
|
}
|
|
147661
147661
|
|
|
147662
147662
|
// packages/core/dist/document/html-pptx-walker.js
|
|
147663
|
+
var DOCUMENT_CAPTURE_DENSITY = 2;
|
|
147663
147664
|
var LAYOUT_WALKER_JS = `
|
|
147664
147665
|
(() => {
|
|
147665
147666
|
const sections = [...document.querySelectorAll("section.slide")];
|
|
@@ -147822,8 +147823,14 @@ var LAYOUT_WALKER_JS = `
|
|
|
147822
147823
|
})()
|
|
147823
147824
|
`;
|
|
147824
147825
|
|
|
147826
|
+
// packages/core/dist/shared/async.js
|
|
147827
|
+
function sleep(ms) {
|
|
147828
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
147829
|
+
}
|
|
147830
|
+
|
|
147825
147831
|
// packages/core/dist/document/html-pptx-headless.js
|
|
147826
|
-
var
|
|
147832
|
+
var configuredSettleMs = Number(process.env.TALOS_CAPTURE_SETTLE_MS ?? 16);
|
|
147833
|
+
var CAPTURE_SETTLE_MS = Number.isFinite(configuredSettleMs) ? Math.max(0, Math.min(250, configuredSettleMs)) : 16;
|
|
147827
147834
|
var pngDataUri = (bytes) => "data:image/png;base64," + Buffer.from(bytes).toString("base64");
|
|
147828
147835
|
var isolateSlide = (si) => `new Promise((done) => { const secs = document.querySelectorAll("section.slide"); secs.forEach((s, j) => { s.style.display = j === ${si} ? "" : "none"; }); window.scrollTo(0, 0); requestAnimationFrame(() => requestAnimationFrame(() => done(true))); })`;
|
|
147829
147836
|
var showAllSlides = `document.querySelectorAll("section.slide").forEach((s) => { s.style.display = ""; }); document.getElementById("__talos_hide")?.remove(); true`;
|
|
@@ -147838,7 +147845,7 @@ async function snapshotHeadless(page, opts = {}) {
|
|
|
147838
147845
|
await page.evaluate(`(() => { document.querySelectorAll("*").forEach((el) => { const bake = getComputedStyle(el).getPropertyValue("--talos-bake").trim() === "1" || (el.closest && el.closest("[data-bake]")); if (bake) { const c = getComputedStyle(el).color; el.style.setProperty("color", c, "important"); el.style.setProperty("-webkit-text-fill-color", c, "important"); } }); const s = document.createElement("style"); s.id = "__talos_hide"; s.textContent = "*{color:transparent !important;-webkit-text-fill-color:transparent !important;text-shadow:none !important}"; document.head.appendChild(s); return true; })()`);
|
|
147839
147846
|
for (let si = 0; si < snapshot.slides.length; si++) {
|
|
147840
147847
|
await page.evaluate(isolateSlide(si));
|
|
147841
|
-
await sleep(
|
|
147848
|
+
await sleep(CAPTURE_SETTLE_MS);
|
|
147842
147849
|
const png = await page.screenshot({ x: 0, y: 0, width: 1280, height: 720 });
|
|
147843
147850
|
const backdropEl = { kind: "image", frame: { x: 0, y: 0, w: 1280, h: 720 }, data: pngDataUri(png) };
|
|
147844
147851
|
const keepEls = snapshot.slides[si].elements.filter((e) => e && (e.kind === "text" || e.kind === "chart"));
|
|
@@ -147853,7 +147860,7 @@ async function snapshotHeadless(page, opts = {}) {
|
|
|
147853
147860
|
if (!Array.isArray(els) || !els.some((e) => e && e.kind === "capture"))
|
|
147854
147861
|
continue;
|
|
147855
147862
|
await page.evaluate(isolateSlide(si));
|
|
147856
|
-
await sleep(
|
|
147863
|
+
await sleep(CAPTURE_SETTLE_MS);
|
|
147857
147864
|
for (const el of els) {
|
|
147858
147865
|
if (!el || el.kind !== "capture")
|
|
147859
147866
|
continue;
|
|
@@ -147882,12 +147889,16 @@ async function snapshotHeadless(page, opts = {}) {
|
|
|
147882
147889
|
}
|
|
147883
147890
|
return snapshot;
|
|
147884
147891
|
}
|
|
147885
|
-
async function rasterizeHeadless(page) {
|
|
147892
|
+
async function rasterizeHeadless(page, slideIndexes) {
|
|
147886
147893
|
const count = Number(await page.evaluate('document.querySelectorAll("section.slide").length'));
|
|
147887
147894
|
if (!count)
|
|
147888
147895
|
throw new Error('no <section class="slide"> found');
|
|
147896
|
+
const indexes = slideIndexes ?? Array.from({ length: count }, (_2, i) => i);
|
|
147897
|
+
if (indexes.length === 0 || indexes.some((i) => !Number.isInteger(i) || i < 0 || i >= count)) {
|
|
147898
|
+
throw new Error(`preview page is out of bounds (deck has ${count} slide${count === 1 ? "" : "s"})`);
|
|
147899
|
+
}
|
|
147889
147900
|
const shots = [];
|
|
147890
|
-
for (
|
|
147901
|
+
for (const i of indexes) {
|
|
147891
147902
|
await page.evaluate(`new Promise((done) => { window.scrollTo(0, document.querySelectorAll("section.slide")[${i}].offsetTop); requestAnimationFrame(() => requestAnimationFrame(() => done(true))); })`);
|
|
147892
147903
|
const png = await page.screenshot({ x: 0, y: 0, width: 1280, height: 720 });
|
|
147893
147904
|
shots.push(Buffer.from(png).toString("base64"));
|
|
@@ -147947,7 +147958,9 @@ async function inlineHtmlImages(html, resolve) {
|
|
|
147947
147958
|
// packages/core/dist/document/deck-catalog.js
|
|
147948
147959
|
var KINDS = ["skin", "pack"];
|
|
147949
147960
|
var MODES = ["light", "dark"];
|
|
147961
|
+
var RENDER_MODES = ["classic-v1", "theme-v2"];
|
|
147950
147962
|
var ID_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
147963
|
+
var COMMIT_RE = /^[0-9a-f]{7,40}$/;
|
|
147951
147964
|
function isStr(v) {
|
|
147952
147965
|
return typeof v === "string" && v.length > 0;
|
|
147953
147966
|
}
|
|
@@ -147977,6 +147990,35 @@ function parseCatalog(raw) {
|
|
|
147977
147990
|
groups.push({ id: g.id, name_cn: g.name_cn, sample: g.sample, scenarios: g.scenarios });
|
|
147978
147991
|
}
|
|
147979
147992
|
});
|
|
147993
|
+
const collections = [];
|
|
147994
|
+
const rawCollections = o.collections === void 0 ? [] : Array.isArray(o.collections) ? o.collections : [];
|
|
147995
|
+
if (o.collections !== void 0 && !Array.isArray(o.collections))
|
|
147996
|
+
errors.push("catalog.collections must be an array when present");
|
|
147997
|
+
rawCollections.forEach((c, i) => {
|
|
147998
|
+
const at = `collection[${i}]`;
|
|
147999
|
+
const before = errors.length;
|
|
148000
|
+
if (!isStr(c?.id) || !ID_RE.test(c.id))
|
|
148001
|
+
errors.push(`${at}: bad id`);
|
|
148002
|
+
if (!isStr(c?.name_cn))
|
|
148003
|
+
errors.push(`${at}: missing name_cn`);
|
|
148004
|
+
if (!isStr(c?.renderMode) || !RENDER_MODES.includes(c.renderMode))
|
|
148005
|
+
errors.push(`${at}: bad renderMode`);
|
|
148006
|
+
if (!isStrArr(c?.entryIds) || c.entryIds.length === 0)
|
|
148007
|
+
errors.push(`${at}: entryIds must be a non-empty string array`);
|
|
148008
|
+
if (c?.sourceCommit !== void 0 && (!isStr(c.sourceCommit) || !COMMIT_RE.test(c.sourceCommit)))
|
|
148009
|
+
errors.push(`${at}: bad sourceCommit`);
|
|
148010
|
+
if (c?.renderMode === "classic-v1" && c?.sourceCommit === void 0)
|
|
148011
|
+
errors.push(`${at}: classic-v1 requires sourceCommit`);
|
|
148012
|
+
if (errors.length === before) {
|
|
148013
|
+
collections.push({
|
|
148014
|
+
id: c.id,
|
|
148015
|
+
name_cn: c.name_cn,
|
|
148016
|
+
renderMode: c.renderMode,
|
|
148017
|
+
entryIds: c.entryIds,
|
|
148018
|
+
...c.sourceCommit !== void 0 ? { sourceCommit: c.sourceCommit } : {}
|
|
148019
|
+
});
|
|
148020
|
+
}
|
|
148021
|
+
});
|
|
147980
148022
|
const entries = [];
|
|
147981
148023
|
const rawEntries = Array.isArray(o.entries) ? o.entries : [];
|
|
147982
148024
|
if (!Array.isArray(o.entries))
|
|
@@ -148016,11 +148058,14 @@ function parseCatalog(raw) {
|
|
|
148016
148058
|
});
|
|
148017
148059
|
}
|
|
148018
148060
|
});
|
|
148019
|
-
return { catalog: errors.length ? null : { groups, entries }, errors };
|
|
148061
|
+
return { catalog: errors.length ? null : { groups, ...collections.length ? { collections } : {}, entries }, errors };
|
|
148020
148062
|
}
|
|
148021
148063
|
function resolveEntry(catalog, id) {
|
|
148022
148064
|
return catalog.entries.find((e) => e.id === id) ?? null;
|
|
148023
148065
|
}
|
|
148066
|
+
function renderModeOf(catalog, id) {
|
|
148067
|
+
return catalog.collections?.find((c) => c.entryIds.includes(id))?.renderMode ?? "theme-v2";
|
|
148068
|
+
}
|
|
148024
148069
|
function assetDirOf(entry) {
|
|
148025
148070
|
return entry.kind === "skin" ? `styles/${entry.id}` : `packs/${entry.id}`;
|
|
148026
148071
|
}
|
|
@@ -148028,6 +148073,108 @@ function cssFileOf(entry) {
|
|
|
148028
148073
|
return entry.kind === "skin" ? "skin.css" : "pack.css";
|
|
148029
148074
|
}
|
|
148030
148075
|
|
|
148076
|
+
// packages/core/dist/shared/guards.js
|
|
148077
|
+
function isRecord(value) {
|
|
148078
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
148079
|
+
}
|
|
148080
|
+
|
|
148081
|
+
// packages/core/dist/document/deck-theme-system.js
|
|
148082
|
+
var ID_RE2 = /^[a-z0-9][a-z0-9-]*$/;
|
|
148083
|
+
var PATH_RE = /^[a-z0-9_./-]+\.css$/i;
|
|
148084
|
+
function isSafeCssPath(v) {
|
|
148085
|
+
return typeof v === "string" && PATH_RE.test(v) && !v.startsWith("/") && !v.includes("..");
|
|
148086
|
+
}
|
|
148087
|
+
function parsePathMap(value, at, errors) {
|
|
148088
|
+
if (!isRecord(value)) {
|
|
148089
|
+
errors.push(`${at} must be an object`);
|
|
148090
|
+
return {};
|
|
148091
|
+
}
|
|
148092
|
+
const out = {};
|
|
148093
|
+
for (const [id, path] of Object.entries(value)) {
|
|
148094
|
+
if (!ID_RE2.test(id))
|
|
148095
|
+
errors.push(`${at}.${id}: bad id`);
|
|
148096
|
+
if (!isSafeCssPath(path)) {
|
|
148097
|
+
errors.push(`${at}.${id}: must be a safe relative .css path`);
|
|
148098
|
+
continue;
|
|
148099
|
+
}
|
|
148100
|
+
out[id] = path;
|
|
148101
|
+
}
|
|
148102
|
+
return out;
|
|
148103
|
+
}
|
|
148104
|
+
function parseThemeSystem(raw) {
|
|
148105
|
+
const errors = [];
|
|
148106
|
+
if (!isRecord(raw))
|
|
148107
|
+
return { system: null, errors: ["theme system is not an object"] };
|
|
148108
|
+
if (raw.version !== 2)
|
|
148109
|
+
errors.push("theme system version must be 2");
|
|
148110
|
+
if (!isSafeCssPath(raw.componentBase)) {
|
|
148111
|
+
errors.push("componentBase must be a safe relative .css path");
|
|
148112
|
+
}
|
|
148113
|
+
if (!isSafeCssPath(raw.artBase)) {
|
|
148114
|
+
errors.push("artBase must be a safe relative .css path");
|
|
148115
|
+
}
|
|
148116
|
+
const componentProfiles = parsePathMap(raw.componentProfiles, "componentProfiles", errors);
|
|
148117
|
+
const mediaStyles = parsePathMap(raw.mediaStyles, "mediaStyles", errors);
|
|
148118
|
+
const artDirections = parsePathMap(raw.artDirections, "artDirections", errors);
|
|
148119
|
+
const bindings = {};
|
|
148120
|
+
if (!isRecord(raw.bindings))
|
|
148121
|
+
errors.push("bindings must be an object");
|
|
148122
|
+
else {
|
|
148123
|
+
for (const [id, value] of Object.entries(raw.bindings)) {
|
|
148124
|
+
const at = `bindings.${id}`;
|
|
148125
|
+
if (!ID_RE2.test(id))
|
|
148126
|
+
errors.push(`${at}: bad id`);
|
|
148127
|
+
if (!isRecord(value)) {
|
|
148128
|
+
errors.push(`${at} must be an object`);
|
|
148129
|
+
continue;
|
|
148130
|
+
}
|
|
148131
|
+
const componentProfile = value.componentProfile;
|
|
148132
|
+
const mediaStyle = value.mediaStyle;
|
|
148133
|
+
const artDirection = value.artDirection;
|
|
148134
|
+
if (typeof componentProfile !== "string" || !ID_RE2.test(componentProfile))
|
|
148135
|
+
errors.push(`${at}: bad componentProfile`);
|
|
148136
|
+
if (typeof mediaStyle !== "string" || !ID_RE2.test(mediaStyle))
|
|
148137
|
+
errors.push(`${at}: bad mediaStyle`);
|
|
148138
|
+
if (typeof artDirection !== "string" || !ID_RE2.test(artDirection))
|
|
148139
|
+
errors.push(`${at}: bad artDirection`);
|
|
148140
|
+
if (typeof componentProfile === "string" && typeof mediaStyle === "string" && typeof artDirection === "string") {
|
|
148141
|
+
bindings[id] = { componentProfile, mediaStyle, artDirection };
|
|
148142
|
+
}
|
|
148143
|
+
}
|
|
148144
|
+
}
|
|
148145
|
+
if (errors.length)
|
|
148146
|
+
return { system: null, errors };
|
|
148147
|
+
return {
|
|
148148
|
+
system: {
|
|
148149
|
+
version: 2,
|
|
148150
|
+
componentBase: raw.componentBase,
|
|
148151
|
+
artBase: raw.artBase,
|
|
148152
|
+
componentProfiles,
|
|
148153
|
+
mediaStyles,
|
|
148154
|
+
artDirections,
|
|
148155
|
+
bindings
|
|
148156
|
+
},
|
|
148157
|
+
errors
|
|
148158
|
+
};
|
|
148159
|
+
}
|
|
148160
|
+
function resolveThemeLayers(system, styleId, mediaOverride) {
|
|
148161
|
+
const binding = system.bindings[styleId];
|
|
148162
|
+
if (!binding)
|
|
148163
|
+
return null;
|
|
148164
|
+
const mediaStyle = mediaOverride ?? binding.mediaStyle;
|
|
148165
|
+
const componentPath = system.componentProfiles[binding.componentProfile];
|
|
148166
|
+
const mediaPath = system.mediaStyles[mediaStyle];
|
|
148167
|
+
const artPath = system.artDirections[binding.artDirection];
|
|
148168
|
+
if (!componentPath || !mediaPath || !artPath)
|
|
148169
|
+
return null;
|
|
148170
|
+
return {
|
|
148171
|
+
paths: [system.componentBase, componentPath, mediaPath, system.artBase, artPath],
|
|
148172
|
+
componentProfile: binding.componentProfile,
|
|
148173
|
+
mediaStyle,
|
|
148174
|
+
artDirection: binding.artDirection
|
|
148175
|
+
};
|
|
148176
|
+
}
|
|
148177
|
+
|
|
148031
148178
|
// apps/admin/data/skills.lib/document/bin-src/html2pptx.mjs
|
|
148032
148179
|
function imageResolver(baseDir) {
|
|
148033
148180
|
return async (src) => {
|
|
@@ -148046,6 +148193,19 @@ function die(msg, code = 1) {
|
|
|
148046
148193
|
`);
|
|
148047
148194
|
process.exit(code);
|
|
148048
148195
|
}
|
|
148196
|
+
function parsePreviewPages(spec) {
|
|
148197
|
+
if (!spec || spec.trim().toLowerCase() === "all") return null;
|
|
148198
|
+
const pages = [];
|
|
148199
|
+
for (const part of spec.split(",")) {
|
|
148200
|
+
const match = /^(\d+)(?:-(\d+))?$/.exec(part.trim());
|
|
148201
|
+
if (!match) die(`bad preview page spec: ${spec} (use all or N,N-M)`, 64);
|
|
148202
|
+
const from = Number(match[1]);
|
|
148203
|
+
const to = match[2] ? Number(match[2]) : from;
|
|
148204
|
+
if (from < 1 || to < from) die(`bad preview page range: ${part}`, 64);
|
|
148205
|
+
for (let p = from; p <= to; p++) if (!pages.includes(p - 1)) pages.push(p - 1);
|
|
148206
|
+
}
|
|
148207
|
+
return pages;
|
|
148208
|
+
}
|
|
148049
148209
|
var _tailwindCss;
|
|
148050
148210
|
async function tailwindCss() {
|
|
148051
148211
|
if (_tailwindCss !== void 0) return _tailwindCss;
|
|
@@ -148118,13 +148278,22 @@ async function withHeadlessPage(html, fn) {
|
|
|
148118
148278
|
if (!chromium) return null;
|
|
148119
148279
|
const browser2 = await chromium.launch();
|
|
148120
148280
|
try {
|
|
148121
|
-
const page = await browser2.newPage({
|
|
148281
|
+
const page = await browser2.newPage({
|
|
148282
|
+
viewport: { width: 1280, height: 720 },
|
|
148283
|
+
deviceScaleFactor: DOCUMENT_CAPTURE_DENSITY
|
|
148284
|
+
});
|
|
148122
148285
|
await page.setContent(html, { waitUntil: "load" });
|
|
148123
148286
|
await page.evaluate("document.fonts && document.fonts.ready").catch(() => {
|
|
148124
148287
|
});
|
|
148125
148288
|
const adapter = {
|
|
148126
148289
|
evaluate: (script) => page.evaluate(script),
|
|
148127
|
-
screenshot: (clip) =>
|
|
148290
|
+
screenshot: async (clip) => {
|
|
148291
|
+
const png = await page.screenshot({ clip });
|
|
148292
|
+
const w = png.readUInt32BE(16), h = png.readUInt32BE(20);
|
|
148293
|
+
const want = [clip.width * DOCUMENT_CAPTURE_DENSITY, clip.height * DOCUMENT_CAPTURE_DENSITY];
|
|
148294
|
+
if (w !== want[0] || h !== want[1]) throw new Error(`captured ${w}x${h}, expected ${want[0]}x${want[1]}`);
|
|
148295
|
+
return png;
|
|
148296
|
+
}
|
|
148128
148297
|
};
|
|
148129
148298
|
return await fn(adapter);
|
|
148130
148299
|
} finally {
|
|
@@ -148187,19 +148356,33 @@ async function main() {
|
|
|
148187
148356
|
const themePath = themeIdx >= 0 ? args[themeIdx + 1] : void 0;
|
|
148188
148357
|
const styleIdx = args.indexOf("--style");
|
|
148189
148358
|
const styleArg = styleIdx >= 0 ? args[styleIdx + 1] : void 0;
|
|
148359
|
+
const themeV2 = args.includes("--theme-v2");
|
|
148360
|
+
const mediaIdx = args.indexOf("--media-style");
|
|
148361
|
+
const mediaStyleArg = mediaIdx >= 0 ? args[mediaIdx + 1] : void 0;
|
|
148190
148362
|
const bdIdx = args.indexOf("--backdrop");
|
|
148191
148363
|
const bdVariant = bdIdx >= 0 ? args[bdIdx + 1] : void 0;
|
|
148192
148364
|
const lineIdx = args.indexOf("--line");
|
|
148193
148365
|
const lineArg = lineIdx >= 0 ? args[lineIdx + 1] : void 0;
|
|
148194
148366
|
const notesIdx = args.indexOf("--notes-doc");
|
|
148195
148367
|
const notesDocPath = notesIdx >= 0 ? args[notesIdx + 1] : void 0;
|
|
148196
|
-
const
|
|
148197
|
-
const
|
|
148368
|
+
const previewIdx = args.indexOf("--preview-dir");
|
|
148369
|
+
const previewDir = previewIdx >= 0 ? args[previewIdx + 1] : void 0;
|
|
148370
|
+
const previewPagesIdx = args.indexOf("--preview-pages");
|
|
148371
|
+
const previewPagesArg = previewPagesIdx >= 0 ? args[previewPagesIdx + 1] : void 0;
|
|
148372
|
+
const previewIndexes = parsePreviewPages(previewPagesArg);
|
|
148373
|
+
const consumed = /* @__PURE__ */ new Set([themeIdx, themeIdx >= 0 ? themeIdx + 1 : -1, styleIdx, styleIdx >= 0 ? styleIdx + 1 : -1, mediaIdx, mediaIdx >= 0 ? mediaIdx + 1 : -1, bdIdx, bdIdx >= 0 ? bdIdx + 1 : -1, lineIdx, lineIdx >= 0 ? lineIdx + 1 : -1, modeIdx, modeIdx >= 0 ? modeIdx + 1 : -1, notesIdx, notesIdx >= 0 ? notesIdx + 1 : -1, previewIdx, previewIdx >= 0 ? previewIdx + 1 : -1, previewPagesIdx, previewPagesIdx >= 0 ? previewPagesIdx + 1 : -1]);
|
|
148374
|
+
const positional = args.filter((a, i) => a !== "--rasterize" && a !== "--editable" && a !== "--theme-v2" && !consumed.has(i));
|
|
148198
148375
|
const [input, out] = positional;
|
|
148199
|
-
if (!input || !out) die("usage: html2pptx <in.html|in.layout.json>
|
|
148200
|
-
if (
|
|
148376
|
+
if (!input || !out && !previewDir) die("usage: html2pptx <in.html|in.layout.json> [out.pptx] [--theme <theme.json>] [--style <name|dir>] [--theme-v2] [--media-style <id>] [--backdrop <variant>] [--line <name|none>] [--editable] [--rasterize] [--notes-doc <out.md>] [--preview-dir <dir>] [--preview-pages <all|N,N-M>]", 64);
|
|
148377
|
+
if (previewPagesArg && !previewDir) die("--preview-pages requires --preview-dir", 64);
|
|
148378
|
+
if (previewDir && out) die("--preview-dir is preview-only; omit the .pptx output", 64);
|
|
148379
|
+
if (previewDir && (rasterize || forceEditable || notesDocPath)) die("--preview-dir cannot be combined with --rasterize, --editable/--mode, or --notes-doc", 64);
|
|
148380
|
+
if (themeV2 && !styleArg) die("--theme-v2 requires --style <catalog-id>", 64);
|
|
148381
|
+
if (mediaStyleArg && !themeV2) die("--media-style requires --theme-v2", 64);
|
|
148382
|
+
if (!previewDir && !/\.pptx$/i.test(out)) die("output must be a .pptx path", 64);
|
|
148201
148383
|
const raw = await (0, import_promises.readFile)(input, "utf8").catch((e) => die(`cannot read ${input}: ${e.message}`, 66));
|
|
148202
148384
|
if (/\.json$/i.test(input)) {
|
|
148385
|
+
if (previewDir) die("--preview-dir requires HTML input", 64);
|
|
148203
148386
|
let snapshot2;
|
|
148204
148387
|
try {
|
|
148205
148388
|
snapshot2 = JSON.parse(raw);
|
|
@@ -148239,18 +148422,17 @@ async function main() {
|
|
|
148239
148422
|
let skinCss = "", backdropHtml = "", skinAccent = "", skinAxis = "", skinChart1 = "";
|
|
148240
148423
|
if (styleArg) {
|
|
148241
148424
|
const skillDir = (0, import_node_path.dirname)((0, import_node_path.dirname)(process.argv[1] || ""));
|
|
148242
|
-
let styleDir, cssName = "skin.css";
|
|
148425
|
+
let styleDir, cssName = "skin.css", entry = null, catalog = null;
|
|
148243
148426
|
if ((0, import_node_fs.existsSync)((0, import_node_path.join)(styleArg, "skin.css"))) {
|
|
148244
148427
|
styleDir = styleArg;
|
|
148245
148428
|
} else if ((0, import_node_fs.existsSync)((0, import_node_path.join)(styleArg, "pack.css"))) {
|
|
148246
148429
|
styleDir = styleArg;
|
|
148247
148430
|
cssName = "pack.css";
|
|
148248
148431
|
} else {
|
|
148249
|
-
let entry = null;
|
|
148250
148432
|
const catalogPath = (0, import_node_path.join)(skillDir, "catalog.json");
|
|
148251
148433
|
if ((0, import_node_fs.existsSync)(catalogPath)) {
|
|
148252
148434
|
try {
|
|
148253
|
-
|
|
148435
|
+
({ catalog } = parseCatalog(JSON.parse((0, import_node_fs.readFileSync)(catalogPath, "utf8"))));
|
|
148254
148436
|
if (catalog) entry = resolveEntry(catalog, styleArg);
|
|
148255
148437
|
} catch {
|
|
148256
148438
|
}
|
|
@@ -148265,7 +148447,27 @@ async function main() {
|
|
|
148265
148447
|
die(`cannot read style ${skinPath}: ${e.message}`, 66);
|
|
148266
148448
|
}
|
|
148267
148449
|
const defaultsPath = (0, import_node_path.join)(skillDir, "styles", "_contract-defaults.css");
|
|
148268
|
-
|
|
148450
|
+
let v2Css = "";
|
|
148451
|
+
if (themeV2) {
|
|
148452
|
+
if (!entry) die("--theme-v2 requires a catalog style id (explicit style directories are V1 only)", 64);
|
|
148453
|
+
if (catalog && renderModeOf(catalog, entry.id) === "classic-v1") {
|
|
148454
|
+
die(`style "${entry.id}" is frozen in collection "original-13" as classic-v1; omit --theme-v2 and --media-style`, 64);
|
|
148455
|
+
}
|
|
148456
|
+
const registryPath = (0, import_node_path.join)(skillDir, "theme-system.json");
|
|
148457
|
+
let parsed;
|
|
148458
|
+
try {
|
|
148459
|
+
parsed = parseThemeSystem(JSON.parse(await (0, import_promises.readFile)(registryPath, "utf8")));
|
|
148460
|
+
} catch (e) {
|
|
148461
|
+
die(`cannot read Theme V2 registry ${registryPath}: ${e.message}`, 66);
|
|
148462
|
+
}
|
|
148463
|
+
if (!parsed.system) die(`invalid Theme V2 registry: ${parsed.errors.join("; ")}`, 66);
|
|
148464
|
+
const layers = resolveThemeLayers(parsed.system, entry.id, mediaStyleArg);
|
|
148465
|
+
if (!layers) die(`Theme V2 cannot resolve style "${entry.id}"${mediaStyleArg ? ` with media style "${mediaStyleArg}"` : ""}`, 66);
|
|
148466
|
+
for (const rel of layers.paths) v2Css += await (0, import_promises.readFile)((0, import_node_path.join)(skillDir, rel), "utf8") + "\n";
|
|
148467
|
+
process.stderr.write(`html2pptx: Theme V2 ${entry.id} = components:${layers.componentProfile} + media:${layers.mediaStyle} + art:${layers.artDirection}
|
|
148468
|
+
`);
|
|
148469
|
+
}
|
|
148470
|
+
skinCss = ((0, import_node_fs.existsSync)(defaultsPath) ? await (0, import_promises.readFile)(defaultsPath, "utf8") + "\n" : "") + v2Css + skinCss;
|
|
148269
148471
|
const sharedBackdropsDir = (0, import_node_path.join)(skillDir, "styles", "_backdrops");
|
|
148270
148472
|
const NO_AUTO_BACKDROP_VARIETY = /* @__PURE__ */ new Set(["mckinsey", "mono", "cinereel"]);
|
|
148271
148473
|
let bdPath;
|
|
@@ -148279,7 +148481,7 @@ async function main() {
|
|
|
148279
148481
|
`);
|
|
148280
148482
|
bdPath = (0, import_node_path.join)(styleDir, "backdrop.html");
|
|
148281
148483
|
}
|
|
148282
|
-
} else if (NO_AUTO_BACKDROP_VARIETY.has((0, import_node_path.basename)(styleDir))) {
|
|
148484
|
+
} else if (themeV2 || NO_AUTO_BACKDROP_VARIETY.has((0, import_node_path.basename)(styleDir))) {
|
|
148283
148485
|
bdPath = (0, import_node_path.join)(styleDir, "backdrop.html");
|
|
148284
148486
|
} else {
|
|
148285
148487
|
const ownVariants = (0, import_node_fs.existsSync)(styleDir) ? (0, import_node_fs.readdirSync)(styleDir).filter((f) => /^backdrop.*\.html$/.test(f)).map((f) => (0, import_node_path.join)(styleDir, f)) : [];
|
|
@@ -148313,7 +148515,8 @@ async function main() {
|
|
|
148313
148515
|
for (const s of skipped) process.stderr.write(`html2pptx: <img src="${s}"> not found/unfetchable \u2014 the render will drop it
|
|
148314
148516
|
`);
|
|
148315
148517
|
if (styleArg) {
|
|
148316
|
-
|
|
148518
|
+
const artLayer = themeV2 ? '<div class="theme-art-layer" aria-hidden="true"><i class="art-shape art-a"></i><i class="art-shape art-b"></i><i class="art-shape art-c"></i><i class="art-pattern"></i></div>' : "";
|
|
148519
|
+
if (backdropHtml || artLayer) rawInlined = rawInlined.replace(/<div class="slide-backdrop">\s*<\/div>/g, `<div class="slide-backdrop">${backdropHtml}${artLayer}</div>`);
|
|
148317
148520
|
if (skinAccent) rawInlined = rawInlined.replaceAll("__ACCENT__", skinAccent);
|
|
148318
148521
|
if (skinAxis) rawInlined = rawInlined.replaceAll("__AXIS__", skinAxis);
|
|
148319
148522
|
if (skinChart1) rawInlined = rawInlined.replaceAll("__CHART1__", skinChart1);
|
|
@@ -148323,6 +148526,24 @@ async function main() {
|
|
|
148323
148526
|
const latin = await latinFontFaceCss(rawInlined + skinCss);
|
|
148324
148527
|
const fontCss = cjk + latin;
|
|
148325
148528
|
const html = injectHead(rawInlined, `${fontCss ? `<style>${fontCss}</style>` : ""}${tw ? `<style>${tw}</style>` : ""}<style>${themeCss}${SKELETON_CSS}${skinCss}</style>`);
|
|
148529
|
+
if (previewDir) {
|
|
148530
|
+
let images;
|
|
148531
|
+
if (hasService) ({ images } = await callService("/shot", html, previewIndexes ? { pages: previewIndexes } : {}).catch((e) => die(e.message, 1)));
|
|
148532
|
+
else {
|
|
148533
|
+
images = await withHeadlessPage(html, (p) => rasterizeHeadless(p, previewIndexes ?? void 0)).catch((e) => die(e.message, 1));
|
|
148534
|
+
if (images == null) die(NO_BROWSER, 69);
|
|
148535
|
+
}
|
|
148536
|
+
await (0, import_promises.mkdir)(previewDir, { recursive: true });
|
|
148537
|
+
const pageNumbers = previewIndexes ? previewIndexes.map((i) => i + 1) : images.map((_2, i) => i + 1);
|
|
148538
|
+
const files = [];
|
|
148539
|
+
for (let i = 0; i < images.length; i++) {
|
|
148540
|
+
const path = (0, import_node_path.join)(previewDir, `slide-${String(pageNumbers[i]).padStart(3, "0")}.png`);
|
|
148541
|
+
await (0, import_promises.writeFile)(path, Buffer.from(images[i], "base64"));
|
|
148542
|
+
files.push(path);
|
|
148543
|
+
}
|
|
148544
|
+
process.stdout.write(JSON.stringify({ ok: true, engine: hasService ? "preview" : "preview (headless)", slides: images.length, pages: pageNumbers, files }, null, 1) + "\n");
|
|
148545
|
+
return;
|
|
148546
|
+
}
|
|
148326
148547
|
if (rasterize) {
|
|
148327
148548
|
let images;
|
|
148328
148549
|
if (hasService) ({ images } = await callService("/shot", html).catch((e) => die(e.message, 1)));
|
|
@@ -7,13 +7,24 @@
|
|
|
7
7
|
{"id":"creative","name_cn":"创意手作","sample":"styles/_samples/_groups/creative.webp","scenarios":["创意","教学","工作坊","头脑风暴"]},
|
|
8
8
|
{"id":"natural","name_cn":"自然温和","sample":"styles/_samples/_groups/natural.webp","scenarios":["品牌手册","可持续","美妆","零售"]}
|
|
9
9
|
],
|
|
10
|
+
"collections": [
|
|
11
|
+
{
|
|
12
|
+
"id": "original-13",
|
|
13
|
+
"name_cn": "初代经典",
|
|
14
|
+
"renderMode": "classic-v1",
|
|
15
|
+
"sourceCommit": "7306d8e5",
|
|
16
|
+
"entryIds": ["cool", "swiss-grid", "black-gold", "olive-gold", "mckinsey", "apple", "mono", "ivory-gold", "magazine-ink", "anthropic", "hand-drawn", "cinereel", "branding"]
|
|
17
|
+
}
|
|
18
|
+
],
|
|
10
19
|
"entries": [
|
|
11
20
|
{"id":"cool","kind":"skin","group":"tech-future","name_cn":"酷炫深色","oneliner":"深蓝辉光 · 科技发布","scenarios":["科技","发布","pitch","主题演讲"],"mode":"dark","sample":"styles/_samples/cool.webp","motion":"motion/cool.json"},
|
|
12
21
|
{"id":"neon-cyber","kind":"skin","group":"tech-future","name_cn":"霓虹赛博","oneliner":"霓虹品红 · 赛博夜场","scenarios":["科技","游戏","Web3","夜场发布"],"mode":"dark","sample":"styles/_samples/neon-cyber.webp","motion":"motion/neon-cyber.json"},
|
|
22
|
+
{"id":"prismatic-3d","kind":"pack","group":"tech-future","name_cn":"棱镜空间","oneliner":"紫黑棱镜 · 立体发布","scenarios":["科技发布","AI 产品","创意提案","未来趋势"],"mode":"dark","sample":"styles/_samples/prismatic-3d.webp","motion":"motion/prismatic-3d.json"},
|
|
13
23
|
{"id":"swiss-grid","kind":"skin","group":"tech-future","name_cn":"瑞士国际","oneliner":"克莱因蓝白 · 瑞士国际","scenarios":["科技产品","数据汇报","设计","年度总结"],"mode":"light","sample":"styles/_samples/swiss-grid.webp","motion":"motion/swiss-grid.json"},
|
|
14
24
|
{"id":"black-gold","kind":"skin","group":"biz-premium","name_cn":"黑金","oneliner":"纯黑金辉 · 高端商务","scenarios":["金融","年报","路演","奢侈品"],"mode":"dark","sample":"styles/_samples/black-gold.webp","motion":"motion/black-gold.json"},
|
|
15
25
|
{"id":"olive-gold","kind":"skin","group":"biz-premium","name_cn":"橄榄金","oneliner":"橄榄亮金 · 高端招商","scenarios":["高端","证书","招商","品牌"],"mode":"dark","sample":"styles/_samples/olive-gold.webp","motion":"motion/olive-gold.json"},
|
|
16
26
|
{"id":"mckinsey","kind":"skin","group":"biz-premium","name_cn":"白底咨询","oneliner":"白底藏青 · 咨询评审","scenarios":["咨询","战略汇报","评审","董事会"],"mode":"light","sample":"styles/_samples/mckinsey.webp","motion":"motion/mckinsey.json"},
|
|
27
|
+
{"id":"mckinsey-photo","kind":"pack","group":"biz-premium","name_cn":"咨询影像","oneliner":"藏青影像 · 企业叙事","scenarios":["咨询","企业战略","案例研究","年度回顾"],"mode":"light","sample":"styles/_samples/mckinsey-photo.webp","motion":"motion/mckinsey-photo.json"},
|
|
17
28
|
{"id":"apple","kind":"skin","group":"minimal","name_cn":"纯黑极简","oneliner":"纯黑极简 · 产品发布","scenarios":["产品发布","主题演讲","极简演示"],"mode":"dark","sample":"styles/_samples/apple.webp","motion":"motion/apple.json"},
|
|
18
29
|
{"id":"mono","kind":"skin","group":"minimal","name_cn":"纯白黑灰","oneliner":"纯白黑灰 · 极简设计","scenarios":["极简","高端","设计","单色报告"],"mode":"light","sample":"styles/_samples/mono.webp","motion":"motion/mono.json"},
|
|
19
30
|
{"id":"ivory-gold","kind":"skin","group":"minimal","name_cn":"奶油青铜","oneliner":"奶油青铜 · 奢华极简","scenarios":["奢华极简","品牌手册","路演","高端零售"],"mode":"light","sample":"styles/_samples/ivory-gold.webp","motion":"motion/ivory-gold.json"},
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/* Theme V2 semantic component contract. Enabled only by --theme-v2. */
|
|
2
|
+
:root{
|
|
3
|
+
--cmp-radius:var(--card-radius,4px);--cmp-border:var(--hair);--cmp-surface:transparent;
|
|
4
|
+
--cmp-surface-strong:var(--title);--cmp-on-strong:var(--slide-bg);--cmp-shadow:none;
|
|
5
|
+
--cmp-pad:24px;--cmp-gap:18px;--cmp-line:1px;--cmp-media-radius:var(--cmp-radius);
|
|
6
|
+
--cmp-media-fit:cover;--cmp-media-filter:none;--cmp-media-shadow:none;
|
|
7
|
+
}
|
|
8
|
+
.component-card,.metric-card,.proof-card,.price-card,.team-card,.feature-card,.fund-card{
|
|
9
|
+
position:relative;background:var(--cmp-surface);border:var(--cmp-line) solid var(--cmp-border);
|
|
10
|
+
border-radius:var(--cmp-radius);box-shadow:var(--cmp-shadow);padding:var(--cmp-pad);overflow:hidden;
|
|
11
|
+
}
|
|
12
|
+
.component-card--strong,.metric-card--hero,.price-card--featured{
|
|
13
|
+
background:var(--cmp-surface-strong);border-color:var(--cmp-surface-strong);color:var(--cmp-on-strong);
|
|
14
|
+
}
|
|
15
|
+
.component-card--strong :is(h2,h3,p,span),.metric-card--hero :is(h2,h3,p,span),.price-card--featured :is(h2,h3,p,span){color:inherit}
|
|
16
|
+
.metric-value{font-family:var(--font-head);font-size:calc(44px * var(--type-scale,1));font-weight:800;letter-spacing:-.04em;line-height:1}
|
|
17
|
+
.metric-label,.component-label,.media-caption{color:var(--muted);font-size:calc(13px * var(--type-scale,1));letter-spacing:.08em;text-transform:uppercase}
|
|
18
|
+
.component-title{font-family:var(--font-head);color:var(--title);font-weight:750;line-height:1.15}
|
|
19
|
+
.component-copy{color:var(--body);line-height:1.55}
|
|
20
|
+
.badge,.tag,.pill{display:inline-flex;align-items:center;width:max-content;border:var(--cmp-line) solid var(--cmp-border);border-radius:999px;padding:5px 11px;font-size:calc(12px * var(--type-scale,1));font-weight:700}
|
|
21
|
+
.badge--accent,.tag--accent{background:var(--accent);border-color:var(--accent);color:var(--slide-bg)}
|
|
22
|
+
.media-frame,.media-cutout,.device-frame{position:relative;overflow:hidden;border:var(--cmp-line) solid var(--cmp-border);border-radius:var(--cmp-media-radius);box-shadow:var(--cmp-media-shadow);background:var(--card-bg,transparent)}
|
|
23
|
+
.media-frame>img,.media-cutout>img,.device-frame>img{width:100%;height:100%;object-fit:var(--cmp-media-fit);filter:var(--cmp-media-filter)}
|
|
24
|
+
.quote-mark{font-family:var(--font-head);color:var(--accent);font-size:calc(64px * var(--type-scale,1));line-height:.6}
|
|
25
|
+
.quote-copy{font-family:var(--font-head);font-size:calc(26px * var(--type-scale,1));line-height:1.32;color:var(--title)}
|
|
26
|
+
.logo-tile{display:flex;align-items:center;justify-content:center;min-height:62px;border:var(--cmp-line) solid var(--cmp-border);border-radius:var(--cmp-radius);color:var(--muted);font-weight:700}
|
|
27
|
+
.progress-track,.fund-track{height:10px;background:var(--hair);border-radius:999px;overflow:hidden}
|
|
28
|
+
.progress-fill,.fund-fill{height:100%;background:var(--accent);border-radius:inherit}
|
|
29
|
+
.timeline-node{width:14px;height:14px;border-radius:50%;background:var(--accent);box-shadow:0 0 0 5px var(--cmp-surface)}
|
|
30
|
+
.avatar-frame{overflow:hidden;border-radius:50%;border:var(--cmp-line) solid var(--cmp-border)}
|
|
31
|
+
.avatar-frame>img{width:100%;height:100%;object-fit:cover}
|
|
32
|
+
.data-chip{font-family:var(--font-head);font-variant-numeric:tabular-nums;color:var(--accent);font-weight:800}
|
|
33
|
+
.component-grid{display:grid;gap:var(--cmp-gap)}
|
|
34
|
+
.chart-shell,.table-shell,.callout,.workflow-node{background:var(--cmp-surface);border:var(--cmp-line) solid var(--cmp-border);border-radius:var(--cmp-radius);box-shadow:var(--cmp-shadow)}
|
|
35
|
+
.chart-shell,.table-shell{padding:var(--cmp-pad)}
|
|
36
|
+
.chart-shell .chart{background:transparent}
|
|
37
|
+
.legend-item{display:flex;align-items:center;gap:8px;color:var(--muted);font-size:calc(13px * var(--type-scale,1))}
|
|
38
|
+
.legend-item:before{content:"";width:9px;height:9px;border-radius:50%;background:var(--accent)}
|
|
39
|
+
.table-shell .dt-head{background:color-mix(in srgb,var(--accent) 10%,transparent);border-bottom:var(--cmp-line) solid var(--cmp-border)}
|
|
40
|
+
.table-shell .dt-row{border-bottom:var(--cmp-line) solid var(--hair)}
|
|
41
|
+
.callout{padding:16px 18px;border-left:4px solid var(--accent)}
|
|
42
|
+
.workflow-node{padding:18px;text-align:center}
|
|
43
|
+
.workflow-connector{height:var(--cmp-line);background:var(--cmp-border)}
|
|
44
|
+
.cta-block{background:var(--accent);color:var(--slide-bg);border-radius:var(--cmp-radius);padding:var(--cmp-pad)}
|
|
45
|
+
.cta-block :is(h2,h3,p,span){color:inherit}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
:root{--cmp-radius:6px;--cmp-line:1px;--cmp-pad:24px;--cmp-gap:16px;--cmp-surface:var(--card-bg,transparent);--cmp-border:var(--hair);--cmp-shadow:none}
|
|
2
|
+
.component-card:before,.metric-card:before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--accent)}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
:root{--cmp-radius:0px;--cmp-line:1px;--cmp-pad:22px;--cmp-gap:14px;--cmp-surface:transparent;--cmp-border:var(--title);--cmp-shadow:none}
|
|
2
|
+
.component-card,.metric-card,.proof-card,.price-card,.team-card{border-left-width:5px;border-top:0;border-right:0;border-bottom:0}
|
|
3
|
+
.component-label{font-family:var(--font-head);letter-spacing:.16em}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
:root{--cmp-radius:18px;--cmp-line:1px;--cmp-pad:26px;--cmp-gap:18px;--cmp-surface:color-mix(in srgb,var(--slide-bg) 58%,transparent);--cmp-border:color-mix(in srgb,var(--accent) 28%,var(--hair));--cmp-shadow:0 18px 44px rgba(0,0,0,.18)}
|
|
2
|
+
.component-card,.metric-card,.proof-card,.price-card,.team-card{backdrop-filter:blur(16px)}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
:root{--cmp-radius:0px;--cmp-line:1px;--cmp-pad:28px;--cmp-gap:20px;--cmp-surface:transparent;--cmp-border:var(--accent);--cmp-shadow:none}
|
|
2
|
+
.component-card,.metric-card,.proof-card,.price-card,.team-card{border-top:0;border-left:0;border-right:0}
|
|
3
|
+
.component-label,.metric-label{font-family:var(--font-head);letter-spacing:.2em}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
:root{--cmp-radius:2px;--cmp-line:2px;--cmp-pad:24px;--cmp-gap:18px;--cmp-surface:var(--card-bg,transparent);--cmp-border:var(--title);--cmp-shadow:8px 8px 0 var(--title)}
|
|
2
|
+
.component-card--strong,.metric-card--hero,.price-card--featured{transform:rotate(-1deg)}
|
|
3
|
+
.badge,.tag,.pill{border-radius:2px;text-transform:uppercase}
|