wand-kit 0.0.0-stage → 0.2.0
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/.gitkeep +0 -0
- package/PROMPT.md +255 -0
- package/SKILL.md +117 -0
- package/START-HERE.md +16 -0
- package/brands/current/assets/bg-cover-dark.png +0 -0
- package/brands/current/assets/bg-overlay-dark.png +0 -0
- package/brands/current/assets/bg-statement-dark.png +0 -0
- package/brands/current/assets/closing-art.png +0 -0
- package/brands/current/assets/cover-art.png +0 -0
- package/brands/current/assets/divider-art.png +0 -0
- package/brands/current/assets/glyphs/README.md +29 -0
- package/brands/current/assets/glyphs/activity.svg +15 -0
- package/brands/current/assets/glyphs/atom.svg +17 -0
- package/brands/current/assets/glyphs/badge-check.svg +16 -0
- package/brands/current/assets/glyphs/bell.svg +16 -0
- package/brands/current/assets/glyphs/blocks.svg +16 -0
- package/brands/current/assets/glyphs/book-open.svg +16 -0
- package/brands/current/assets/glyphs/bot.svg +20 -0
- package/brands/current/assets/glyphs/boxes.svg +26 -0
- package/brands/current/assets/glyphs/brain.svg +23 -0
- package/brands/current/assets/glyphs/briefcase.svg +16 -0
- package/brands/current/assets/glyphs/building-2.svg +21 -0
- package/brands/current/assets/glyphs/calendar.svg +18 -0
- package/brands/current/assets/glyphs/chart-column.svg +18 -0
- package/brands/current/assets/glyphs/chart-line.svg +16 -0
- package/brands/current/assets/glyphs/chart-pie.svg +16 -0
- package/brands/current/assets/glyphs/circle-check.svg +16 -0
- package/brands/current/assets/glyphs/clipboard-check.svg +17 -0
- package/brands/current/assets/glyphs/clock.svg +16 -0
- package/brands/current/assets/glyphs/cloud.svg +15 -0
- package/brands/current/assets/glyphs/code.svg +15 -0
- package/brands/current/assets/glyphs/coins.svg +18 -0
- package/brands/current/assets/glyphs/compass.svg +16 -0
- package/brands/current/assets/glyphs/cpu.svg +24 -0
- package/brands/current/assets/glyphs/database.svg +17 -0
- package/brands/current/assets/glyphs/eye.svg +16 -0
- package/brands/current/assets/glyphs/file-check.svg +17 -0
- package/brands/current/assets/glyphs/filter.svg +15 -0
- package/brands/current/assets/glyphs/fingerprint.svg +23 -0
- package/brands/current/assets/glyphs/flag.svg +16 -0
- package/brands/current/assets/glyphs/gauge.svg +16 -0
- package/brands/current/assets/glyphs/gavel.svg +19 -0
- package/brands/current/assets/glyphs/git-branch.svg +18 -0
- package/brands/current/assets/glyphs/globe.svg +17 -0
- package/brands/current/assets/glyphs/graduation-cap.svg +17 -0
- package/brands/current/assets/glyphs/handshake.svg +19 -0
- package/brands/current/assets/glyphs/hexagon.svg +15 -0
- package/brands/current/assets/glyphs/index.json +177 -0
- package/brands/current/assets/glyphs/infinity.svg +15 -0
- package/brands/current/assets/glyphs/key.svg +17 -0
- package/brands/current/assets/glyphs/landmark.svg +20 -0
- package/brands/current/assets/glyphs/layers.svg +17 -0
- package/brands/current/assets/glyphs/lightbulb.svg +17 -0
- package/brands/current/assets/glyphs/link.svg +16 -0
- package/brands/current/assets/glyphs/list-checks.svg +19 -0
- package/brands/current/assets/glyphs/lock.svg +16 -0
- package/brands/current/assets/glyphs/map.svg +17 -0
- package/brands/current/assets/glyphs/megaphone.svg +16 -0
- package/brands/current/assets/glyphs/message-square.svg +15 -0
- package/brands/current/assets/glyphs/milestone.svg +17 -0
- package/brands/current/assets/glyphs/network.svg +19 -0
- package/brands/current/assets/glyphs/orbit.svg +19 -0
- package/brands/current/assets/glyphs/package.svg +18 -0
- package/brands/current/assets/glyphs/plug.svg +18 -0
- package/brands/current/assets/glyphs/puzzle.svg +15 -0
- package/brands/current/assets/glyphs/radar.svg +22 -0
- package/brands/current/assets/glyphs/receipt.svg +17 -0
- package/brands/current/assets/glyphs/refresh-cw.svg +18 -0
- package/brands/current/assets/glyphs/rocket.svg +18 -0
- package/brands/current/assets/glyphs/route.svg +17 -0
- package/brands/current/assets/glyphs/scale.svg +19 -0
- package/brands/current/assets/glyphs/search.svg +16 -0
- package/brands/current/assets/glyphs/server.svg +18 -0
- package/brands/current/assets/glyphs/settings.svg +16 -0
- package/brands/current/assets/glyphs/share-2.svg +19 -0
- package/brands/current/assets/glyphs/shield-check.svg +16 -0
- package/brands/current/assets/glyphs/shuffle.svg +19 -0
- package/brands/current/assets/glyphs/sparkles.svg +19 -0
- package/brands/current/assets/glyphs/square-stack.svg +17 -0
- package/brands/current/assets/glyphs/target.svg +17 -0
- package/brands/current/assets/glyphs/trending-up.svg +16 -0
- package/brands/current/assets/glyphs/triangle-alert.svg +17 -0
- package/brands/current/assets/glyphs/trophy.svg +20 -0
- package/brands/current/assets/glyphs/users.svg +18 -0
- package/brands/current/assets/glyphs/wallet.svg +16 -0
- package/brands/current/assets/glyphs/wand-sparkles.svg +22 -0
- package/brands/current/assets/glyphs/workflow.svg +17 -0
- package/brands/current/assets/glyphs/zap.svg +15 -0
- package/brands/current/assets/mark-dark.png +0 -0
- package/brands/current/assets/mark-white.png +0 -0
- package/brands/current/assets/orb-cover.png +0 -0
- package/brands/current/assets/orb-glow.png +0 -0
- package/brands/current/assets/wordmark-dark.png +0 -0
- package/brands/current/assets/wordmark-white.png +0 -0
- package/brands/current/fonts/Geist-Bold.ttf +0 -0
- package/brands/current/fonts/Geist-BoldItalic.ttf +0 -0
- package/brands/current/fonts/Geist-ExtraBold.ttf +0 -0
- package/brands/current/fonts/Geist-ExtraBoldItalic.ttf +0 -0
- package/brands/current/fonts/Geist-Italic.ttf +0 -0
- package/brands/current/fonts/Geist-Light.ttf +0 -0
- package/brands/current/fonts/Geist-LightItalic.ttf +0 -0
- package/brands/current/fonts/Geist-Medium.ttf +0 -0
- package/brands/current/fonts/Geist-MediumItalic.ttf +0 -0
- package/brands/current/fonts/Geist-Regular.ttf +0 -0
- package/brands/current/fonts/Geist-SemiBold.ttf +0 -0
- package/brands/current/fonts/Geist-SemiBoldItalic.ttf +0 -0
- package/brands/current/lib/glyphs.js +87 -0
- package/brands/current/lib/measure.js +115 -0
- package/brands/current/lib/pdf.js +603 -0
- package/brands/current/lib/ttf.py +167 -0
- package/brands/current/lib/wandxml.py +37 -0
- package/brands/current/tokens.json +206 -0
- package/brands/next/assets/closing-art.png +0 -0
- package/brands/next/assets/cover-art.png +0 -0
- package/brands/next/assets/divider-art.png +0 -0
- package/brands/next/assets/glyphs/README.md +29 -0
- package/brands/next/assets/glyphs/activity.svg +15 -0
- package/brands/next/assets/glyphs/atom.svg +17 -0
- package/brands/next/assets/glyphs/badge-check.svg +16 -0
- package/brands/next/assets/glyphs/bell.svg +16 -0
- package/brands/next/assets/glyphs/blocks.svg +16 -0
- package/brands/next/assets/glyphs/book-open.svg +16 -0
- package/brands/next/assets/glyphs/bot.svg +20 -0
- package/brands/next/assets/glyphs/boxes.svg +26 -0
- package/brands/next/assets/glyphs/brain.svg +23 -0
- package/brands/next/assets/glyphs/briefcase.svg +16 -0
- package/brands/next/assets/glyphs/building-2.svg +21 -0
- package/brands/next/assets/glyphs/calendar.svg +18 -0
- package/brands/next/assets/glyphs/chart-column.svg +18 -0
- package/brands/next/assets/glyphs/chart-line.svg +16 -0
- package/brands/next/assets/glyphs/chart-pie.svg +16 -0
- package/brands/next/assets/glyphs/circle-check.svg +16 -0
- package/brands/next/assets/glyphs/clipboard-check.svg +17 -0
- package/brands/next/assets/glyphs/clock.svg +16 -0
- package/brands/next/assets/glyphs/cloud.svg +15 -0
- package/brands/next/assets/glyphs/code.svg +15 -0
- package/brands/next/assets/glyphs/coins.svg +18 -0
- package/brands/next/assets/glyphs/compass.svg +16 -0
- package/brands/next/assets/glyphs/cpu.svg +24 -0
- package/brands/next/assets/glyphs/database.svg +17 -0
- package/brands/next/assets/glyphs/eye.svg +16 -0
- package/brands/next/assets/glyphs/file-check.svg +17 -0
- package/brands/next/assets/glyphs/filter.svg +15 -0
- package/brands/next/assets/glyphs/fingerprint.svg +23 -0
- package/brands/next/assets/glyphs/flag.svg +16 -0
- package/brands/next/assets/glyphs/gauge.svg +16 -0
- package/brands/next/assets/glyphs/gavel.svg +19 -0
- package/brands/next/assets/glyphs/git-branch.svg +18 -0
- package/brands/next/assets/glyphs/globe.svg +17 -0
- package/brands/next/assets/glyphs/graduation-cap.svg +17 -0
- package/brands/next/assets/glyphs/handshake.svg +19 -0
- package/brands/next/assets/glyphs/hexagon.svg +15 -0
- package/brands/next/assets/glyphs/index.json +177 -0
- package/brands/next/assets/glyphs/infinity.svg +15 -0
- package/brands/next/assets/glyphs/key.svg +17 -0
- package/brands/next/assets/glyphs/landmark.svg +20 -0
- package/brands/next/assets/glyphs/layers.svg +17 -0
- package/brands/next/assets/glyphs/lightbulb.svg +17 -0
- package/brands/next/assets/glyphs/link.svg +16 -0
- package/brands/next/assets/glyphs/list-checks.svg +19 -0
- package/brands/next/assets/glyphs/lock.svg +16 -0
- package/brands/next/assets/glyphs/map.svg +17 -0
- package/brands/next/assets/glyphs/megaphone.svg +16 -0
- package/brands/next/assets/glyphs/message-square.svg +15 -0
- package/brands/next/assets/glyphs/milestone.svg +17 -0
- package/brands/next/assets/glyphs/network.svg +19 -0
- package/brands/next/assets/glyphs/orbit.svg +19 -0
- package/brands/next/assets/glyphs/package.svg +18 -0
- package/brands/next/assets/glyphs/plug.svg +18 -0
- package/brands/next/assets/glyphs/puzzle.svg +15 -0
- package/brands/next/assets/glyphs/radar.svg +22 -0
- package/brands/next/assets/glyphs/receipt.svg +17 -0
- package/brands/next/assets/glyphs/refresh-cw.svg +18 -0
- package/brands/next/assets/glyphs/rocket.svg +18 -0
- package/brands/next/assets/glyphs/route.svg +17 -0
- package/brands/next/assets/glyphs/scale.svg +19 -0
- package/brands/next/assets/glyphs/search.svg +16 -0
- package/brands/next/assets/glyphs/server.svg +18 -0
- package/brands/next/assets/glyphs/settings.svg +16 -0
- package/brands/next/assets/glyphs/share-2.svg +19 -0
- package/brands/next/assets/glyphs/shield-check.svg +16 -0
- package/brands/next/assets/glyphs/shuffle.svg +19 -0
- package/brands/next/assets/glyphs/sparkles.svg +19 -0
- package/brands/next/assets/glyphs/square-stack.svg +17 -0
- package/brands/next/assets/glyphs/target.svg +17 -0
- package/brands/next/assets/glyphs/trending-up.svg +16 -0
- package/brands/next/assets/glyphs/triangle-alert.svg +17 -0
- package/brands/next/assets/glyphs/trophy.svg +20 -0
- package/brands/next/assets/glyphs/users.svg +18 -0
- package/brands/next/assets/glyphs/wallet.svg +16 -0
- package/brands/next/assets/glyphs/wand-sparkles.svg +22 -0
- package/brands/next/assets/glyphs/workflow.svg +17 -0
- package/brands/next/assets/glyphs/zap.svg +15 -0
- package/brands/next/assets/layers-dark.png +0 -0
- package/brands/next/assets/layers-light.png +0 -0
- package/brands/next/assets/ornaments/burst-dark.png +0 -0
- package/brands/next/assets/ornaments/burst-light.png +0 -0
- package/brands/next/assets/ornaments/chain-dark.png +0 -0
- package/brands/next/assets/ornaments/chain-light.png +0 -0
- package/brands/next/assets/ornaments/coil-dark.png +0 -0
- package/brands/next/assets/ornaments/coil-light.png +0 -0
- package/brands/next/assets/ornaments/cone-dark.png +0 -0
- package/brands/next/assets/ornaments/cone-light.png +0 -0
- package/brands/next/assets/ornaments/diamond-dark.png +0 -0
- package/brands/next/assets/ornaments/diamond-light.png +0 -0
- package/brands/next/assets/ornaments/fan-dark.png +0 -0
- package/brands/next/assets/ornaments/fan-light.png +0 -0
- package/brands/next/assets/ornaments/globe-dark.png +0 -0
- package/brands/next/assets/ornaments/globe-light.png +0 -0
- package/brands/next/assets/ornaments/orbit-dark.png +0 -0
- package/brands/next/assets/ornaments/orbit-light.png +0 -0
- package/brands/next/assets/ornaments/rings-dark.png +0 -0
- package/brands/next/assets/ornaments/rings-light.png +0 -0
- package/brands/next/assets/ornaments/sphere-dark.png +0 -0
- package/brands/next/assets/ornaments/sphere-light.png +0 -0
- package/brands/next/assets/ornaments/sun-dark.png +0 -0
- package/brands/next/assets/ornaments/sun-light.png +0 -0
- package/brands/next/assets/photos/atrium.jpg +0 -0
- package/brands/next/assets/photos/cantilever.jpg +0 -0
- package/brands/next/assets/photos/corridor.jpg +0 -0
- package/brands/next/assets/photos/dome.jpg +0 -0
- package/brands/next/assets/photos/facade.jpg +0 -0
- package/brands/next/assets/photos/glass.jpg +0 -0
- package/brands/next/assets/photos/stairs.jpg +0 -0
- package/brands/next/assets/photos/tower.jpg +0 -0
- package/brands/next/assets/photos/walk.jpg +0 -0
- package/brands/next/assets/spark-gold.png +0 -0
- package/brands/next/assets/statement-art.png +0 -0
- package/brands/next/assets/wordmark-dark.png +0 -0
- package/brands/next/assets/wordmark-light.png +0 -0
- package/brands/next/assets/wordmark.svg +7 -0
- package/brands/next/fonts/FKRomanStandard-Light.ttf +0 -0
- package/brands/next/fonts/OFL-OverusedGrotesk.txt +93 -0
- package/brands/next/fonts/OverusedGrotesk-Italic.ttf +0 -0
- package/brands/next/fonts/OverusedGrotesk-Medium.ttf +0 -0
- package/brands/next/fonts/OverusedGrotesk-MediumItalic.ttf +0 -0
- package/brands/next/fonts/OverusedGrotesk-Roman.ttf +0 -0
- package/brands/next/fonts/OverusedGrotesk-SemiBold.ttf +0 -0
- package/brands/next/fonts/OverusedGrotesk-SemiBoldItalic.ttf +0 -0
- package/brands/next/fonts/faces.json +27 -0
- package/brands/next/lib/glyphs.js +89 -0
- package/brands/next/lib/measure.js +121 -0
- package/brands/next/lib/pdf.js +597 -0
- package/brands/next/lib/ttf.py +169 -0
- package/brands/next/lib/wandxml.py +37 -0
- package/brands/next/tokens.json +174 -0
- package/examples/gallery/job.mjs +83 -0
- package/examples/overview/job.mjs +99 -0
- package/lib/brand.js +135 -0
- package/lib/components.js +313 -0
- package/lib/content.js +66 -0
- package/lib/engine.js +280 -0
- package/lib/html_export.js +71 -0
- package/lib/pptx.js +446 -0
- package/lib/surfaces.js +62 -0
- package/package.json +17 -4
- package/templates/card.mjs +30 -0
- package/templates/page.mjs +52 -0
- package/templates/slide.mjs +46 -0
- package/tools/embed_fonts.py +154 -0
- package/wand.js +179 -0
- package/README.md +0 -3
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ttf.py — the ~1% of TrueType that embed_fonts.py needs, with no fontTools.
|
|
3
|
+
|
|
4
|
+
Reads `head` and `OS/2` for the fields an EOT header carries, and rewrites the
|
|
5
|
+
`name` table so a face reports the family we address it by. Weight in this
|
|
6
|
+
system is carried by the family name — `Geist SemiBold` regular, not `Geist`
|
|
7
|
+
bold — so retagging is not cosmetic: without it PowerPoint resolves four of the
|
|
8
|
+
five families to the same face.
|
|
9
|
+
|
|
10
|
+
Everything else in the font is copied through untouched.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import struct
|
|
14
|
+
|
|
15
|
+
_HEAD_CHECKSUM_ADJ = 8 # offset of checkSumAdjustment within `head`
|
|
16
|
+
_MAGIC = 0xB1B0AFBA
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TTFError(ValueError):
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class TTF:
|
|
24
|
+
def __init__(self, data):
|
|
25
|
+
if len(data) < 12:
|
|
26
|
+
raise TTFError("not a font: too short")
|
|
27
|
+
tag = data[:4]
|
|
28
|
+
if tag not in (b"\x00\x01\x00\x00", b"true", b"ttcf", b"OTTO"):
|
|
29
|
+
raise TTFError(f"unrecognised sfnt tag {tag!r}")
|
|
30
|
+
if tag == b"ttcf":
|
|
31
|
+
raise TTFError("font collections (.ttc) are not supported — pass a single face")
|
|
32
|
+
self.data = data
|
|
33
|
+
self.sfnt = tag
|
|
34
|
+
(num,) = struct.unpack(">H", data[4:6])
|
|
35
|
+
self.tables = {}
|
|
36
|
+
for i in range(num):
|
|
37
|
+
off = 12 + i * 16
|
|
38
|
+
t, csum, o, ln = struct.unpack(">4sIII", data[off:off + 16])
|
|
39
|
+
self.tables[t] = (o, ln, csum)
|
|
40
|
+
|
|
41
|
+
# -- reading -----------------------------------------------------------
|
|
42
|
+
|
|
43
|
+
def table(self, tag):
|
|
44
|
+
if isinstance(tag, str):
|
|
45
|
+
tag = tag.encode()
|
|
46
|
+
if tag not in self.tables:
|
|
47
|
+
raise TTFError(f"font has no {tag.decode()} table")
|
|
48
|
+
o, ln, _ = self.tables[tag]
|
|
49
|
+
return self.data[o:o + ln]
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def check_sum_adjustment(self):
|
|
53
|
+
return struct.unpack(">I", self.table("head")[8:12])[0]
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def os2(self):
|
|
57
|
+
"""The OS/2 fields the EOT header needs."""
|
|
58
|
+
t = self.table("OS/2")
|
|
59
|
+
version = struct.unpack(">H", t[0:2])[0]
|
|
60
|
+
d = {
|
|
61
|
+
"version": version,
|
|
62
|
+
"usWeightClass": struct.unpack(">H", t[4:6])[0],
|
|
63
|
+
"panose": t[32:42],
|
|
64
|
+
"ulUnicodeRange": struct.unpack(">IIII", t[42:58]),
|
|
65
|
+
"fsSelection": struct.unpack(">H", t[62:64])[0],
|
|
66
|
+
}
|
|
67
|
+
# code page ranges only exist from version 1
|
|
68
|
+
d["ulCodePageRange"] = struct.unpack(">II", t[78:86]) if version >= 1 and len(t) >= 86 else (0, 0)
|
|
69
|
+
return d
|
|
70
|
+
|
|
71
|
+
def names(self):
|
|
72
|
+
"""{nameID: string} for the Windows/Unicode records, best effort."""
|
|
73
|
+
t = self.table("name")
|
|
74
|
+
count, storage = struct.unpack(">HH", t[2:6])
|
|
75
|
+
out = {}
|
|
76
|
+
for i in range(count):
|
|
77
|
+
p = 6 + i * 12
|
|
78
|
+
plat, enc, lang, nid, ln, off = struct.unpack(">HHHHHH", t[p:p + 12])
|
|
79
|
+
raw = t[storage + off: storage + off + ln]
|
|
80
|
+
try:
|
|
81
|
+
s = raw.decode("utf-16-be") if plat == 3 or (plat == 0) else raw.decode("latin-1")
|
|
82
|
+
except UnicodeDecodeError:
|
|
83
|
+
continue
|
|
84
|
+
out.setdefault(nid, s)
|
|
85
|
+
return out
|
|
86
|
+
|
|
87
|
+
# -- writing -----------------------------------------------------------
|
|
88
|
+
|
|
89
|
+
def retagged(self, family, subfamily, full, postscript):
|
|
90
|
+
"""Return new font bytes with name IDs 1/2/4/6 replaced."""
|
|
91
|
+
replace = {1: family, 2: subfamily, 4: full, 6: postscript}
|
|
92
|
+
name = _rebuild_name(self.table("name"), replace)
|
|
93
|
+
return _reassemble(self, {b"name": name})
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _rebuild_name(t, replace):
|
|
97
|
+
count, storage = struct.unpack(">HH", t[2:6])
|
|
98
|
+
records, strings, cursor = [], bytearray(), 0
|
|
99
|
+
|
|
100
|
+
for i in range(count):
|
|
101
|
+
p = 6 + i * 12
|
|
102
|
+
plat, enc, lang, nid, ln, off = struct.unpack(">HHHHHH", t[p:p + 12])
|
|
103
|
+
if nid in replace:
|
|
104
|
+
s = replace[nid]
|
|
105
|
+
raw = s.encode("utf-16-be") if plat in (0, 3) else s.encode("latin-1", "replace")
|
|
106
|
+
else:
|
|
107
|
+
raw = t[storage + off: storage + off + ln]
|
|
108
|
+
records.append((plat, enc, lang, nid, len(raw), cursor))
|
|
109
|
+
strings += raw
|
|
110
|
+
cursor += len(raw)
|
|
111
|
+
|
|
112
|
+
# sort order is required by the spec: platform, encoding, language, name
|
|
113
|
+
records.sort(key=lambda r: (r[0], r[1], r[2], r[3]))
|
|
114
|
+
head = struct.pack(">HHH", 0, len(records), 6 + len(records) * 12)
|
|
115
|
+
body = b"".join(struct.pack(">HHHHHH", *r) for r in records)
|
|
116
|
+
return head + body + bytes(strings)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _checksum(b):
|
|
120
|
+
if len(b) % 4:
|
|
121
|
+
b = b + b"\0" * (4 - len(b) % 4)
|
|
122
|
+
return sum(struct.unpack(f">{len(b)//4}I", b)) & 0xFFFFFFFF
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _reassemble(font, overrides):
|
|
126
|
+
"""Rewrite the whole sfnt with some tables replaced, fixing every offset,
|
|
127
|
+
every table checksum and the head checkSumAdjustment."""
|
|
128
|
+
tags = sorted(font.tables)
|
|
129
|
+
parts = {}
|
|
130
|
+
for t in tags:
|
|
131
|
+
parts[t] = overrides.get(t, font.table(t))
|
|
132
|
+
|
|
133
|
+
# head's checkSumAdjustment must be zero while the file checksum is taken
|
|
134
|
+
head = bytearray(parts[b"head"])
|
|
135
|
+
head[_HEAD_CHECKSUM_ADJ:_HEAD_CHECKSUM_ADJ + 4] = b"\0\0\0\0"
|
|
136
|
+
parts[b"head"] = bytes(head)
|
|
137
|
+
|
|
138
|
+
n = len(tags)
|
|
139
|
+
# binary-search fields the spec wants present; readers ignore them but
|
|
140
|
+
# validators complain when they are wrong
|
|
141
|
+
entry_selector = max(n.bit_length() - 1, 0)
|
|
142
|
+
search_range = (1 << entry_selector) * 16
|
|
143
|
+
out = bytearray(struct.pack(">4sHHHH", font.sfnt, n, search_range,
|
|
144
|
+
entry_selector, n * 16 - search_range))
|
|
145
|
+
|
|
146
|
+
offset = 12 + n * 16
|
|
147
|
+
directory, body = bytearray(), bytearray()
|
|
148
|
+
for t in tags:
|
|
149
|
+
d = parts[t]
|
|
150
|
+
directory += struct.pack(">4sIII", t, _checksum(d), offset, len(d))
|
|
151
|
+
body += d
|
|
152
|
+
pad = (-len(d)) % 4
|
|
153
|
+
body += b"\0" * pad
|
|
154
|
+
offset += len(d) + pad
|
|
155
|
+
|
|
156
|
+
out += directory + body
|
|
157
|
+
adj = (_MAGIC - _checksum(bytes(out))) & 0xFFFFFFFF
|
|
158
|
+
|
|
159
|
+
head_off = struct.unpack(">I", out[12 + tags.index(b"head") * 16 + 8:
|
|
160
|
+
12 + tags.index(b"head") * 16 + 12])[0]
|
|
161
|
+
out[head_off + _HEAD_CHECKSUM_ADJ: head_off + _HEAD_CHECKSUM_ADJ + 4] = struct.pack(">I", adj)
|
|
162
|
+
return bytes(out)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def load(path):
|
|
166
|
+
with open(path, "rb") as f:
|
|
167
|
+
return TTF(f.read())
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""
|
|
2
|
+
wandxml.py — XML parsing that works with nothing installed.
|
|
3
|
+
|
|
4
|
+
The kit has to run wherever someone unzips it. `defusedxml` is the better
|
|
5
|
+
parser and we use it when it's there, but requiring a pip install to get past
|
|
6
|
+
Phase 0 means the engine is unusable in exactly the situation it was built for:
|
|
7
|
+
a fresh container with a zip and a .pptx in it.
|
|
8
|
+
|
|
9
|
+
The stdlib fallback is guarded against the one attack that matters for a parser
|
|
10
|
+
pointed at an untrusted .pptx — entity expansion — by refusing any document with
|
|
11
|
+
a DOCTYPE. Office files never have one.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
from defusedxml import minidom as _md
|
|
16
|
+
HARDENED = True
|
|
17
|
+
except ImportError: # stdlib fallback
|
|
18
|
+
from xml.dom import minidom as _md
|
|
19
|
+
HARDENED = False
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class UnsafeXML(ValueError):
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def parse(data):
|
|
27
|
+
"""Parse .pptx part bytes (or str) into a minidom Document."""
|
|
28
|
+
probe = data[:8192]
|
|
29
|
+
if isinstance(probe, bytes):
|
|
30
|
+
probe = probe.decode("utf-8", "ignore")
|
|
31
|
+
if not HARDENED and ("<!DOCTYPE" in probe or "<!ENTITY" in probe):
|
|
32
|
+
raise UnsafeXML(
|
|
33
|
+
"document declares a DOCTYPE or ENTITY. Office parts never do. "
|
|
34
|
+
"Refusing to parse it with the stdlib parser — `pip install defusedxml` "
|
|
35
|
+
"if this file is genuinely trusted."
|
|
36
|
+
)
|
|
37
|
+
return _md.parseString(data)
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_": "The current brand as values a kit can draw with: the swatch is BRAND.md's table, measured from the Vivicta and Kearney decks; `roles` names what each value is for, once per ground, so a component asks for `ink` or `accent` and never for a hex. The studio kit (power-prompts/studio) reads this file; BRAND.md documents usage. If a hex here and in BRAND.md ever differ, BRAND.md is right and this file has drifted.",
|
|
3
|
+
"name": "current",
|
|
4
|
+
"title": "Wand, current brand (Geist)",
|
|
5
|
+
"swatch": {
|
|
6
|
+
"accent": "8B7CF6",
|
|
7
|
+
"accentDeep": "6C5CE7",
|
|
8
|
+
"accentSoft": "9481FF",
|
|
9
|
+
"accentPale": "DCD6F5",
|
|
10
|
+
"bgDark": "240F48",
|
|
11
|
+
"card": "291D5A",
|
|
12
|
+
"cardStroke": "5B4BB0",
|
|
13
|
+
"cardMuted": "1B1738",
|
|
14
|
+
"cardMutedStroke": "3A2E63",
|
|
15
|
+
"cardEmphFlat": "251C63",
|
|
16
|
+
"inset": "1A1033",
|
|
17
|
+
"eyebrow": "A78BFA",
|
|
18
|
+
"label": "8F86B8",
|
|
19
|
+
"lede": "AA9BFF",
|
|
20
|
+
"ledeSoft": "C4B5F4",
|
|
21
|
+
"footerDark": "746B98",
|
|
22
|
+
"bodyDark": "F5F5F5",
|
|
23
|
+
"mutedDark": "BBBBBB",
|
|
24
|
+
"bodyDarkAlt": "C6BFE4",
|
|
25
|
+
"emphRow": "4D2E8C",
|
|
26
|
+
"emphRowStroke": "7557AE",
|
|
27
|
+
"bgLight": "F8F6FB",
|
|
28
|
+
"inkLight": "1D1A33",
|
|
29
|
+
"bodyLight": "5C5779",
|
|
30
|
+
"mutedLight": "555077",
|
|
31
|
+
"cardLight": "FFFFFF",
|
|
32
|
+
"surface": "EBE8F8",
|
|
33
|
+
"track": "E9E6F5",
|
|
34
|
+
"divider": "E4E0F2",
|
|
35
|
+
"footerLight": "999999",
|
|
36
|
+
"white": "FFFFFF"
|
|
37
|
+
},
|
|
38
|
+
"roles": {
|
|
39
|
+
"light": {
|
|
40
|
+
"bg": "F8F6FB",
|
|
41
|
+
"paper": "FFFFFF",
|
|
42
|
+
"ink": "1D1A33",
|
|
43
|
+
"text": "5C5779",
|
|
44
|
+
"soft": "555077",
|
|
45
|
+
"muted": "999999",
|
|
46
|
+
"accent": "8B7CF6",
|
|
47
|
+
"accentText": "6C5CE7",
|
|
48
|
+
"label": "6C5CE7",
|
|
49
|
+
"emph": "251C63",
|
|
50
|
+
"emphInk": "FFFFFF",
|
|
51
|
+
"emphText": "DCD6F5",
|
|
52
|
+
"emphAccent": "AA9BFF",
|
|
53
|
+
"stroke": "E4E0F2",
|
|
54
|
+
"rule": "E4E0F2",
|
|
55
|
+
"track": "E9E6F5",
|
|
56
|
+
"surface": "EBE8F8"
|
|
57
|
+
},
|
|
58
|
+
"dark": {
|
|
59
|
+
"bg": "240F48",
|
|
60
|
+
"paper": "291D5A",
|
|
61
|
+
"ink": "FFFFFF",
|
|
62
|
+
"text": "F5F5F5",
|
|
63
|
+
"soft": "BBBBBB",
|
|
64
|
+
"muted": "746B98",
|
|
65
|
+
"accent": "9481FF",
|
|
66
|
+
"accentText": "9481FF",
|
|
67
|
+
"label": "A78BFA",
|
|
68
|
+
"emph": "4D2E8C",
|
|
69
|
+
"emphInk": "FFFFFF",
|
|
70
|
+
"emphText": "DCD6F5",
|
|
71
|
+
"emphAccent": "C4B5F4",
|
|
72
|
+
"stroke": "5B4BB0",
|
|
73
|
+
"rule": "3A2E63",
|
|
74
|
+
"track": "1A1033",
|
|
75
|
+
"surface": "1A1033"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"faces": {
|
|
79
|
+
"display": {
|
|
80
|
+
"family": "Geist",
|
|
81
|
+
"weight": 600,
|
|
82
|
+
"tracking": -0.02,
|
|
83
|
+
"leading": 1.08
|
|
84
|
+
},
|
|
85
|
+
"body": {
|
|
86
|
+
"family": "Geist",
|
|
87
|
+
"weight": 400,
|
|
88
|
+
"tracking": 0,
|
|
89
|
+
"leading": 1.6
|
|
90
|
+
},
|
|
91
|
+
"label": {
|
|
92
|
+
"family": "Geist",
|
|
93
|
+
"weight": 600,
|
|
94
|
+
"tracking": 0.18,
|
|
95
|
+
"leading": 1.2,
|
|
96
|
+
"caps": true
|
|
97
|
+
},
|
|
98
|
+
"files": [
|
|
99
|
+
{
|
|
100
|
+
"family": "Geist",
|
|
101
|
+
"weight": 300,
|
|
102
|
+
"italic": false,
|
|
103
|
+
"file": "Geist-Light.ttf",
|
|
104
|
+
"pptx": "Geist Light"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"family": "Geist",
|
|
108
|
+
"weight": 300,
|
|
109
|
+
"italic": true,
|
|
110
|
+
"file": "Geist-LightItalic.ttf",
|
|
111
|
+
"pptx": "Geist Light"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"family": "Geist",
|
|
115
|
+
"weight": 400,
|
|
116
|
+
"italic": false,
|
|
117
|
+
"file": "Geist-Regular.ttf",
|
|
118
|
+
"pptx": "Geist"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"family": "Geist",
|
|
122
|
+
"weight": 400,
|
|
123
|
+
"italic": true,
|
|
124
|
+
"file": "Geist-Italic.ttf",
|
|
125
|
+
"pptx": "Geist"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"family": "Geist",
|
|
129
|
+
"weight": 500,
|
|
130
|
+
"italic": false,
|
|
131
|
+
"file": "Geist-Medium.ttf",
|
|
132
|
+
"pptx": "Geist Medium"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"family": "Geist",
|
|
136
|
+
"weight": 500,
|
|
137
|
+
"italic": true,
|
|
138
|
+
"file": "Geist-MediumItalic.ttf",
|
|
139
|
+
"pptx": "Geist Medium"
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"family": "Geist",
|
|
143
|
+
"weight": 600,
|
|
144
|
+
"italic": false,
|
|
145
|
+
"file": "Geist-SemiBold.ttf",
|
|
146
|
+
"pptx": "Geist SemiBold"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"family": "Geist",
|
|
150
|
+
"weight": 600,
|
|
151
|
+
"italic": true,
|
|
152
|
+
"file": "Geist-SemiBoldItalic.ttf",
|
|
153
|
+
"pptx": "Geist SemiBold"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"family": "Geist",
|
|
157
|
+
"weight": 700,
|
|
158
|
+
"italic": false,
|
|
159
|
+
"file": "Geist-Bold.ttf",
|
|
160
|
+
"pptx": "Geist Bold"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"family": "Geist",
|
|
164
|
+
"weight": 700,
|
|
165
|
+
"italic": true,
|
|
166
|
+
"file": "Geist-BoldItalic.ttf",
|
|
167
|
+
"pptx": "Geist Bold"
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"family": "Geist",
|
|
171
|
+
"weight": 800,
|
|
172
|
+
"italic": false,
|
|
173
|
+
"file": "Geist-ExtraBold.ttf",
|
|
174
|
+
"pptx": "Geist ExtraBold"
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
"family": "Geist",
|
|
178
|
+
"weight": 800,
|
|
179
|
+
"italic": true,
|
|
180
|
+
"file": "Geist-ExtraBoldItalic.ttf",
|
|
181
|
+
"pptx": "Geist ExtraBold"
|
|
182
|
+
}
|
|
183
|
+
],
|
|
184
|
+
"license": "Geist: SIL OFL 1.1 (npm geist@1.7.2)"
|
|
185
|
+
},
|
|
186
|
+
"shape": {
|
|
187
|
+
"radius": 1,
|
|
188
|
+
"cardStroke": 1,
|
|
189
|
+
"emphStroke": 0
|
|
190
|
+
},
|
|
191
|
+
"art": {
|
|
192
|
+
"cover": "bg-cover-dark.png",
|
|
193
|
+
"overlay": "bg-overlay-dark.png",
|
|
194
|
+
"statement": "bg-statement-dark.png",
|
|
195
|
+
"closing": "closing-art.png",
|
|
196
|
+
"coverArt": "cover-art.png",
|
|
197
|
+
"divider": "divider-art.png",
|
|
198
|
+
"orb": "orb-cover.png",
|
|
199
|
+
"glow": "orb-glow.png",
|
|
200
|
+
"markOnLight": "mark-dark.png",
|
|
201
|
+
"markOnDark": "mark-dark.png",
|
|
202
|
+
"wordmarkOnLight": "wordmark-dark.png",
|
|
203
|
+
"wordmarkOnDark": "wordmark-white.png",
|
|
204
|
+
"markInvertOnDark": true
|
|
205
|
+
}
|
|
206
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Glyphs — Lucide
|
|
2
|
+
|
|
3
|
+
75 icons from [Lucide](https://lucide.dev) v0.469.0, **ISC licensed** (permissive:
|
|
4
|
+
use, modify and redistribute, keep the notice). They replace the numbered PNGs
|
|
5
|
+
that were reverse-extracted from a reference deck.
|
|
6
|
+
|
|
7
|
+
Two problems they fix, both of which were standing known gaps:
|
|
8
|
+
|
|
9
|
+
**Polarity.** The old glyphs were baked white or baked accent, so a white one on
|
|
10
|
+
a light-theme `surface` tile was invisible. These are single-colour stroke SVGs
|
|
11
|
+
with `stroke="currentColor"`, and the kit substitutes the theme's ink colour at
|
|
12
|
+
build time. There is no variant to pick and nothing to get wrong.
|
|
13
|
+
|
|
14
|
+
**Meaning.** They have names. A spec says `icon: "shield-check"`, not
|
|
15
|
+
`icon: "icon-17.png"`. `index.json` groups them by what a deck actually needs —
|
|
16
|
+
governance, workforce, platform, process, outcome, signal.
|
|
17
|
+
|
|
18
|
+
## How they reach the deck
|
|
19
|
+
|
|
20
|
+
As vector. pptxgenjs writes the OOXML `asvg:svgBlip` extension with a raster
|
|
21
|
+
fallback, so PowerPoint 2016+ renders the SVG and anything older gets the PNG.
|
|
22
|
+
Nothing is rasterised at build time, so the kit still needs no native
|
|
23
|
+
dependency.
|
|
24
|
+
|
|
25
|
+
## The old set
|
|
26
|
+
|
|
27
|
+
`../icons/*.png` is still there and still works — every existing spec references
|
|
28
|
+
those filenames. New specs should use glyph names. The two sets can coexist
|
|
29
|
+
indefinitely; `iconTile` resolves a name first and falls back to a filename.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!-- @license lucide-static v0.469.0 - ISC -->
|
|
2
|
+
<svg
|
|
3
|
+
class="lucide lucide-activity"
|
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
+
width="24"
|
|
6
|
+
height="24"
|
|
7
|
+
viewBox="0 0 24 24"
|
|
8
|
+
fill="none"
|
|
9
|
+
stroke="currentColor"
|
|
10
|
+
stroke-width="2"
|
|
11
|
+
stroke-linecap="round"
|
|
12
|
+
stroke-linejoin="round"
|
|
13
|
+
>
|
|
14
|
+
<path d="M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2" />
|
|
15
|
+
</svg>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!-- @license lucide-static v0.469.0 - ISC -->
|
|
2
|
+
<svg
|
|
3
|
+
class="lucide lucide-atom"
|
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
+
width="24"
|
|
6
|
+
height="24"
|
|
7
|
+
viewBox="0 0 24 24"
|
|
8
|
+
fill="none"
|
|
9
|
+
stroke="currentColor"
|
|
10
|
+
stroke-width="2"
|
|
11
|
+
stroke-linecap="round"
|
|
12
|
+
stroke-linejoin="round"
|
|
13
|
+
>
|
|
14
|
+
<circle cx="12" cy="12" r="1" />
|
|
15
|
+
<path d="M20.2 20.2c2.04-2.03.02-7.36-4.5-11.9-4.54-4.52-9.87-6.54-11.9-4.5-2.04 2.03-.02 7.36 4.5 11.9 4.54 4.52 9.87 6.54 11.9 4.5Z" />
|
|
16
|
+
<path d="M15.7 15.7c4.52-4.54 6.54-9.87 4.5-11.9-2.03-2.04-7.36-.02-11.9 4.5-4.52 4.54-6.54 9.87-4.5 11.9 2.03 2.04 7.36.02 11.9-4.5Z" />
|
|
17
|
+
</svg>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<!-- @license lucide-static v0.469.0 - ISC -->
|
|
2
|
+
<svg
|
|
3
|
+
class="lucide lucide-badge-check"
|
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
+
width="24"
|
|
6
|
+
height="24"
|
|
7
|
+
viewBox="0 0 24 24"
|
|
8
|
+
fill="none"
|
|
9
|
+
stroke="currentColor"
|
|
10
|
+
stroke-width="2"
|
|
11
|
+
stroke-linecap="round"
|
|
12
|
+
stroke-linejoin="round"
|
|
13
|
+
>
|
|
14
|
+
<path d="M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z" />
|
|
15
|
+
<path d="m9 12 2 2 4-4" />
|
|
16
|
+
</svg>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<!-- @license lucide-static v0.469.0 - ISC -->
|
|
2
|
+
<svg
|
|
3
|
+
class="lucide lucide-bell"
|
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
+
width="24"
|
|
6
|
+
height="24"
|
|
7
|
+
viewBox="0 0 24 24"
|
|
8
|
+
fill="none"
|
|
9
|
+
stroke="currentColor"
|
|
10
|
+
stroke-width="2"
|
|
11
|
+
stroke-linecap="round"
|
|
12
|
+
stroke-linejoin="round"
|
|
13
|
+
>
|
|
14
|
+
<path d="M10.268 21a2 2 0 0 0 3.464 0" />
|
|
15
|
+
<path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326" />
|
|
16
|
+
</svg>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<!-- @license lucide-static v0.469.0 - ISC -->
|
|
2
|
+
<svg
|
|
3
|
+
class="lucide lucide-blocks"
|
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
+
width="24"
|
|
6
|
+
height="24"
|
|
7
|
+
viewBox="0 0 24 24"
|
|
8
|
+
fill="none"
|
|
9
|
+
stroke="currentColor"
|
|
10
|
+
stroke-width="2"
|
|
11
|
+
stroke-linecap="round"
|
|
12
|
+
stroke-linejoin="round"
|
|
13
|
+
>
|
|
14
|
+
<rect width="7" height="7" x="14" y="3" rx="1" />
|
|
15
|
+
<path d="M10 21V8a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-5a1 1 0 0 0-1-1H3" />
|
|
16
|
+
</svg>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<!-- @license lucide-static v0.469.0 - ISC -->
|
|
2
|
+
<svg
|
|
3
|
+
class="lucide lucide-book-open"
|
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
+
width="24"
|
|
6
|
+
height="24"
|
|
7
|
+
viewBox="0 0 24 24"
|
|
8
|
+
fill="none"
|
|
9
|
+
stroke="currentColor"
|
|
10
|
+
stroke-width="2"
|
|
11
|
+
stroke-linecap="round"
|
|
12
|
+
stroke-linejoin="round"
|
|
13
|
+
>
|
|
14
|
+
<path d="M12 7v14" />
|
|
15
|
+
<path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z" />
|
|
16
|
+
</svg>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<!-- @license lucide-static v0.469.0 - ISC -->
|
|
2
|
+
<svg
|
|
3
|
+
class="lucide lucide-bot"
|
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
+
width="24"
|
|
6
|
+
height="24"
|
|
7
|
+
viewBox="0 0 24 24"
|
|
8
|
+
fill="none"
|
|
9
|
+
stroke="currentColor"
|
|
10
|
+
stroke-width="2"
|
|
11
|
+
stroke-linecap="round"
|
|
12
|
+
stroke-linejoin="round"
|
|
13
|
+
>
|
|
14
|
+
<path d="M12 8V4H8" />
|
|
15
|
+
<rect width="16" height="12" x="4" y="8" rx="2" />
|
|
16
|
+
<path d="M2 14h2" />
|
|
17
|
+
<path d="M20 14h2" />
|
|
18
|
+
<path d="M15 13v2" />
|
|
19
|
+
<path d="M9 13v2" />
|
|
20
|
+
</svg>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<!-- @license lucide-static v0.469.0 - ISC -->
|
|
2
|
+
<svg
|
|
3
|
+
class="lucide lucide-boxes"
|
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
+
width="24"
|
|
6
|
+
height="24"
|
|
7
|
+
viewBox="0 0 24 24"
|
|
8
|
+
fill="none"
|
|
9
|
+
stroke="currentColor"
|
|
10
|
+
stroke-width="2"
|
|
11
|
+
stroke-linecap="round"
|
|
12
|
+
stroke-linejoin="round"
|
|
13
|
+
>
|
|
14
|
+
<path d="M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z" />
|
|
15
|
+
<path d="m7 16.5-4.74-2.85" />
|
|
16
|
+
<path d="m7 16.5 5-3" />
|
|
17
|
+
<path d="M7 16.5v5.17" />
|
|
18
|
+
<path d="M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z" />
|
|
19
|
+
<path d="m17 16.5-5-3" />
|
|
20
|
+
<path d="m17 16.5 4.74-2.85" />
|
|
21
|
+
<path d="M17 16.5v5.17" />
|
|
22
|
+
<path d="M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z" />
|
|
23
|
+
<path d="M12 8 7.26 5.15" />
|
|
24
|
+
<path d="m12 8 4.74-2.85" />
|
|
25
|
+
<path d="M12 13.5V8" />
|
|
26
|
+
</svg>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<!-- @license lucide-static v0.469.0 - ISC -->
|
|
2
|
+
<svg
|
|
3
|
+
class="lucide lucide-brain"
|
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
+
width="24"
|
|
6
|
+
height="24"
|
|
7
|
+
viewBox="0 0 24 24"
|
|
8
|
+
fill="none"
|
|
9
|
+
stroke="currentColor"
|
|
10
|
+
stroke-width="2"
|
|
11
|
+
stroke-linecap="round"
|
|
12
|
+
stroke-linejoin="round"
|
|
13
|
+
>
|
|
14
|
+
<path d="M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z" />
|
|
15
|
+
<path d="M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z" />
|
|
16
|
+
<path d="M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4" />
|
|
17
|
+
<path d="M17.599 6.5a3 3 0 0 0 .399-1.375" />
|
|
18
|
+
<path d="M6.003 5.125A3 3 0 0 0 6.401 6.5" />
|
|
19
|
+
<path d="M3.477 10.896a4 4 0 0 1 .585-.396" />
|
|
20
|
+
<path d="M19.938 10.5a4 4 0 0 1 .585.396" />
|
|
21
|
+
<path d="M6 18a4 4 0 0 1-1.967-.516" />
|
|
22
|
+
<path d="M19.967 17.484A4 4 0 0 1 18 18" />
|
|
23
|
+
</svg>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<!-- @license lucide-static v0.469.0 - ISC -->
|
|
2
|
+
<svg
|
|
3
|
+
class="lucide lucide-briefcase"
|
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
+
width="24"
|
|
6
|
+
height="24"
|
|
7
|
+
viewBox="0 0 24 24"
|
|
8
|
+
fill="none"
|
|
9
|
+
stroke="currentColor"
|
|
10
|
+
stroke-width="2"
|
|
11
|
+
stroke-linecap="round"
|
|
12
|
+
stroke-linejoin="round"
|
|
13
|
+
>
|
|
14
|
+
<path d="M16 20V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16" />
|
|
15
|
+
<rect width="20" height="14" x="2" y="6" rx="2" />
|
|
16
|
+
</svg>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<!-- @license lucide-static v0.469.0 - ISC -->
|
|
2
|
+
<svg
|
|
3
|
+
class="lucide lucide-building-2"
|
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
+
width="24"
|
|
6
|
+
height="24"
|
|
7
|
+
viewBox="0 0 24 24"
|
|
8
|
+
fill="none"
|
|
9
|
+
stroke="currentColor"
|
|
10
|
+
stroke-width="2"
|
|
11
|
+
stroke-linecap="round"
|
|
12
|
+
stroke-linejoin="round"
|
|
13
|
+
>
|
|
14
|
+
<path d="M6 22V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18Z" />
|
|
15
|
+
<path d="M6 12H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2" />
|
|
16
|
+
<path d="M18 9h2a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-2" />
|
|
17
|
+
<path d="M10 6h4" />
|
|
18
|
+
<path d="M10 10h4" />
|
|
19
|
+
<path d="M10 14h4" />
|
|
20
|
+
<path d="M10 18h4" />
|
|
21
|
+
</svg>
|