Incorporo-user commited on
Commit
8b468fc
·
verified ·
1 Parent(s): bfd2e1c

Inkvec 0.2: the presentation page, and Inkvec Studio Lite under studio/

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. README.md +41 -102
  2. fonts/inter-latin.woff2 +0 -0
  3. fonts/playfair-latin.woff2 +0 -0
  4. index.html +0 -0
  5. logolabs-mark.svg +0 -3
  6. pkg-threads/inkvec_wasm.d.ts +0 -240
  7. pkg-threads/inkvec_wasm_bg.wasm.d.ts +0 -40
  8. pkg-threads/package.json +0 -24
  9. pkg/inkvec_wasm.d.ts +0 -218
  10. pkg/inkvec_wasm_bg.wasm.d.ts +0 -33
  11. pkg/package.json +0 -24
  12. samples/1075thefan.png +0 -0
  13. samples/365retailmarkets.png +0 -0
  14. samples/adamo.png +0 -0
  15. samples/tiny.png +0 -0
  16. showcase.json +0 -0
  17. studio/LICENSE +201 -0
  18. studio/NOTICE +59 -0
  19. studio/STUDIO_THIRD_PARTY.md +501 -0
  20. studio/THIRD_PARTY.md +573 -0
  21. studio/assets/denoiser.worker-ER2QG0XM.js +1 -0
  22. studio/assets/engine.worker-Cn2MnOae.js +1 -0
  23. studio/assets/main-B-nuHqfb.css +1 -0
  24. studio/assets/main-x93uzIN_.js +0 -0
  25. studio/assets/showcase-Ip4y7DPQ.js +0 -0
  26. studio/assets/zip-DlX9-WSC.js +1 -0
  27. denoise.js → studio/denoise.js +0 -0
  28. logo.svg → studio/favicon.svg +0 -0
  29. studio/fonts/inter-latin.woff2 +0 -0
  30. studio/fonts/playfair-latin.woff2 +0 -0
  31. studio/guide/batch.html +101 -0
  32. studio/guide/export.html +117 -0
  33. studio/guide/fabricate.html +328 -0
  34. studio/guide/getting-started.html +174 -0
  35. studio/guide/guide.css +224 -0
  36. studio/guide/img/auto-chose-photo.webp +0 -0
  37. studio/guide/img/batch.webp +0 -0
  38. studio/guide/img/chooser.webp +0 -0
  39. studio/guide/img/detail-certainty.webp +0 -0
  40. studio/guide/img/export.webp +0 -0
  41. studio/guide/img/fabricate-htv-rail.webp +0 -0
  42. studio/guide/img/fabricate-laser-rail.webp +0 -0
  43. studio/guide/img/fabricate-vinyl.webp +0 -0
  44. studio/guide/img/first-run.webp +0 -0
  45. studio/guide/img/help.webp +0 -0
  46. studio/guide/img/minify.webp +0 -0
  47. studio/guide/img/overlays.webp +0 -0
  48. studio/guide/img/palette.webp +0 -0
  49. studio/guide/img/result.webp +0 -0
  50. studio/guide/img/settings.webp +0 -0
README.md CHANGED
@@ -14,105 +14,44 @@ custom_headers:
14
 
15
  # Inkvec
16
 
17
- Exact vectors from logos, icons and flat artwork, entirely in the browser. Inkvec is
18
- LogoLabs' tracer compiled to WebAssembly and served as a static page: drop an image, get an
19
- SVG, nothing leaves your machine.
20
-
21
- Boundaries land where the anti-aliasing says they are, circles come back as circles, the
22
- pieces of one colour are one path, and the number of coordinates is chosen by minimum
23
- description length rather than a tolerance slider. Across 21 cases — 14 hash-selected real
24
- icons across seven families, 4 hand-picked synthetic probes, and 3 real brand logos from an
25
- external dataset (selection fixed from the seed `crosscompare-2026-09-15-v1`) — scored
26
- against the source render, Inkvec's median colour error (dE00) is 11x lower than VTracer's
27
- default output at roughly a quarter of the coordinates; the 3 brand logos are not part of the
28
- repo, so a clean clone reproduces the other 18. Full numbers, sourced, are in the
29
- [project README](https://github.com/logolabs/inkvec#results).
30
-
31
- Damaged input — a JPEG, a WebP, something an image model decoded — can be cleaned first by
32
- the trained denoiser, which runs here on WebGPU. See [The denoiser](#the-denoiser).
33
-
34
- ## Build
35
-
36
- ```
37
- rustup target add wasm32-unknown-unknown
38
- rustup toolchain install nightly --component rust-src
39
- tools/build_wasm.sh
40
- ```
41
-
42
- That writes two packages, and `web/worker.js` picks between them at load:
43
-
44
- | | `web/pkg/` | `web/pkg-threads/` |
45
- |---|---|---|
46
- | toolchain | stable | nightly, with `std` rebuilt for atomics |
47
- | cores | one | one rayon worker per core |
48
- | needs | nothing | a cross-origin isolated page |
49
-
50
- The tracer, its arithmetic and its output are the same in both — measured, by hashing the
51
- SVGs from each: on a sixteen-core machine the threaded build is 3.7x to 4.3x faster on real
52
- logos and returns the identical bytes.
53
-
54
- Isolation is what the `custom_headers` block in this README asks the Space for. Where it is
55
- not granted the page loads the single-threaded package instead and everything still works.
56
-
57
- The page is `web/index.html`; serve it over HTTP (ES modules do not load from `file://`).
58
-
59
- ## The denoiser
60
-
61
- The `--restore` pre-pass runs in the browser as well, off by default, with the same three
62
- modes the command line has:
63
-
64
- | | |
65
- |---|---|
66
- | **No denoise** | what the page has always done |
67
- | **Auto** | trace once, measure how far the raster disagrees with its own trace where the trace claims a flat interior, denoise and retrace only above the threshold |
68
- | **On** | always denoise first |
69
-
70
- It is the same network, not a second one: `web/denoise.js` loads `restorer.onnx` from
71
- [`Logolabs/inkvec-denoiser-001`](https://huggingface.co/Logolabs/inkvec-denoiser-001) — the
72
- file the command line pulls, checked against the same SHA-256 the WebAssembly build reports —
73
- into [ONNX Runtime Web](https://onnxruntime.ai/docs/tutorials/web/), pinned to 1.30.0. WebGPU
74
- runs it where the browser has it, and ONNX Runtime's WebAssembly kernels where it does not;
75
- which one ran is on the result line.
76
-
77
- Everything around the network is the tracer's own code, reached through WebAssembly rather
78
- than rewritten in JavaScript: the compositing onto white, the pad to a multiple of 16, the
79
- crop, the quantisation to 256 levels, the extreme-snapping (`inkvec_restore::network_input`
80
- and `network_output`), the `auto` decision (`inkvec_restore::decide`) and the forced soft
81
- intake for the trace that follows. `denoise.js` turns one Float32Array into another and does
82
- nothing else.
83
-
84
- Measured against native ONNX Runtime on a 512-px JPEG, the WebAssembly kernels agree to
85
- 4.2e-7; after the 8-bit quantisation the tracer reads, one channel of one pixel in 786,432
86
- differs by one level.
87
-
88
- Turning it on downloads ONNX Runtime Web (~28 MB, from jsDelivr) and the weights (~80 MB,
89
- from Hugging Face) once; the browser caches both. The image is still never uploaded.
90
-
91
- While a run is going the page shows its steps separately — the weights (counted in bytes,
92
- because there is something real to count), the denoiser pass, and the trace — each with the
93
- time it is taking. Neither the network pass nor the trace reports anything until it is done,
94
- so their tracks sweep instead of inventing a percentage.
95
-
96
- ## Deploy
97
-
98
- This folder is the Space. Create a Space under the LogoLabs org with the **static** SDK and
99
- push these files (README, `index.html`, `worker.js`, `denoise.js`, `samples/`, the built
100
- `pkg/` and `pkg-threads/`). Build the packages with `tools/build_wasm.sh`, then upload this
101
- folder to the Space with `huggingface-cli` once you are logged in. ONNX Runtime and the
102
- denoiser weights are not part of the upload: the page fetches them at run time.
103
-
104
- ## Notes
105
-
106
- - Single-threaded in the browser (rayon runs its work on the calling thread when it cannot
107
- spawn). A 768-px logo takes about eight seconds; the native binary uses every core and is
108
- several times faster. Browser threads need cross-origin isolation headers the static SDK
109
- cannot set; a `coi-serviceworker` shim is the usual workaround if that ever matters.
110
- - Inputs above the "max dimension" setting are traced at that size and written at the
111
- original size, so a 4000-px screenshot still finishes.
112
- - The denoiser runs at the size the tracer will see — after "max dimension", after the
113
- unblock — because that is where `--restore` sits in the pipeline, and it costs what a
114
- 20-million-parameter network costs: seconds on a GPU, longer on the WebAssembly kernels.
115
- A browser whose only WebGPU adapter is a software one (SwiftShader, lavapipe) is taken as
116
- no GPU at all and the WebAssembly kernels run instead: measured in a headless Chromium, a
117
- 512-px pass those kernels finished in about eight seconds had still not returned ten
118
- minutes into the software adapter.
 
14
 
15
  # Inkvec
16
 
17
+ This Space has two pages. The front page presents Inkvec: before-and-after on real logos
18
+ with the geometry showing, the latest comparison with other tracers, what is new, and how it
19
+ works. **Inkvec Studio Lite**, under [`studio/`](studio/), is the editor itself.
20
+
21
+ ## Inkvec Studio Lite
22
+
23
+ The Inkvec Studio editor, in your browser. Drop a logo, an icon or flat artwork and get an
24
+ exact SVG back: boundaries where the anti-aliasing says they are, circles as circles, one path
25
+ per colour, and the number of coordinates chosen by minimum description length rather than a
26
+ tolerance slider. Nothing is uploaded — the tracer runs in this tab, as WebAssembly, on your
27
+ own processor.
28
+
29
+ It is the desktop app's interface and the desktop app's code, not a demo of them:
30
+
31
+ - **Vectorize** with a live draft while you move a control and the full trace once you stop,
32
+ eight presets, the Custom wizard, the measured colour difference, the palette with colour
33
+ groups, snapping to a brand palette, and export (SVG, minified SVG, PNG sizes, a favicon set,
34
+ an asset pack) as a download.
35
+ - **Minify SVG**: rewrite an SVG you already have in fewer bytes, with the difference measured.
36
+ - **Fabricate**: vinyl sheets, stickers, stencils and laser cut lines, with a preflight.
37
+ - **Clean up damage**: the trained denoiser for JPEG and screenshot damage, downloaded once
38
+ into your browser and run on your GPU where there is one (ONNX Runtime Web).
39
+
40
+ Use **Full screen** in the top bar, or **Open in its own tab** when the Space's frame will not
41
+ go full screen; its own tab also gives it every core. It is built for a laptop or desktop
42
+ screen. A logo dropped on the front page opens straight in the Studio, handed over inside
43
+ your browser.
44
+
45
+ The desktop app, **Inkvec Studio** (Windows, macOS, Linux), is the same interface plus what a
46
+ browser cannot do: folders of images in one batch, the `inkvec` command line, the right-click
47
+ menu, and traces larger than 2048 px. Releases: <https://github.com/logolabs/inkvec/releases>.
48
+
49
+ ## How it runs
50
+
51
+ The Studio's backend is a shared Rust core (`studio/core`) that the desktop app wraps in Tauri
52
+ and this page wraps in a Web Worker (`studio/wasm`). Two builds of that worker sit side by side:
53
+ one with a rayon thread pool, which needs the cross-origin isolation the headers above ask for,
54
+ and a single-threaded one for anywhere that isolation is not granted. Same code, same output.
55
+
56
+ Source, benchmarks and licences: <https://github.com/logolabs/inkvec>. Apache-2.0. Made by
57
+ LogoLabs.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fonts/inter-latin.woff2 ADDED
Binary file (48.3 kB). View file
 
fonts/playfair-latin.woff2 ADDED
Binary file (38.4 kB). View file
 
index.html CHANGED
The diff for this file is too large to render. See raw diff
 
logolabs-mark.svg DELETED
pkg-threads/inkvec_wasm.d.ts DELETED
@@ -1,240 +0,0 @@
1
- /* tslint:disable */
2
- /* eslint-disable */
3
-
4
- /**
5
- * A decoded raster, prepared for tracing and held across a denoiser round trip.
6
- *
7
- * [`prepare`] makes one, [`Intake::trace`] finishes the job, and in between the denoiser
8
- * exports hand the tensor out to the page's ONNX Runtime Web session and take its answer
9
- * back. With no denoising in between, `prepare(...).trace()` is exactly what [`trace`] does
10
- * — the same call, because [`trace`] *is* that pair.
11
- *
12
- * JavaScript owns it and must release it: `free()` after the last [`Intake::trace`], or
13
- * [`Intake::trace_once`] instead of that last trace, which consumes the intake and leaves
14
- * nothing to free. Not both -- `free()` on an intake `traceOnce` already took is a free of
15
- * a null pointer.
16
- */
17
- export class Intake {
18
- private constructor();
19
- free(): void;
20
- [Symbol.dispose](): void;
21
- /**
22
- * The tensor the denoiser network takes: composited onto white, planar, edge-padded.
23
- *
24
- * This is `inkvec_restore::network_input`, the same preparation the command line's
25
- * in-process backends do, so the browser is not a second recipe — only a second
26
- * runtime for the same `restorer.onnx`.
27
- */
28
- denoiser_input(): Float32Array;
29
- /**
30
- * How far this raster disagrees with `svg` where the trace claims a flat interior —
31
- * `inkvec_restore::decide`'s signal, and the one `--restore auto` decides on. Above
32
- * [`denoiser_threshold`] the input is treated as damaged. `undefined` when the SVG
33
- * could not be rendered or has no flat interior to measure.
34
- */
35
- residual(svg: string): number | undefined;
36
- /**
37
- * The raster as RGBA8, for showing the page what the denoiser did.
38
- */
39
- rgba8(): Uint8Array;
40
- /**
41
- * Take the network's output — the same `1 x 3 x height x width` planar layout — as the
42
- * raster to trace: cropped back to size, quantised to 256 levels, extremes snapped,
43
- * alpha carried through, all of it `inkvec_restore::network_output`.
44
- *
45
- * The trace that follows is then forced onto soft intake, as `--restore` forces it: a
46
- * denoised raster can look clean enough that the edge-width and ringing detectors no
47
- * longer open soft intake by themselves, and the network was validated with it open.
48
- */
49
- take_denoiser_output(chw: Float32Array): void;
50
- /**
51
- * Trace it, consuming the intake. `trace` when the answer is only needed once.
52
- */
53
- traceOnce(): string;
54
- /**
55
- * Trace it, without consuming: `auto` needs one trace before it can decide whether to
56
- * denoise, and keeps that trace when the input turns out to be undamaged.
57
- *
58
- * The clone this takes is the raster only. It is the price of asking for the same trace
59
- * twice, and it is small next to the trace.
60
- */
61
- trace(): string;
62
- /**
63
- * The size of the tensor [`Intake::denoiser_input`] returns, as `[width, height]`: the
64
- * raster's size rounded up to a multiple of 16, which is what the network's four 2x
65
- * downsamplings require. The tensor itself is `1 x 3 x height x width`, planar.
66
- */
67
- readonly denoiser_input_size: Uint32Array;
68
- /**
69
- * The height the tracer will see.
70
- */
71
- readonly height: number;
72
- /**
73
- * The width the tracer will see, after `max_dim` and any intake normalisation. This is
74
- * the size the denoiser runs at, which is the point of denoising here rather than
75
- * before the decode: the network must see the raster the tracer sees.
76
- */
77
- readonly width: number;
78
- }
79
-
80
- /**
81
- * The build target the contract fixtures key their SVG hashes by (`inkvec::build_target`):
82
- * `wasm32-unknown` for both builds.
83
- */
84
- export function build_target(): string;
85
-
86
- /**
87
- * Every option at its default, as a JSON object.
88
- */
89
- export function default_options_json(): string;
90
-
91
- /**
92
- * The SHA-256 the weights must hash to, so a page can refuse a truncated or tampered
93
- * download the way `inkvec_restore::pull_onnx_weights` refuses one.
94
- */
95
- export function denoiser_model_sha256(): string;
96
-
97
- /**
98
- * Where the denoiser weights come from: the same `restorer.onnx` the command line pulls,
99
- * from the same Hugging Face repository.
100
- */
101
- export function denoiser_model_url(): string;
102
-
103
- /**
104
- * The interior residual above which `auto` denoises, `inkvec_restore::Options`' default.
105
- */
106
- export function denoiser_threshold(): number;
107
-
108
- export function initThreadPool(num_threads: number): Promise<any>;
109
-
110
- /**
111
- * The JSON Schema of the options: byte for byte `bindings/options.schema.json`.
112
- */
113
- export function options_schema_json(): string;
114
-
115
- /**
116
- * Decode an image and run the pipeline up to the point the denoiser would see it, for a
117
- * caller that wants to denoise it there. The arguments are [`trace`]'s.
118
- *
119
- * `trace(bytes, ...)` is `prepare(bytes, ...).traceOnce()`; the page calls this one instead
120
- * when it has a denoiser to run in between.
121
- */
122
- export function prepare(bytes: Uint8Array, precision: number, min_area: number, colors: number, merge: number, max_dim: number, time_budget: number, no_background: boolean, minify: boolean, margin: number, content_units: boolean, cutout: boolean): Intake;
123
-
124
- /**
125
- * Whether this is the threaded build, whose pool `initThreadPool` starts.
126
- *
127
- * How many workers to start is left to JavaScript: only the page knows whether it is
128
- * allowed to (`crossOriginIsolated`) and how many cores the visitor has agreed to give it.
129
- */
130
- export function threads_available(): boolean;
131
-
132
- /**
133
- * Trace image bytes to an SVG string.
134
- *
135
- * `precision`, `min_area`, `colors`, `merge` are the tracer's quality knobs (pass the
136
- * defaults 0.1, 2, 64, 0.035 when unsure; the merge default is
137
- * `inkvec_trace::color::DEFAULT_MERGE_DISTANCE`); `max_dim` and `time_budget` bound the
138
- * work; `no_background`, `minify`, `margin`, `content_units` shape the output. `max_dim = 0`
139
- * means no cap. `cutout` is `--cutout`: an input's transparency is carried into the SVG
140
- * (holes stay holes, a flat wash keeps its opacity); it changes nothing for an opaque
141
- * input.
142
- */
143
- export function trace(bytes: Uint8Array, precision: number, min_area: number, colors: number, merge: number, max_dim: number, time_budget: number, no_background: boolean, minify: boolean, margin: number, content_units: boolean, cutout: boolean): string;
144
-
145
- /**
146
- * Trace an encoded image (PNG, JPEG, WebP, GIF, BMP or TIFF) to an SVG string, with the
147
- * options as a JSON object -- `inkvec::trace` with `inkvec::Options::from_json(options)`.
148
- * Missing keys take their defaults; `""` and `"{}"` mean all defaults.
149
- */
150
- export function trace_json(bytes: Uint8Array, options: string): string;
151
-
152
- /**
153
- * Trace raw pixels -- straight RGBA8, row-major, exactly `width * height * 4` bytes, as in
154
- * `ImageData.data` -- to an SVG string. `inkvec::trace_rgba`; the options as for
155
- * [`trace_json`]. Byte-identical to [`trace_json`] on a PNG of the same pixels.
156
- */
157
- export function trace_rgba_json(pixels: Uint8Array, width: number, height: number, options: string): string;
158
-
159
- /**
160
- * The tracer's version, for the page footer.
161
- */
162
- export function version(): string;
163
-
164
- export class wbg_rayon_PoolBuilder {
165
- private constructor();
166
- free(): void;
167
- [Symbol.dispose](): void;
168
- build(): void;
169
- numThreads(): number;
170
- receiver(): number;
171
- }
172
-
173
- export function wbg_rayon_start_worker(receiver: number): void;
174
-
175
- export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
176
-
177
- export interface InitOutput {
178
- readonly __wbg_intake_free: (a: number, b: number) => void;
179
- readonly __wbg_wbg_rayon_poolbuilder_free: (a: number, b: number) => void;
180
- readonly build_target: () => [number, number];
181
- readonly default_options_json: () => [number, number];
182
- readonly denoiser_model_sha256: () => [number, number];
183
- readonly denoiser_model_url: () => [number, number];
184
- readonly denoiser_threshold: () => number;
185
- readonly initThreadPool: (a: number) => any;
186
- readonly intake_denoiser_input: (a: number) => [number, number];
187
- readonly intake_denoiser_input_size: (a: number) => [number, number];
188
- readonly intake_height: (a: number) => number;
189
- readonly intake_residual: (a: number, b: number, c: number) => [number, number];
190
- readonly intake_rgba8: (a: number) => [number, number];
191
- readonly intake_take_denoiser_output: (a: number, b: number, c: number) => [number, number];
192
- readonly intake_trace: (a: number) => [number, number, number, number];
193
- readonly intake_traceOnce: (a: number) => [number, number, number, number];
194
- readonly intake_width: (a: number) => number;
195
- readonly options_schema_json: () => [number, number];
196
- readonly prepare: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => [number, number, number];
197
- readonly threads_available: () => number;
198
- readonly trace: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => [number, number, number, number];
199
- readonly trace_json: (a: number, b: number, c: number, d: number) => [number, number, number, number];
200
- readonly trace_rgba_json: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number];
201
- readonly version: () => [number, number];
202
- readonly wbg_rayon_poolbuilder_build: (a: number) => void;
203
- readonly wbg_rayon_poolbuilder_numThreads: (a: number) => number;
204
- readonly wbg_rayon_poolbuilder_receiver: (a: number) => number;
205
- readonly wbg_rayon_start_worker: (a: number) => void;
206
- readonly memory: WebAssembly.Memory;
207
- readonly __wbindgen_free: (a: number, b: number, c: number) => void;
208
- readonly __wbindgen_exn_store: (a: number) => void;
209
- readonly __externref_table_alloc: () => number;
210
- readonly __wbindgen_externrefs: WebAssembly.Table;
211
- readonly __wbindgen_malloc: (a: number, b: number) => number;
212
- readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
213
- readonly __externref_table_dealloc: (a: number) => void;
214
- readonly __wbindgen_thread_destroy: (a?: number, b?: number, c?: number) => void;
215
- readonly __wbindgen_start: (a: number) => void;
216
- }
217
-
218
- export type SyncInitInput = BufferSource | WebAssembly.Module;
219
-
220
- /**
221
- * Instantiates the given `module`, which can either be bytes or
222
- * a precompiled `WebAssembly.Module`.
223
- *
224
- * @param {{ module: SyncInitInput, memory?: WebAssembly.Memory, thread_stack_size?: number }} module - Passing `SyncInitInput` directly is deprecated.
225
- * @param {WebAssembly.Memory} memory - Deprecated.
226
- *
227
- * @returns {InitOutput}
228
- */
229
- export function initSync(module: { module: SyncInitInput, memory?: WebAssembly.Memory, thread_stack_size?: number } | SyncInitInput, memory?: WebAssembly.Memory): InitOutput;
230
-
231
- /**
232
- * If `module_or_path` is {RequestInfo} or {URL}, makes a request and
233
- * for everything else, calls `WebAssembly.instantiate` directly.
234
- *
235
- * @param {{ module_or_path: InitInput | Promise<InitInput>, memory?: WebAssembly.Memory, thread_stack_size?: number }} module_or_path - Passing `InitInput` directly is deprecated.
236
- * @param {WebAssembly.Memory} memory - Deprecated.
237
- *
238
- * @returns {Promise<InitOutput>}
239
- */
240
- export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput>, memory?: WebAssembly.Memory, thread_stack_size?: number } | InitInput | Promise<InitInput>, memory?: WebAssembly.Memory): Promise<InitOutput>;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pkg-threads/inkvec_wasm_bg.wasm.d.ts DELETED
@@ -1,40 +0,0 @@
1
- /* tslint:disable */
2
- /* eslint-disable */
3
- export const __wbg_intake_free: (a: number, b: number) => void;
4
- export const __wbg_wbg_rayon_poolbuilder_free: (a: number, b: number) => void;
5
- export const build_target: () => [number, number];
6
- export const default_options_json: () => [number, number];
7
- export const denoiser_model_sha256: () => [number, number];
8
- export const denoiser_model_url: () => [number, number];
9
- export const denoiser_threshold: () => number;
10
- export const initThreadPool: (a: number) => any;
11
- export const intake_denoiser_input: (a: number) => [number, number];
12
- export const intake_denoiser_input_size: (a: number) => [number, number];
13
- export const intake_height: (a: number) => number;
14
- export const intake_residual: (a: number, b: number, c: number) => [number, number];
15
- export const intake_rgba8: (a: number) => [number, number];
16
- export const intake_take_denoiser_output: (a: number, b: number, c: number) => [number, number];
17
- export const intake_trace: (a: number) => [number, number, number, number];
18
- export const intake_traceOnce: (a: number) => [number, number, number, number];
19
- export const intake_width: (a: number) => number;
20
- export const options_schema_json: () => [number, number];
21
- export const prepare: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => [number, number, number];
22
- export const threads_available: () => number;
23
- export const trace: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => [number, number, number, number];
24
- export const trace_json: (a: number, b: number, c: number, d: number) => [number, number, number, number];
25
- export const trace_rgba_json: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number];
26
- export const version: () => [number, number];
27
- export const wbg_rayon_poolbuilder_build: (a: number) => void;
28
- export const wbg_rayon_poolbuilder_numThreads: (a: number) => number;
29
- export const wbg_rayon_poolbuilder_receiver: (a: number) => number;
30
- export const wbg_rayon_start_worker: (a: number) => void;
31
- export const memory: WebAssembly.Memory;
32
- export const __wbindgen_free: (a: number, b: number, c: number) => void;
33
- export const __wbindgen_exn_store: (a: number) => void;
34
- export const __externref_table_alloc: () => number;
35
- export const __wbindgen_externrefs: WebAssembly.Table;
36
- export const __wbindgen_malloc: (a: number, b: number) => number;
37
- export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
38
- export const __externref_table_dealloc: (a: number) => void;
39
- export const __wbindgen_thread_destroy: (a?: number, b?: number, c?: number) => void;
40
- export const __wbindgen_start: (a: number) => void;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pkg-threads/package.json DELETED
@@ -1,24 +0,0 @@
1
- {
2
- "name": "inkvec-wasm",
3
- "type": "module",
4
- "collaborators": [
5
- "LogoLabs"
6
- ],
7
- "description": "Inkvec in the browser: the tracer compiled to WebAssembly",
8
- "version": "0.1.4",
9
- "license": "Apache-2.0",
10
- "repository": {
11
- "type": "git",
12
- "url": "https://github.com/logolabs/inkvec"
13
- },
14
- "files": [
15
- "inkvec_wasm_bg.wasm",
16
- "inkvec_wasm.js",
17
- "inkvec_wasm.d.ts"
18
- ],
19
- "main": "inkvec_wasm.js",
20
- "types": "inkvec_wasm.d.ts",
21
- "sideEffects": [
22
- "./snippets/*"
23
- ]
24
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pkg/inkvec_wasm.d.ts DELETED
@@ -1,218 +0,0 @@
1
- /* tslint:disable */
2
- /* eslint-disable */
3
-
4
- /**
5
- * A decoded raster, prepared for tracing and held across a denoiser round trip.
6
- *
7
- * [`prepare`] makes one, [`Intake::trace`] finishes the job, and in between the denoiser
8
- * exports hand the tensor out to the page's ONNX Runtime Web session and take its answer
9
- * back. With no denoising in between, `prepare(...).trace()` is exactly what [`trace`] does
10
- * — the same call, because [`trace`] *is* that pair.
11
- *
12
- * JavaScript owns it and must release it: `free()` after the last [`Intake::trace`], or
13
- * [`Intake::trace_once`] instead of that last trace, which consumes the intake and leaves
14
- * nothing to free. Not both -- `free()` on an intake `traceOnce` already took is a free of
15
- * a null pointer.
16
- */
17
- export class Intake {
18
- private constructor();
19
- free(): void;
20
- [Symbol.dispose](): void;
21
- /**
22
- * The tensor the denoiser network takes: composited onto white, planar, edge-padded.
23
- *
24
- * This is `inkvec_restore::network_input`, the same preparation the command line's
25
- * in-process backends do, so the browser is not a second recipe — only a second
26
- * runtime for the same `restorer.onnx`.
27
- */
28
- denoiser_input(): Float32Array;
29
- /**
30
- * How far this raster disagrees with `svg` where the trace claims a flat interior —
31
- * `inkvec_restore::decide`'s signal, and the one `--restore auto` decides on. Above
32
- * [`denoiser_threshold`] the input is treated as damaged. `undefined` when the SVG
33
- * could not be rendered or has no flat interior to measure.
34
- */
35
- residual(svg: string): number | undefined;
36
- /**
37
- * The raster as RGBA8, for showing the page what the denoiser did.
38
- */
39
- rgba8(): Uint8Array;
40
- /**
41
- * Take the network's output — the same `1 x 3 x height x width` planar layout — as the
42
- * raster to trace: cropped back to size, quantised to 256 levels, extremes snapped,
43
- * alpha carried through, all of it `inkvec_restore::network_output`.
44
- *
45
- * The trace that follows is then forced onto soft intake, as `--restore` forces it: a
46
- * denoised raster can look clean enough that the edge-width and ringing detectors no
47
- * longer open soft intake by themselves, and the network was validated with it open.
48
- */
49
- take_denoiser_output(chw: Float32Array): void;
50
- /**
51
- * Trace it, consuming the intake. `trace` when the answer is only needed once.
52
- */
53
- traceOnce(): string;
54
- /**
55
- * Trace it, without consuming: `auto` needs one trace before it can decide whether to
56
- * denoise, and keeps that trace when the input turns out to be undamaged.
57
- *
58
- * The clone this takes is the raster only. It is the price of asking for the same trace
59
- * twice, and it is small next to the trace.
60
- */
61
- trace(): string;
62
- /**
63
- * The size of the tensor [`Intake::denoiser_input`] returns, as `[width, height]`: the
64
- * raster's size rounded up to a multiple of 16, which is what the network's four 2x
65
- * downsamplings require. The tensor itself is `1 x 3 x height x width`, planar.
66
- */
67
- readonly denoiser_input_size: Uint32Array;
68
- /**
69
- * The height the tracer will see.
70
- */
71
- readonly height: number;
72
- /**
73
- * The width the tracer will see, after `max_dim` and any intake normalisation. This is
74
- * the size the denoiser runs at, which is the point of denoising here rather than
75
- * before the decode: the network must see the raster the tracer sees.
76
- */
77
- readonly width: number;
78
- }
79
-
80
- /**
81
- * The build target the contract fixtures key their SVG hashes by (`inkvec::build_target`):
82
- * `wasm32-unknown` for both builds.
83
- */
84
- export function build_target(): string;
85
-
86
- /**
87
- * Every option at its default, as a JSON object.
88
- */
89
- export function default_options_json(): string;
90
-
91
- /**
92
- * The SHA-256 the weights must hash to, so a page can refuse a truncated or tampered
93
- * download the way `inkvec_restore::pull_onnx_weights` refuses one.
94
- */
95
- export function denoiser_model_sha256(): string;
96
-
97
- /**
98
- * Where the denoiser weights come from: the same `restorer.onnx` the command line pulls,
99
- * from the same Hugging Face repository.
100
- */
101
- export function denoiser_model_url(): string;
102
-
103
- /**
104
- * The interior residual above which `auto` denoises, `inkvec_restore::Options`' default.
105
- */
106
- export function denoiser_threshold(): number;
107
-
108
- /**
109
- * The JSON Schema of the options: byte for byte `bindings/options.schema.json`.
110
- */
111
- export function options_schema_json(): string;
112
-
113
- /**
114
- * Decode an image and run the pipeline up to the point the denoiser would see it, for a
115
- * caller that wants to denoise it there. The arguments are [`trace`]'s.
116
- *
117
- * `trace(bytes, ...)` is `prepare(bytes, ...).traceOnce()`; the page calls this one instead
118
- * when it has a denoiser to run in between.
119
- */
120
- export function prepare(bytes: Uint8Array, precision: number, min_area: number, colors: number, merge: number, max_dim: number, time_budget: number, no_background: boolean, minify: boolean, margin: number, content_units: boolean, cutout: boolean): Intake;
121
-
122
- /**
123
- * Whether this is the threaded build, whose pool `initThreadPool` starts.
124
- *
125
- * How many workers to start is left to JavaScript: only the page knows whether it is
126
- * allowed to (`crossOriginIsolated`) and how many cores the visitor has agreed to give it.
127
- */
128
- export function threads_available(): boolean;
129
-
130
- /**
131
- * Trace image bytes to an SVG string.
132
- *
133
- * `precision`, `min_area`, `colors`, `merge` are the tracer's quality knobs (pass the
134
- * defaults 0.1, 2, 64, 0.035 when unsure; the merge default is
135
- * `inkvec_trace::color::DEFAULT_MERGE_DISTANCE`); `max_dim` and `time_budget` bound the
136
- * work; `no_background`, `minify`, `margin`, `content_units` shape the output. `max_dim = 0`
137
- * means no cap. `cutout` is `--cutout`: an input's transparency is carried into the SVG
138
- * (holes stay holes, a flat wash keeps its opacity); it changes nothing for an opaque
139
- * input.
140
- */
141
- export function trace(bytes: Uint8Array, precision: number, min_area: number, colors: number, merge: number, max_dim: number, time_budget: number, no_background: boolean, minify: boolean, margin: number, content_units: boolean, cutout: boolean): string;
142
-
143
- /**
144
- * Trace an encoded image (PNG, JPEG, WebP, GIF, BMP or TIFF) to an SVG string, with the
145
- * options as a JSON object -- `inkvec::trace` with `inkvec::Options::from_json(options)`.
146
- * Missing keys take their defaults; `""` and `"{}"` mean all defaults.
147
- */
148
- export function trace_json(bytes: Uint8Array, options: string): string;
149
-
150
- /**
151
- * Trace raw pixels -- straight RGBA8, row-major, exactly `width * height * 4` bytes, as in
152
- * `ImageData.data` -- to an SVG string. `inkvec::trace_rgba`; the options as for
153
- * [`trace_json`]. Byte-identical to [`trace_json`] on a PNG of the same pixels.
154
- */
155
- export function trace_rgba_json(pixels: Uint8Array, width: number, height: number, options: string): string;
156
-
157
- /**
158
- * The tracer's version, for the page footer.
159
- */
160
- export function version(): string;
161
-
162
- export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
163
-
164
- export interface InitOutput {
165
- readonly memory: WebAssembly.Memory;
166
- readonly __wbg_intake_free: (a: number, b: number) => void;
167
- readonly build_target: () => [number, number];
168
- readonly default_options_json: () => [number, number];
169
- readonly denoiser_model_sha256: () => [number, number];
170
- readonly denoiser_model_url: () => [number, number];
171
- readonly denoiser_threshold: () => number;
172
- readonly intake_denoiser_input: (a: number) => [number, number];
173
- readonly intake_denoiser_input_size: (a: number) => [number, number];
174
- readonly intake_height: (a: number) => number;
175
- readonly intake_residual: (a: number, b: number, c: number) => [number, number];
176
- readonly intake_rgba8: (a: number) => [number, number];
177
- readonly intake_take_denoiser_output: (a: number, b: number, c: number) => [number, number];
178
- readonly intake_trace: (a: number) => [number, number, number, number];
179
- readonly intake_traceOnce: (a: number) => [number, number, number, number];
180
- readonly intake_width: (a: number) => number;
181
- readonly options_schema_json: () => [number, number];
182
- readonly prepare: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => [number, number, number];
183
- readonly threads_available: () => number;
184
- readonly trace: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => [number, number, number, number];
185
- readonly trace_json: (a: number, b: number, c: number, d: number) => [number, number, number, number];
186
- readonly trace_rgba_json: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number];
187
- readonly version: () => [number, number];
188
- readonly __wbindgen_free: (a: number, b: number, c: number) => void;
189
- readonly __wbindgen_exn_store: (a: number) => void;
190
- readonly __externref_table_alloc: () => number;
191
- readonly __wbindgen_externrefs: WebAssembly.Table;
192
- readonly __wbindgen_malloc: (a: number, b: number) => number;
193
- readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
194
- readonly __externref_table_dealloc: (a: number) => void;
195
- readonly __wbindgen_start: () => void;
196
- }
197
-
198
- export type SyncInitInput = BufferSource | WebAssembly.Module;
199
-
200
- /**
201
- * Instantiates the given `module`, which can either be bytes or
202
- * a precompiled `WebAssembly.Module`.
203
- *
204
- * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
205
- *
206
- * @returns {InitOutput}
207
- */
208
- export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
209
-
210
- /**
211
- * If `module_or_path` is {RequestInfo} or {URL}, makes a request and
212
- * for everything else, calls `WebAssembly.instantiate` directly.
213
- *
214
- * @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
215
- *
216
- * @returns {Promise<InitOutput>}
217
- */
218
- export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pkg/inkvec_wasm_bg.wasm.d.ts DELETED
@@ -1,33 +0,0 @@
1
- /* tslint:disable */
2
- /* eslint-disable */
3
- export const memory: WebAssembly.Memory;
4
- export const __wbg_intake_free: (a: number, b: number) => void;
5
- export const build_target: () => [number, number];
6
- export const default_options_json: () => [number, number];
7
- export const denoiser_model_sha256: () => [number, number];
8
- export const denoiser_model_url: () => [number, number];
9
- export const denoiser_threshold: () => number;
10
- export const intake_denoiser_input: (a: number) => [number, number];
11
- export const intake_denoiser_input_size: (a: number) => [number, number];
12
- export const intake_height: (a: number) => number;
13
- export const intake_residual: (a: number, b: number, c: number) => [number, number];
14
- export const intake_rgba8: (a: number) => [number, number];
15
- export const intake_take_denoiser_output: (a: number, b: number, c: number) => [number, number];
16
- export const intake_trace: (a: number) => [number, number, number, number];
17
- export const intake_traceOnce: (a: number) => [number, number, number, number];
18
- export const intake_width: (a: number) => number;
19
- export const options_schema_json: () => [number, number];
20
- export const prepare: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => [number, number, number];
21
- export const threads_available: () => number;
22
- export const trace: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => [number, number, number, number];
23
- export const trace_json: (a: number, b: number, c: number, d: number) => [number, number, number, number];
24
- export const trace_rgba_json: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number];
25
- export const version: () => [number, number];
26
- export const __wbindgen_free: (a: number, b: number, c: number) => void;
27
- export const __wbindgen_exn_store: (a: number) => void;
28
- export const __externref_table_alloc: () => number;
29
- export const __wbindgen_externrefs: WebAssembly.Table;
30
- export const __wbindgen_malloc: (a: number, b: number) => number;
31
- export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
32
- export const __externref_table_dealloc: (a: number) => void;
33
- export const __wbindgen_start: () => void;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pkg/package.json DELETED
@@ -1,24 +0,0 @@
1
- {
2
- "name": "inkvec-wasm",
3
- "type": "module",
4
- "collaborators": [
5
- "LogoLabs"
6
- ],
7
- "description": "Inkvec in the browser: the tracer compiled to WebAssembly",
8
- "version": "0.1.4",
9
- "license": "Apache-2.0",
10
- "repository": {
11
- "type": "git",
12
- "url": "https://github.com/logolabs/inkvec"
13
- },
14
- "files": [
15
- "inkvec_wasm_bg.wasm",
16
- "inkvec_wasm.js",
17
- "inkvec_wasm.d.ts"
18
- ],
19
- "main": "inkvec_wasm.js",
20
- "types": "inkvec_wasm.d.ts",
21
- "sideEffects": [
22
- "./snippets/*"
23
- ]
24
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
samples/1075thefan.png DELETED
Binary file (17 kB)
 
samples/365retailmarkets.png DELETED
Binary file (29.4 kB)
 
samples/adamo.png DELETED
Binary file (36.2 kB)
 
samples/tiny.png DELETED
Binary file (4.56 kB)
 
showcase.json CHANGED
The diff for this file is too large to render. See raw diff
 
studio/LICENSE ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
studio/NOTICE ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Inkvec
2
+ Copyright 2026 LogoLabs and Stefan-Lucian Deleanu
3
+
4
+ This product includes software developed by LogoLabs and licensed under the Apache
5
+ License, Version 2.0 (see LICENSE).
6
+
7
+ ------------------------------------------------------------------------------------
8
+
9
+ This distribution includes third-party components. Every Rust crate Inkvec compiles
10
+ against, plus the tools and runtimes used by the optional restorer and SR pre-pass, are
11
+ listed with their licences and upstream URLs in docs/THIRD_PARTY.md; that file is
12
+ regenerated from the resolved dependency graph and is the authoritative list.
13
+
14
+ The document-level rules in `inkvec-svgmin` (crates/inkvec-svgmin/src/document.rs) are a
15
+ clean-room re-implementation of ideas from SVGO, which is the reference for what is safe
16
+ to take out of an SVG and what is not:
17
+
18
+ SVGO MIT
19
+ https://github.com/svg/svgo
20
+ No SVGO code is used. The behaviour of its convertColors,
21
+ cleanupNumericValues, removeUnknownsAndDefaults, removeComments,
22
+ removeMetadata, removeDesc, removeEmptyAttrs, cleanupIds,
23
+ collapseGroups, moveElemsAttrsToGroup and convertStyleToAttrs plugins
24
+ is reproduced from their documented contracts, some of them
25
+ deliberately narrower than the original.
26
+
27
+ The benchmark corpora committed under bench/data (test data, not shipped in any build)
28
+ are drawn from the following third-party icon sets, each under its own upstream licence:
29
+
30
+ lucide ISC (includes Feather's MIT notice)
31
+ https://github.com/lucide-icons/lucide
32
+
33
+ material-icons Apache-2.0
34
+ https://github.com/google/material-design-icons
35
+
36
+ simple-icons CC0-1.0
37
+ https://github.com/simple-icons/simple-icons
38
+ The icons are dedicated to the public domain; the brand names and
39
+ logos depicted remain trademarks of their respective owners. See
40
+ simple-icons' own DISCLAIMER.md.
41
+
42
+ twemoji CC-BY 4.0 (graphics)
43
+ https://github.com/jdecked/twemoji
44
+
45
+ noto-emoji Apache-2.0 (images), OFL-1.1 (fonts)
46
+ https://github.com/googlefonts/noto-emoji
47
+
48
+ openmoji CC-BY-SA 4.0
49
+ https://openmoji.org
50
+
51
+ fluent-emoji MIT
52
+ https://github.com/microsoft/fluentui-emoji
53
+
54
+ When the optional `restore-model` feature is built and an ONNX Runtime library is
55
+ redistributed with the result, Microsoft's ONNX Runtime ThirdPartyNotices.txt is included
56
+ alongside it, as required by its licence.
57
+
58
+ For the complete, generated list of Rust crates and their licences, see
59
+ docs/THIRD_PARTY.md.
studio/STUDIO_THIRD_PARTY.md ADDED
@@ -0,0 +1,501 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Third-party components — Inkvec Studio
2
+
3
+ Generated by `studio/tools/third_party.py`. Regenerate it after changing dependencies.
4
+ Inkvec Studio itself is licensed under Apache-2.0 (`LICENSE`); Inkvec Studio Lite, its browser build, is the same code and the same licence.
5
+
6
+ 439 Rust crates are compiled into the app (315 in every build; the rest only with the optional denoiser, or only on the platform the Build column names).
7
+
8
+ Not under a plainly permissive licence, with the smallest build that compiles them. None is copyleft in a way that reaches this app: MPL-2.0 is file-level and these crates are used unmodified.
9
+
10
+ - `cssparser` — MPL-2.0 (default)
11
+ - `cssparser-macros` — MPL-2.0 (default)
12
+ - `dtoa-short` — MPL-2.0 (default)
13
+ - `option-ext` — MPL-2.0 (default)
14
+ - `selectors` — MPL-2.0 (default)
15
+
16
+ ## Crates
17
+
18
+ | Crate | Licence | Build |
19
+ | --- | --- | --- |
20
+ | `adler2` | 0BSD OR MIT OR Apache-2.0 | default |
21
+ | `aho-corasick` | Unlicense OR MIT | default |
22
+ | `alloc-no-stdlib` | BSD-3-Clause | default |
23
+ | `alloc-stdlib` | BSD-3-Clause | default |
24
+ | `anyhow` | MIT OR Apache-2.0 | default |
25
+ | `arboard` | MIT OR Apache-2.0 | default |
26
+ | `arrayref` | BSD-2-Clause | default |
27
+ | `arrayvec` | MIT OR Apache-2.0 | default |
28
+ | `async-broadcast` | MIT OR Apache-2.0 | linux |
29
+ | `async-channel` | Apache-2.0 OR MIT | linux |
30
+ | `async-executor` | Apache-2.0 OR MIT | linux |
31
+ | `async-io` | Apache-2.0 OR MIT | linux |
32
+ | `async-lock` | Apache-2.0 OR MIT | linux |
33
+ | `async-process` | Apache-2.0 OR MIT | linux |
34
+ | `async-recursion` | MIT OR Apache-2.0 | linux |
35
+ | `async-signal` | Apache-2.0 OR MIT | linux |
36
+ | `async-task` | Apache-2.0 OR MIT | linux |
37
+ | `async-trait` | MIT OR Apache-2.0 | linux |
38
+ | `atk` | MIT | linux |
39
+ | `atk-sys` | MIT | linux |
40
+ | `atomic-waker` | Apache-2.0 OR MIT | linux |
41
+ | `autocfg` | Apache-2.0 OR MIT | default |
42
+ | `base64` | MIT OR Apache-2.0 | default |
43
+ | `base64ct` | Apache-2.0 OR MIT | default |
44
+ | `bit-set` | Apache-2.0 OR MIT | default |
45
+ | `bit-vec` | Apache-2.0 OR MIT | default |
46
+ | `bitflags` | MIT OR Apache-2.0 | default |
47
+ | `block-buffer` | MIT OR Apache-2.0 | default |
48
+ | `block2` | MIT | macos |
49
+ | `blocking` | Apache-2.0 OR MIT | linux |
50
+ | `brotli` | BSD-3-Clause AND MIT | default |
51
+ | `brotli-decompressor` | BSD-3-Clause/MIT | default |
52
+ | `bumpalo` | MIT OR Apache-2.0 | default |
53
+ | `bytemuck` | Zlib OR Apache-2.0 OR MIT | default |
54
+ | `byteorder` | Unlicense OR MIT | default |
55
+ | `byteorder-lite` | Unlicense OR MIT | default |
56
+ | `bytes` | MIT | default |
57
+ | `cairo-rs` | MIT | linux |
58
+ | `cairo-sys-rs` | MIT | linux |
59
+ | `camino` | MIT OR Apache-2.0 | default |
60
+ | `cargo-platform` | MIT OR Apache-2.0 | default |
61
+ | `cargo_metadata` | MIT | default |
62
+ | `cargo_toml` | Apache-2.0 OR MIT | default |
63
+ | `cc` | MIT OR Apache-2.0 | default |
64
+ | `cfb` | MIT | default |
65
+ | `cfg-expr` | MIT OR Apache-2.0 | linux |
66
+ | `cfg-if` | MIT OR Apache-2.0 | default |
67
+ | `clipboard-win` | BSL-1.0 | default |
68
+ | `color_quant` | MIT | default |
69
+ | `concurrent-queue` | Apache-2.0 OR MIT | linux |
70
+ | `const-oid` | Apache-2.0 OR MIT | default |
71
+ | `cookie` | MIT OR Apache-2.0 | default |
72
+ | `core-foundation` | MIT OR Apache-2.0 | macos |
73
+ | `core-foundation-sys` | MIT OR Apache-2.0 | macos |
74
+ | `core-graphics` | MIT OR Apache-2.0 | macos |
75
+ | `core-graphics-types` | MIT OR Apache-2.0 | macos |
76
+ | `cpufeatures` | MIT OR Apache-2.0 | default |
77
+ | `crc32fast` | MIT OR Apache-2.0 | default |
78
+ | `crossbeam-channel` | MIT OR Apache-2.0 | default |
79
+ | `crossbeam-deque` | MIT OR Apache-2.0 | default |
80
+ | `crossbeam-epoch` | MIT OR Apache-2.0 | default |
81
+ | `crossbeam-utils` | MIT OR Apache-2.0 | default |
82
+ | `crypto-common` | MIT OR Apache-2.0 | default |
83
+ | `cssparser` | MPL-2.0 | default |
84
+ | `cssparser-macros` | MPL-2.0 | default |
85
+ | `ctor` | Apache-2.0 OR MIT | default |
86
+ | `ctor-proc-macro` | Apache-2.0 OR MIT | default |
87
+ | `darling` | MIT | default |
88
+ | `darling_core` | MIT | default |
89
+ | `darling_macro` | MIT | default |
90
+ | `data-url` | MIT OR Apache-2.0 | default |
91
+ | `dbus` | Apache-2.0/MIT | linux |
92
+ | `der` | Apache-2.0 OR MIT | default |
93
+ | `deranged` | MIT OR Apache-2.0 | default |
94
+ | `derive_more` | MIT | default |
95
+ | `derive_more-impl` | MIT | default |
96
+ | `digest` | MIT OR Apache-2.0 | default |
97
+ | `dirs` | MIT OR Apache-2.0 | default |
98
+ | `dirs-sys` | MIT OR Apache-2.0 | default |
99
+ | `dispatch2` | Zlib OR Apache-2.0 OR MIT | macos |
100
+ | `displaydoc` | MIT OR Apache-2.0 | default |
101
+ | `dlopen2` | MIT | linux |
102
+ | `dlopen2_derive` | MIT | linux |
103
+ | `dom_query` | MIT | default |
104
+ | `downcast-rs` | MIT/Apache-2.0 | linux |
105
+ | `dpi` | Apache-2.0 AND MIT | default |
106
+ | `dtoa` | MIT OR Apache-2.0 | default |
107
+ | `dtoa-short` | MPL-2.0 | default |
108
+ | `dunce` | CC0-1.0 OR MIT-0 OR Apache-2.0 | default |
109
+ | `dyn-clone` | MIT OR Apache-2.0 | default |
110
+ | `either` | MIT OR Apache-2.0 | default |
111
+ | `embed-resource` | MIT | default |
112
+ | `embed_plist` | MIT OR Apache-2.0 | macos |
113
+ | `endi` | MIT | linux |
114
+ | `enumflags2` | MIT OR Apache-2.0 | linux |
115
+ | `enumflags2_derive` | MIT OR Apache-2.0 | linux |
116
+ | `equivalent` | Apache-2.0 OR MIT | default |
117
+ | `erased-serde` | MIT OR Apache-2.0 | default |
118
+ | `errno` | MIT OR Apache-2.0 | linux |
119
+ | `error-code` | BSL-1.0 | default |
120
+ | `event-listener` | Apache-2.0 OR MIT | linux |
121
+ | `event-listener-strategy` | Apache-2.0 OR MIT | linux |
122
+ | `fastrand` | Apache-2.0 OR MIT | default |
123
+ | `fax` | MIT | default |
124
+ | `fdeflate` | MIT OR Apache-2.0 | default |
125
+ | `field-offset` | MIT OR Apache-2.0 | linux |
126
+ | `find-msvc-tools` | MIT OR Apache-2.0 | default |
127
+ | `fixedbitset` | MIT OR Apache-2.0 | linux |
128
+ | `flate2` | MIT OR Apache-2.0 | default |
129
+ | `float-cmp` | MIT | default |
130
+ | `fnv` | Apache-2.0 / MIT | default |
131
+ | `foldhash` | Zlib | default |
132
+ | `foreign-types` | MIT/Apache-2.0 | macos |
133
+ | `foreign-types-macros` | MIT/Apache-2.0 | macos |
134
+ | `foreign-types-shared` | MIT/Apache-2.0 | macos |
135
+ | `form_urlencoded` | MIT OR Apache-2.0 | default |
136
+ | `futures-channel` | MIT OR Apache-2.0 | linux |
137
+ | `futures-core` | MIT OR Apache-2.0 | linux |
138
+ | `futures-executor` | MIT OR Apache-2.0 | linux |
139
+ | `futures-io` | MIT OR Apache-2.0 | linux |
140
+ | `futures-lite` | Apache-2.0 OR MIT | linux |
141
+ | `futures-macro` | MIT OR Apache-2.0 | linux |
142
+ | `futures-task` | MIT OR Apache-2.0 | linux |
143
+ | `futures-util` | MIT OR Apache-2.0 | linux |
144
+ | `gdk` | MIT | linux |
145
+ | `gdk-pixbuf` | MIT | linux |
146
+ | `gdk-pixbuf-sys` | MIT | linux |
147
+ | `gdk-sys` | MIT | linux |
148
+ | `gdkwayland-sys` | MIT | linux |
149
+ | `gdkx11` | MIT | linux |
150
+ | `gdkx11-sys` | MIT | linux |
151
+ | `generic-array` | MIT | default |
152
+ | `gethostname` | Apache-2.0 | linux |
153
+ | `getrandom` | MIT OR Apache-2.0 | default |
154
+ | `gif` | MIT OR Apache-2.0 | default |
155
+ | `gio` | MIT | linux |
156
+ | `gio-sys` | MIT | linux |
157
+ | `glib` | MIT | linux |
158
+ | `glib-macros` | MIT | linux |
159
+ | `glib-sys` | MIT | linux |
160
+ | `glob` | MIT OR Apache-2.0 | default |
161
+ | `gobject-sys` | MIT | linux |
162
+ | `gtk` | MIT | linux |
163
+ | `gtk-sys` | MIT | linux |
164
+ | `gtk3-macros` | MIT | linux |
165
+ | `half` | MIT OR Apache-2.0 | default |
166
+ | `hashbrown` | MIT OR Apache-2.0 | default |
167
+ | `heck` | MIT OR Apache-2.0 | default |
168
+ | `hex` | MIT OR Apache-2.0 | linux |
169
+ | `hmac-sha256` | ISC | default |
170
+ | `html5ever` | MIT OR Apache-2.0 | default |
171
+ | `http` | MIT OR Apache-2.0 | default |
172
+ | `http-range` | MIT | default |
173
+ | `httparse` | MIT OR Apache-2.0 | default |
174
+ | `hybrid-array` | MIT OR Apache-2.0 | default |
175
+ | `i_float` | MIT | default |
176
+ | `i_key_sort` | MIT | default |
177
+ | `i_overlay` | MIT OR Apache-2.0 | default |
178
+ | `i_shape` | MIT | default |
179
+ | `i_tree` | MIT | default |
180
+ | `ico` | MIT | default |
181
+ | `icu_collections` | Unicode-3.0 | default |
182
+ | `icu_locale_core` | Unicode-3.0 | default |
183
+ | `icu_normalizer` | Unicode-3.0 | default |
184
+ | `icu_normalizer_data` | Unicode-3.0 | default |
185
+ | `icu_properties` | Unicode-3.0 | default |
186
+ | `icu_properties_data` | Unicode-3.0 | default |
187
+ | `icu_provider` | Unicode-3.0 | default |
188
+ | `ident_case` | MIT/Apache-2.0 | default |
189
+ | `idna` | MIT OR Apache-2.0 | default |
190
+ | `idna_adapter` | Apache-2.0 OR MIT | default |
191
+ | `image` | MIT OR Apache-2.0 | default |
192
+ | `image-webp` | MIT OR Apache-2.0 | default |
193
+ | `imagesize` | MIT | default |
194
+ | `indexmap` | Apache-2.0 OR MIT | default |
195
+ | `infer` | MIT | default |
196
+ | `is-docker` | MIT | linux |
197
+ | `is-wsl` | MIT | linux |
198
+ | `itoa` | MIT OR Apache-2.0 | default |
199
+ | `javascriptcore-rs` | MIT | linux |
200
+ | `javascriptcore-rs-sys` | MIT | linux |
201
+ | `json-patch` | MIT/Apache-2.0 | default |
202
+ | `jsonptr` | MIT OR Apache-2.0 | default |
203
+ | `keyboard-types` | MIT OR Apache-2.0 | default |
204
+ | `kurbo` | Apache-2.0 OR MIT | default |
205
+ | `libc` | MIT OR Apache-2.0 | default |
206
+ | `libdbus-sys` | Apache-2.0/MIT | linux |
207
+ | `libm` | MIT | default |
208
+ | `linux-raw-sys` | Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT | linux |
209
+ | `litemap` | Unicode-3.0 | default |
210
+ | `lock_api` | MIT OR Apache-2.0 | default |
211
+ | `log` | MIT OR Apache-2.0 | default |
212
+ | `lzma-rust2` | Apache-2.0 | default |
213
+ | `markup5ever` | MIT OR Apache-2.0 | default |
214
+ | `memchr` | Unlicense OR MIT | default |
215
+ | `memoffset` | MIT | linux |
216
+ | `mime` | MIT OR Apache-2.0 | default |
217
+ | `miniz_oxide` | MIT OR Zlib OR Apache-2.0 | default |
218
+ | `mio` | MIT | default |
219
+ | `moxcms` | BSD-3-Clause OR Apache-2.0 | default |
220
+ | `muda` | Apache-2.0 OR MIT | default |
221
+ | `native-tls` | MIT OR Apache-2.0 | default |
222
+ | `new_debug_unreachable` | MIT | default |
223
+ | `nom` | MIT | linux |
224
+ | `num-conv` | MIT OR Apache-2.0 | default |
225
+ | `num-traits` | MIT OR Apache-2.0 | default |
226
+ | `objc2` | MIT | macos |
227
+ | `objc2-app-kit` | Zlib OR Apache-2.0 OR MIT | macos |
228
+ | `objc2-core-foundation` | Zlib OR Apache-2.0 OR MIT | macos |
229
+ | `objc2-core-graphics` | Zlib OR Apache-2.0 OR MIT | macos |
230
+ | `objc2-encode` | MIT | macos |
231
+ | `objc2-exception-helper` | Zlib OR Apache-2.0 OR MIT | macos |
232
+ | `objc2-foundation` | MIT | macos |
233
+ | `objc2-web-kit` | Zlib OR Apache-2.0 OR MIT | macos |
234
+ | `once_cell` | MIT OR Apache-2.0 | default |
235
+ | `open` | MIT | default |
236
+ | `option-ext` | MPL-2.0 | default |
237
+ | `ordered-stream` | MIT OR Apache-2.0 | linux |
238
+ | `ort` | MIT OR Apache-2.0 | default |
239
+ | `ort-sys` | MIT OR Apache-2.0 | default |
240
+ | `os_pipe` | MIT | linux |
241
+ | `pango` | MIT | linux |
242
+ | `pango-sys` | MIT | linux |
243
+ | `parking` | Apache-2.0 OR MIT | linux |
244
+ | `parking_lot` | MIT OR Apache-2.0 | default |
245
+ | `parking_lot_core` | MIT OR Apache-2.0 | default |
246
+ | `pem-rfc7468` | Apache-2.0 OR MIT | default |
247
+ | `percent-encoding` | MIT OR Apache-2.0 | default |
248
+ | `petgraph` | MIT OR Apache-2.0 | linux |
249
+ | `phf` | MIT | default |
250
+ | `phf_codegen` | MIT | default |
251
+ | `phf_generator` | MIT | default |
252
+ | `phf_macros` | MIT | default |
253
+ | `phf_shared` | MIT | default |
254
+ | `pico-args` | MIT | default |
255
+ | `pin-project-lite` | Apache-2.0 OR MIT | default |
256
+ | `piper` | MIT OR Apache-2.0 | linux |
257
+ | `pkg-config` | MIT OR Apache-2.0 | linux |
258
+ | `plist` | MIT | default |
259
+ | `png` | MIT OR Apache-2.0 | default |
260
+ | `polling` | Apache-2.0 OR MIT | linux |
261
+ | `polycool` | MIT OR Apache-2.0 | default |
262
+ | `potential_utf` | Unicode-3.0 | default |
263
+ | `powerfmt` | MIT OR Apache-2.0 | default |
264
+ | `precomputed-hash` | MIT | default |
265
+ | `proc-macro-crate` | MIT OR Apache-2.0 | linux |
266
+ | `proc-macro-error` | MIT OR Apache-2.0 | linux |
267
+ | `proc-macro-error-attr` | MIT OR Apache-2.0 | linux |
268
+ | `proc-macro2` | MIT OR Apache-2.0 | default |
269
+ | `pxfm` | BSD-3-Clause OR Apache-2.0 | default |
270
+ | `quick-error` | MIT/Apache-2.0 | default |
271
+ | `quick-xml` | MIT | default |
272
+ | `quote` | MIT OR Apache-2.0 | default |
273
+ | `raw-window-handle` | MIT OR Apache-2.0 OR Zlib | default |
274
+ | `rayon` | MIT OR Apache-2.0 | default |
275
+ | `rayon-core` | MIT OR Apache-2.0 | default |
276
+ | `regex` | MIT OR Apache-2.0 | default |
277
+ | `regex-automata` | MIT OR Apache-2.0 | default |
278
+ | `regex-syntax` | MIT OR Apache-2.0 | default |
279
+ | `resvg` | Apache-2.0 OR MIT | default |
280
+ | `rfd` | MIT | default |
281
+ | `rgb` | MIT | default |
282
+ | `ring` | Apache-2.0 AND ISC | default |
283
+ | `robust` | MIT OR Apache-2.0 | default |
284
+ | `roxmltree` | MIT OR Apache-2.0 | default |
285
+ | `rustc-hash` | Apache-2.0 OR MIT | default |
286
+ | `rustc_version` | MIT OR Apache-2.0 | default |
287
+ | `rustix` | Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT | linux |
288
+ | `rustls` | Apache-2.0 OR ISC OR MIT | default |
289
+ | `rustls-pki-types` | MIT OR Apache-2.0 | default |
290
+ | `rustls-webpki` | ISC | default |
291
+ | `same-file` | Unlicense/MIT | default |
292
+ | `schannel` | MIT | default |
293
+ | `schemars` | MIT | default |
294
+ | `schemars_derive` | MIT | default |
295
+ | `scopeguard` | MIT OR Apache-2.0 | default |
296
+ | `selectors` | MPL-2.0 | default |
297
+ | `semver` | MIT OR Apache-2.0 | default |
298
+ | `serde` | MIT OR Apache-2.0 | default |
299
+ | `serde-untagged` | MIT OR Apache-2.0 | default |
300
+ | `serde_core` | MIT OR Apache-2.0 | default |
301
+ | `serde_derive` | MIT OR Apache-2.0 | default |
302
+ | `serde_derive_internals` | MIT OR Apache-2.0 | default |
303
+ | `serde_json` | MIT OR Apache-2.0 | default |
304
+ | `serde_repr` | MIT OR Apache-2.0 | default |
305
+ | `serde_spanned` | MIT OR Apache-2.0 | default |
306
+ | `serde_with` | MIT OR Apache-2.0 | default |
307
+ | `serde_with_macros` | MIT OR Apache-2.0 | default |
308
+ | `serialize-to-javascript` | MIT OR Apache-2.0 | default |
309
+ | `serialize-to-javascript-impl` | MIT OR Apache-2.0 | default |
310
+ | `servo_arc` | MIT OR Apache-2.0 | default |
311
+ | `sha2` | MIT OR Apache-2.0 | default |
312
+ | `shlex` | MIT OR Apache-2.0 | default |
313
+ | `signal-hook-registry` | MIT OR Apache-2.0 | linux |
314
+ | `simd-adler32` | MIT | default |
315
+ | `simplecss` | Apache-2.0 OR MIT | default |
316
+ | `siphasher` | MIT/Apache-2.0 | default |
317
+ | `slab` | MIT | linux |
318
+ | `smallvec` | MIT OR Apache-2.0 | default |
319
+ | `socket2` | MIT OR Apache-2.0 | default |
320
+ | `socks` | MIT/Apache-2.0 | default |
321
+ | `softbuffer` | MIT OR Apache-2.0 | default |
322
+ | `soup3` | MIT | linux |
323
+ | `soup3-sys` | MIT | linux |
324
+ | `stable_deref_trait` | MIT OR Apache-2.0 | default |
325
+ | `strict-num` | MIT | default |
326
+ | `string_cache` | MIT OR Apache-2.0 | default |
327
+ | `string_cache_codegen` | MIT OR Apache-2.0 | default |
328
+ | `strsim` | MIT | default |
329
+ | `subtle` | BSD-3-Clause | default |
330
+ | `svgtypes` | Apache-2.0 OR MIT | default |
331
+ | `syn` | MIT OR Apache-2.0 | default |
332
+ | `synstructure` | MIT | default |
333
+ | `system-deps` | MIT OR Apache-2.0 | linux |
334
+ | `tao` | Apache-2.0 | default |
335
+ | `target-lexicon` | Apache-2.0 WITH LLVM-exception | linux |
336
+ | `tauri` | Apache-2.0 OR MIT | default |
337
+ | `tauri-build` | Apache-2.0 OR MIT | default |
338
+ | `tauri-codegen` | Apache-2.0 OR MIT | default |
339
+ | `tauri-macros` | Apache-2.0 OR MIT | default |
340
+ | `tauri-plugin` | Apache-2.0 OR MIT | default |
341
+ | `tauri-plugin-clipboard-manager` | Apache-2.0 OR MIT | default |
342
+ | `tauri-plugin-dialog` | Apache-2.0 OR MIT | default |
343
+ | `tauri-plugin-fs` | Apache-2.0 OR MIT | default |
344
+ | `tauri-plugin-opener` | Apache-2.0 OR MIT | default |
345
+ | `tauri-plugin-single-instance` | Apache-2.0 OR MIT | default |
346
+ | `tauri-runtime` | Apache-2.0 OR MIT | default |
347
+ | `tauri-runtime-wry` | Apache-2.0 OR MIT | default |
348
+ | `tauri-utils` | Apache-2.0 OR MIT | default |
349
+ | `tauri-winres` | MIT | default |
350
+ | `tendril` | MIT OR Apache-2.0 | default |
351
+ | `thiserror` | MIT OR Apache-2.0 | default |
352
+ | `thiserror-impl` | MIT OR Apache-2.0 | default |
353
+ | `tiff` | MIT | default |
354
+ | `time` | MIT OR Apache-2.0 | default |
355
+ | `time-core` | MIT OR Apache-2.0 | default |
356
+ | `time-macros` | MIT OR Apache-2.0 | default |
357
+ | `tiny-skia` | BSD-3-Clause | default |
358
+ | `tiny-skia-path` | BSD-3-Clause | default |
359
+ | `tinystr` | Unicode-3.0 | default |
360
+ | `tokio` | MIT | default |
361
+ | `toml` | MIT OR Apache-2.0 | default |
362
+ | `toml_datetime` | MIT OR Apache-2.0 | default |
363
+ | `toml_edit` | MIT OR Apache-2.0 | linux |
364
+ | `toml_parser` | MIT OR Apache-2.0 | default |
365
+ | `toml_writer` | MIT OR Apache-2.0 | default |
366
+ | `tracing` | MIT | default |
367
+ | `tracing-attributes` | MIT | default |
368
+ | `tracing-core` | MIT | default |
369
+ | `tree_magic_mini` | MIT | linux |
370
+ | `typed-path` | MIT OR Apache-2.0 | default |
371
+ | `typeid` | MIT OR Apache-2.0 | default |
372
+ | `typenum` | MIT OR Apache-2.0 | default |
373
+ | `unic-char-property` | MIT/Apache-2.0 | default |
374
+ | `unic-char-range` | MIT/Apache-2.0 | default |
375
+ | `unic-common` | MIT/Apache-2.0 | default |
376
+ | `unic-ucd-ident` | MIT/Apache-2.0 | default |
377
+ | `unic-ucd-version` | MIT/Apache-2.0 | default |
378
+ | `unicode-ident` | (MIT OR Apache-2.0) AND Unicode-3.0 | default |
379
+ | `unicode-segmentation` | MIT OR Apache-2.0 | default |
380
+ | `untrusted` | ISC | default |
381
+ | `ureq` | MIT OR Apache-2.0 | default |
382
+ | `ureq-proto` | MIT OR Apache-2.0 | default |
383
+ | `url` | MIT OR Apache-2.0 | default |
384
+ | `urlpattern` | MIT | default |
385
+ | `usvg` | Apache-2.0 OR MIT | default |
386
+ | `utf8-zero` | MIT OR Apache-2.0 | default |
387
+ | `utf8_iter` | Apache-2.0 OR MIT | default |
388
+ | `uuid` | Apache-2.0 OR MIT | default |
389
+ | `version-compare` | MIT | linux |
390
+ | `version_check` | MIT/Apache-2.0 | default |
391
+ | `vswhom` | MIT | default |
392
+ | `vswhom-sys` | MIT | default |
393
+ | `walkdir` | Unlicense/MIT | default |
394
+ | `wayland-backend` | MIT | linux |
395
+ | `wayland-client` | MIT | linux |
396
+ | `wayland-protocols` | MIT | linux |
397
+ | `wayland-protocols-wlr` | MIT | linux |
398
+ | `wayland-scanner` | MIT | linux |
399
+ | `wayland-sys` | MIT | linux |
400
+ | `web_atoms` | MIT OR Apache-2.0 | default |
401
+ | `webkit2gtk` | MIT | linux |
402
+ | `webkit2gtk-sys` | MIT | linux |
403
+ | `webpki-root-certs` | CDLA-Permissive-2.0 | default |
404
+ | `webpki-roots` | CDLA-Permissive-2.0 | default |
405
+ | `webview2-com` | MIT | default |
406
+ | `webview2-com-macros` | MIT | default |
407
+ | `webview2-com-sys` | MIT | default |
408
+ | `weezl` | MIT OR Apache-2.0 | default |
409
+ | `winapi` | MIT/Apache-2.0 | default |
410
+ | `winapi-util` | Unlicense OR MIT | default |
411
+ | `window-vibrancy` | Apache-2.0 OR MIT | default |
412
+ | `windows` | MIT OR Apache-2.0 | default |
413
+ | `windows-collections` | MIT OR Apache-2.0 | default |
414
+ | `windows-core` | MIT OR Apache-2.0 | default |
415
+ | `windows-future` | MIT OR Apache-2.0 | default |
416
+ | `windows-implement` | MIT OR Apache-2.0 | default |
417
+ | `windows-interface` | MIT OR Apache-2.0 | default |
418
+ | `windows-link` | MIT OR Apache-2.0 | default |
419
+ | `windows-numerics` | MIT OR Apache-2.0 | default |
420
+ | `windows-result` | MIT OR Apache-2.0 | default |
421
+ | `windows-strings` | MIT OR Apache-2.0 | default |
422
+ | `windows-sys` | MIT OR Apache-2.0 | default |
423
+ | `windows-targets` | MIT OR Apache-2.0 | default |
424
+ | `windows-threading` | MIT OR Apache-2.0 | default |
425
+ | `windows-version` | MIT OR Apache-2.0 | default |
426
+ | `windows_x86_64_msvc` | MIT OR Apache-2.0 | default |
427
+ | `winnow` | MIT | default |
428
+ | `winreg` | MIT | default |
429
+ | `wl-clipboard-rs` | MIT/Apache-2.0 | linux |
430
+ | `writeable` | Unicode-3.0 | default |
431
+ | `wry` | Apache-2.0 OR MIT | default |
432
+ | `x11` | MIT | linux |
433
+ | `x11-dl` | MIT | linux |
434
+ | `x11rb` | MIT OR Apache-2.0 | linux |
435
+ | `x11rb-protocol` | MIT OR Apache-2.0 | linux |
436
+ | `yoke` | Unicode-3.0 | default |
437
+ | `yoke-derive` | Unicode-3.0 | default |
438
+ | `zbus` | MIT | linux |
439
+ | `zbus_macros` | MIT | linux |
440
+ | `zbus_names` | MIT | linux |
441
+ | `zcheapstr` | MIT | linux |
442
+ | `zerocopy` | BSD-2-Clause OR Apache-2.0 OR MIT | default |
443
+ | `zerocopy-derive` | BSD-2-Clause OR Apache-2.0 OR MIT | default |
444
+ | `zerofrom` | Unicode-3.0 | default |
445
+ | `zerofrom-derive` | Unicode-3.0 | default |
446
+ | `zeroize` | Apache-2.0 OR MIT | default |
447
+ | `zerotrie` | Unicode-3.0 | default |
448
+ | `zerovec` | Unicode-3.0 | default |
449
+ | `zerovec-derive` | Unicode-3.0 | default |
450
+ | `zip` | MIT | default |
451
+ | `zlib-rs` | Zlib | default |
452
+ | `zmij` | MIT | default |
453
+ | `zopfli` | Apache-2.0 | default |
454
+ | `zune-core` | MIT OR Apache-2.0 OR Zlib | default |
455
+ | `zune-jpeg` | MIT OR Apache-2.0 OR Zlib | default |
456
+ | `zvariant` | MIT | linux |
457
+ | `zvariant_derive` | MIT | linux |
458
+ | `zvariant_utils` | MIT | linux |
459
+
460
+ ## Bundled fonts
461
+
462
+ Both are subset to Latin and shipped in `studio/public/fonts/`. The app makes no network
463
+ request it has not explained, and that includes a font, which is why they are bundled
464
+ rather than fetched.
465
+
466
+ | Font | Licence | Source |
467
+ | --- | --- | --- |
468
+ | Inter | SIL Open Font License 1.1 | https://github.com/rsms/inter |
469
+ | Playfair Display | SIL Open Font License 1.1 | https://github.com/clauseggers/Playfair-Display |
470
+
471
+ The OFL permits bundling and redistribution with the application. Neither font is
472
+ renamed, sold on its own, or distributed with a reserved font name.
473
+
474
+ ## Icons
475
+
476
+ The interface's glyphs are drawn from Lucide's geometry, inlined in
477
+ `studio/src/lib/dom.ts` rather than taken as a package dependency — only the twenty-odd
478
+ shapes the app actually uses. Lucide is ISC-licensed.
479
+
480
+ The app's own mark (the stair-stepped pixels and the copper curve) is LogoLabs' and is
481
+ drawn by `studio/tools/make_assets.py`.
482
+
483
+ ## JavaScript
484
+
485
+ The bundled frontend has no runtime framework. Its only dependencies are Tauri's own
486
+ JavaScript API and three of its plugins, all MIT OR Apache-2.0:
487
+
488
+ | Package | Licence |
489
+ | --- | --- |
490
+ | @tauri-apps/api | MIT OR Apache-2.0 |
491
+ | @tauri-apps/plugin-dialog | MIT OR Apache-2.0 |
492
+ | @tauri-apps/plugin-opener | MIT OR Apache-2.0 |
493
+ | @tauri-apps/plugin-clipboard-manager | MIT OR Apache-2.0 |
494
+
495
+ `vite` and `typescript` are build-time only and are not distributed with the app.
496
+
497
+ ## The engine
498
+
499
+ Inkvec itself, and every crate in this repository, is Apache-2.0. Its own dependency
500
+ notices are in `docs/THIRD_PARTY.md`, which the app ships and displays alongside this
501
+ file.
studio/THIRD_PARTY.md ADDED
@@ -0,0 +1,573 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Third-party components
2
+
3
+ Generated by `tools/third_party.py` on 2026-09-20. Regenerate it after changing dependencies.
4
+ Inkvec itself is licensed under Apache-2.0 (`LICENSE`).
5
+
6
+ 516 Rust crates are compiled across all builds: 159 in every build, 42 more with the ONNX Runtime restorer, 315 more only with other optional features.
7
+
8
+ Not under a permissive licence (or no licence declared), with the smallest build that compiles them:
9
+
10
+ - `colored` 3.1.1: MPL-2.0 (all features)
11
+ - `option-ext` 0.2.0: MPL-2.0 (all features)
12
+
13
+ ## Python tools and model weights
14
+
15
+ | component | licence | notes |
16
+ |---|---|---|
17
+ | MambaIR / MambaIRv2 (SR pre-pass architecture and released weights) | Apache-2.0 | https://github.com/csguoh/MambaIR; weights are downloaded by `tools/inkvec_sr`, not redistributed here |
18
+ | mamba-ssm | Apache-2.0 | https://github.com/state-spaces/mamba |
19
+ | PyTorch (Python tool path only) | BSD-3-Clause | not shipped with the binary |
20
+
21
+ The benchmark harness (`bench/`) uses `tqdm` (MPL-2.0 AND MIT) and, through `requests`, `certifi`
22
+ (MPL-2.0). Neither is shipped with Inkvec.
23
+
24
+ ## Native runtimes for the restorer (optional)
25
+
26
+ | component | licence | notes |
27
+ |---|---|---|
28
+ | ONNX Runtime (`restore-model`) | MIT | the binary bundles third-party code, including Eigen (MPL-2.0); ship Microsoft's `ThirdPartyNotices.txt` with any redistributed `onnxruntime` library |
29
+ | DirectML (`DirectML.dll`) | Microsoft DirectML License Agreement (proprietary) | only in the prebuilt static Windows package `ort` downloads; not needed for CPU inference and not part of a build linked against Microsoft's CPU release. Review its terms before redistributing it |
30
+
31
+ ## Benchmark corpus (`bench/data`)
32
+
33
+ The screen-set rasters committed under `bench/data` are renders of third-party icon sets. They
34
+ are test data, not part of any build. Each keeps its upstream licence:
35
+
36
+ | family | licence | attribution | notes |
37
+ |---|---|---|---|
38
+ | lucide | ISC (includes Feather's MIT notice) | yes | https://github.com/lucide-icons/lucide |
39
+ | material-icons | Apache-2.0 | notice | https://github.com/google/material-design-icons |
40
+ | simple-icons | CC0-1.0 | no | brand logos: the marks remain trademarks of their owners; see simple-icons `DISCLAIMER.md` |
41
+ | twemoji | CC-BY 4.0 (graphics) | yes | https://github.com/jdecked/twemoji |
42
+ | noto-emoji | Apache-2.0 (images), OFL-1.1 (fonts) | notice | https://github.com/googlefonts/noto-emoji |
43
+ | openmoji | CC-BY-SA 4.0 | yes, share-alike | https://openmoji.org |
44
+ | fluent-emoji | MIT | yes | https://github.com/microsoft/fluentui-emoji |
45
+ | synthetic | generated by this project | no | `bench/cases` |
46
+
47
+ Upstream licence terms for each family are linked in the table above.
48
+
49
+ ## Rust crates (516)
50
+
51
+ `builds` is the smallest build that compiles the crate: `default` (every workspace build),
52
+ `restore-model` (only with the ONNX Runtime restorer), or `all features` (only with an optional
53
+ feature such as the Burn restorer backends). Build-script dependencies are included, so a crate
54
+ listed here is compiled but not necessarily linked into the binary.
55
+
56
+ | crate | version | licence | builds |
57
+ |---|---|---|---|
58
+ | addr2line | 0.25.1 | Apache-2.0 OR MIT | all features |
59
+ | adler2 | 2.0.1 | 0BSD OR MIT OR Apache-2.0 | default |
60
+ | ahash | 0.8.12 | MIT OR Apache-2.0 | all features |
61
+ | aho-corasick | 1.1.5 | Unlicense OR MIT | all features |
62
+ | aligned-vec | 0.6.4 | MIT | all features |
63
+ | allocator-api2 | 0.2.21 | MIT OR Apache-2.0 | all features |
64
+ | android_system_properties | 0.1.6 | MIT OR Apache-2.0 | all features |
65
+ | anstream | 1.0.0 | MIT OR Apache-2.0 | all features |
66
+ | anstyle | 1.0.14 | MIT OR Apache-2.0 | all features |
67
+ | anstyle-parse | 1.0.0 | MIT OR Apache-2.0 | all features |
68
+ | anstyle-query | 1.1.5 | MIT OR Apache-2.0 | all features |
69
+ | anstyle-wincon | 3.0.11 | MIT OR Apache-2.0 | all features |
70
+ | anyhow | 1.0.104 | MIT OR Apache-2.0 | all features |
71
+ | arrayref | 0.3.9 | BSD-2-Clause | default |
72
+ | arrayvec | 0.7.8 | MIT OR Apache-2.0 | default |
73
+ | ash | 0.38.0+1.3.281 | MIT OR Apache-2.0 | all features |
74
+ | async-channel | 2.5.0 | Apache-2.0 OR MIT | all features |
75
+ | atomic-waker | 1.1.2 | Apache-2.0 OR MIT | default |
76
+ | atomic_float | 1.1.0 | Apache-2.0 OR MIT OR Unlicense | all features |
77
+ | autocfg | 1.5.1 | Apache-2.0 OR MIT | default |
78
+ | axum | 0.8.9 | MIT | default |
79
+ | axum-core | 0.5.6 | MIT | default |
80
+ | backtrace | 0.3.76 | MIT OR Apache-2.0 | all features |
81
+ | base64 | 0.22.1 | MIT OR Apache-2.0 | default |
82
+ | base64 | 0.23.1 | MIT OR Apache-2.0 | restore-model |
83
+ | base64ct | 1.8.3 | Apache-2.0 OR MIT | restore-model |
84
+ | bincode | 2.0.1 | MIT | all features |
85
+ | bit-set | 0.9.1 | Apache-2.0 OR MIT | all features |
86
+ | bit-vec | 0.9.1 | Apache-2.0 OR MIT | all features |
87
+ | bitflags | 1.3.2 | MIT/Apache-2.0 | default |
88
+ | bitflags | 2.13.1 | MIT OR Apache-2.0 | default |
89
+ | block-buffer | 0.10.4 | MIT OR Apache-2.0 | default |
90
+ | block2 | 0.6.2 | MIT | all features |
91
+ | bumpalo | 3.20.3 | MIT OR Apache-2.0 | default |
92
+ | burn | 0.21.0 | MIT OR Apache-2.0 | all features |
93
+ | burn-autodiff | 0.21.0 | MIT OR Apache-2.0 | all features |
94
+ | burn-backend | 0.21.0 | MIT OR Apache-2.0 | all features |
95
+ | burn-core | 0.21.0 | MIT OR Apache-2.0 | all features |
96
+ | burn-cubecl | 0.21.0 | MIT OR Apache-2.0 | all features |
97
+ | burn-cubecl-fusion | 0.21.0 | MIT OR Apache-2.0 | all features |
98
+ | burn-cuda | 0.21.0 | MIT OR Apache-2.0 | all features |
99
+ | burn-derive | 0.21.0 | MIT OR Apache-2.0 | all features |
100
+ | burn-flex | 0.21.0 | MIT OR Apache-2.0 | all features |
101
+ | burn-fusion | 0.21.0 | MIT OR Apache-2.0 | all features |
102
+ | burn-ir | 0.21.0 | MIT OR Apache-2.0 | all features |
103
+ | burn-ndarray | 0.21.0 | MIT OR Apache-2.0 | all features |
104
+ | burn-nn | 0.21.0 | MIT OR Apache-2.0 | all features |
105
+ | burn-onnx | 0.21.0 | MIT OR Apache-2.0 | all features |
106
+ | burn-optim | 0.21.0 | MIT OR Apache-2.0 | all features |
107
+ | burn-std | 0.21.0 | MIT OR Apache-2.0 | all features |
108
+ | burn-store | 0.21.0 | MIT OR Apache-2.0 | all features |
109
+ | burn-tensor | 0.21.0 | MIT OR Apache-2.0 | all features |
110
+ | burn-wgpu | 0.21.0 | MIT OR Apache-2.0 | all features |
111
+ | bytemuck | 1.25.2 | Zlib OR Apache-2.0 OR MIT | default |
112
+ | bytemuck_derive | 1.12.0 | Zlib OR Apache-2.0 OR MIT | all features |
113
+ | byteorder | 1.5.0 | Unlicense OR MIT | restore-model |
114
+ | byteorder-lite | 0.1.0 | Unlicense OR MIT | default |
115
+ | bytes | 1.12.1 | MIT | default |
116
+ | cc | 1.4.6 | MIT OR Apache-2.0 | restore-model |
117
+ | cfg-if | 1.0.4 | MIT OR Apache-2.0 | default |
118
+ | cfg_aliases | 0.2.2 | MIT | all features |
119
+ | chacha20 | 0.10.2 | MIT OR Apache-2.0 | all features |
120
+ | ciborium | 0.2.2 | Apache-2.0 | all features |
121
+ | ciborium-io | 0.2.2 | Apache-2.0 | all features |
122
+ | ciborium-ll | 0.2.2 | Apache-2.0 | all features |
123
+ | clap | 4.6.7 | MIT OR Apache-2.0 | all features |
124
+ | clap_builder | 4.6.7 | MIT OR Apache-2.0 | all features |
125
+ | clap_derive | 4.6.7 | MIT OR Apache-2.0 | all features |
126
+ | clap_lex | 1.1.1 | MIT OR Apache-2.0 | all features |
127
+ | codespan-reporting | 0.13.1 | Apache-2.0 | all features |
128
+ | color_quant | 1.1.0 | MIT | default |
129
+ | colorchoice | 1.0.5 | MIT OR Apache-2.0 | all features |
130
+ | colored | 3.1.1 | MPL-2.0 | all features |
131
+ | concurrent-queue | 2.5.0 | Apache-2.0 OR MIT | all features |
132
+ | console_error_panic_hook | 0.1.7 | Apache-2.0/MIT | default |
133
+ | const-random | 0.1.18 | MIT OR Apache-2.0 | all features |
134
+ | const-random-macro | 0.1.16 | MIT OR Apache-2.0 | all features |
135
+ | convert_case | 0.10.0 | MIT | all features |
136
+ | core-foundation | 0.10.1 | MIT OR Apache-2.0 | restore-model |
137
+ | core-foundation-sys | 0.8.7 | MIT OR Apache-2.0 | restore-model |
138
+ | core_detect | 1.0.0 | MIT/Apache-2.0 | default |
139
+ | cpufeatures | 0.2.17 | MIT OR Apache-2.0 | default |
140
+ | cpufeatures | 0.3.1 | MIT OR Apache-2.0 | all features |
141
+ | crc32fast | 1.5.1 | MIT OR Apache-2.0 | default |
142
+ | critical-section | 1.2.0 | MIT OR Apache-2.0 | all features |
143
+ | crossbeam-channel | 0.5.17 | MIT OR Apache-2.0 | all features |
144
+ | crossbeam-deque | 0.8.7 | MIT OR Apache-2.0 | default |
145
+ | crossbeam-epoch | 0.9.20 | MIT OR Apache-2.0 | default |
146
+ | crossbeam-utils | 0.8.22 | MIT OR Apache-2.0 | default |
147
+ | crunchy | 0.2.4 | MIT | default |
148
+ | crypto-common | 0.1.7 | MIT OR Apache-2.0 | default |
149
+ | cubecl | 0.10.0 | MIT OR Apache-2.0 | all features |
150
+ | cubecl-common | 0.10.0 | MIT OR Apache-2.0 | all features |
151
+ | cubecl-core | 0.10.0 | MIT OR Apache-2.0 | all features |
152
+ | cubecl-cpp | 0.10.0 | MIT OR Apache-2.0 | all features |
153
+ | cubecl-cuda | 0.10.0 | MIT OR Apache-2.0 | all features |
154
+ | cubecl-ir | 0.10.0 | MIT OR Apache-2.0 | all features |
155
+ | cubecl-macros | 0.10.0 | MIT OR Apache-2.0 | all features |
156
+ | cubecl-macros-internal | 0.10.0 | MIT OR Apache-2.0 | all features |
157
+ | cubecl-opt | 0.10.0 | MIT OR Apache-2.0 | all features |
158
+ | cubecl-runtime | 0.10.0 | MIT OR Apache-2.0 | all features |
159
+ | cubecl-std | 0.10.0 | MIT OR Apache-2.0 | all features |
160
+ | cubecl-wgpu | 0.10.0 | MIT OR Apache-2.0 | all features |
161
+ | cubecl-zspace | 0.10.0 | MIT OR Apache-2.0 | all features |
162
+ | cubek | 0.2.0 | MIT OR Apache-2.0 | all features |
163
+ | cubek-attention | 0.2.0 | MIT OR Apache-2.0 | all features |
164
+ | cubek-convolution | 0.2.0 | MIT OR Apache-2.0 | all features |
165
+ | cubek-fft | 0.2.0 | MIT OR Apache-2.0 | all features |
166
+ | cubek-matmul | 0.2.0 | MIT OR Apache-2.0 | all features |
167
+ | cubek-quant | 0.2.0 | MIT OR Apache-2.0 | all features |
168
+ | cubek-random | 0.2.0 | MIT OR Apache-2.0 | all features |
169
+ | cubek-reduce | 0.2.0 | MIT OR Apache-2.0 | all features |
170
+ | cubek-std | 0.2.0 | MIT OR Apache-2.0 | all features |
171
+ | cudarc | 0.19.9 | MIT OR Apache-2.0 | all features |
172
+ | darling | 0.20.11 | MIT | all features |
173
+ | darling | 0.21.3 | MIT | all features |
174
+ | darling | 0.23.0 | MIT | all features |
175
+ | darling_core | 0.20.11 | MIT | all features |
176
+ | darling_core | 0.21.3 | MIT | all features |
177
+ | darling_core | 0.23.0 | MIT | all features |
178
+ | darling_macro | 0.20.11 | MIT | all features |
179
+ | darling_macro | 0.21.3 | MIT | all features |
180
+ | darling_macro | 0.23.0 | MIT | all features |
181
+ | data-encoding | 2.11.1 | MIT | all features |
182
+ | data-url | 0.3.2 | MIT OR Apache-2.0 | default |
183
+ | der | 0.8.2 | Apache-2.0 OR MIT | restore-model |
184
+ | derive-new | 0.7.0 | MIT | all features |
185
+ | derive_more | 2.1.1 | MIT | all features |
186
+ | derive_more-impl | 2.1.1 | MIT | all features |
187
+ | digest | 0.10.7 | MIT OR Apache-2.0 | default |
188
+ | dirs | 6.0.0 | MIT OR Apache-2.0 | all features |
189
+ | dirs-sys | 0.5.0 | MIT OR Apache-2.0 | all features |
190
+ | dlib | 0.5.3 | MIT | all features |
191
+ | document-features | 0.2.12 | MIT OR Apache-2.0 | all features |
192
+ | dyn-clone | 1.0.20 | MIT OR Apache-2.0 | default |
193
+ | dyn-stack | 0.13.2 | MIT | all features |
194
+ | dyn-stack-macros | 0.1.3 | MIT | all features |
195
+ | either | 1.18.0 | MIT OR Apache-2.0 | default |
196
+ | embassy-futures | 0.1.2 | MIT OR Apache-2.0 | all features |
197
+ | embassy-time | 0.5.1 | MIT OR Apache-2.0 | all features |
198
+ | embassy-time-driver | 0.2.2 | MIT OR Apache-2.0 | all features |
199
+ | embedded-hal | 0.2.7 | MIT OR Apache-2.0 | all features |
200
+ | embedded-hal | 1.0.0 | MIT OR Apache-2.0 | all features |
201
+ | embedded-hal-async | 1.0.0 | MIT OR Apache-2.0 | all features |
202
+ | encoding_rs | 0.8.41 | (Apache-2.0 OR MIT) AND BSD-3-Clause | default |
203
+ | enum-as-inner | 0.6.1 | MIT/Apache-2.0 | all features |
204
+ | enumset | 1.1.14 | MIT/Apache-2.0 | all features |
205
+ | enumset_derive | 0.15.0 | MIT/Apache-2.0 | all features |
206
+ | equator | 0.4.2 | MIT | all features |
207
+ | equator-macro | 0.4.2 | MIT | all features |
208
+ | equivalent | 1.0.2 | Apache-2.0 OR MIT | default |
209
+ | errno | 0.3.14 | MIT OR Apache-2.0 | default |
210
+ | event-listener | 5.4.2 | Apache-2.0 OR MIT | all features |
211
+ | event-listener-strategy | 0.5.4 | Apache-2.0 OR MIT | all features |
212
+ | fastrand | 2.5.0 | Apache-2.0 OR MIT | restore-model |
213
+ | fax | 0.2.7 | MIT | default |
214
+ | fdeflate | 0.3.7 | MIT OR Apache-2.0 | default |
215
+ | find-msvc-tools | 0.1.12 | MIT OR Apache-2.0 | restore-model |
216
+ | fixedbitset | 0.5.7 | MIT OR Apache-2.0 | all features |
217
+ | flate2 | 1.1.10 | MIT OR Apache-2.0 | default |
218
+ | float-cmp | 0.9.0 | MIT | default |
219
+ | float-ord | 0.3.2 | MIT / Apache-2.0 | all features |
220
+ | float4 | 0.2.0 | MIT | all features |
221
+ | float8 | 0.7.0 | MIT | all features |
222
+ | fnv | 1.0.7 | Apache-2.0 / MIT | all features |
223
+ | foldhash | 0.1.5 | Zlib | all features |
224
+ | foldhash | 0.2.0 | Zlib | all features |
225
+ | foreign-types | 0.3.2 | MIT/Apache-2.0 | restore-model |
226
+ | foreign-types-shared | 0.1.1 | MIT/Apache-2.0 | restore-model |
227
+ | form_urlencoded | 1.2.2 | MIT OR Apache-2.0 | default |
228
+ | futures-channel | 0.3.34 | MIT OR Apache-2.0 | default |
229
+ | futures-core | 0.3.34 | MIT OR Apache-2.0 | default |
230
+ | futures-io | 0.3.34 | MIT OR Apache-2.0 | all features |
231
+ | futures-lite | 2.6.1 | Apache-2.0 OR MIT | all features |
232
+ | futures-task | 0.3.34 | MIT OR Apache-2.0 | default |
233
+ | futures-util | 0.3.34 | MIT OR Apache-2.0 | default |
234
+ | gemm | 0.19.0 | MIT | all features |
235
+ | gemm-c32 | 0.19.0 | MIT | all features |
236
+ | gemm-c64 | 0.19.0 | MIT | all features |
237
+ | gemm-common | 0.19.0 | MIT | all features |
238
+ | gemm-f16 | 0.19.0 | MIT | all features |
239
+ | gemm-f32 | 0.19.0 | MIT | all features |
240
+ | gemm-f64 | 0.19.0 | MIT | all features |
241
+ | generic-array | 0.14.7 | MIT | default |
242
+ | getrandom | 0.2.17 | MIT OR Apache-2.0 | all features |
243
+ | getrandom | 0.4.3 | MIT OR Apache-2.0 | restore-model |
244
+ | gif | 0.14.2 | MIT OR Apache-2.0 | default |
245
+ | gimli | 0.32.3 | MIT OR Apache-2.0 | all features |
246
+ | gl_generator | 0.14.0 | Apache-2.0 | all features |
247
+ | glow | 0.17.0 | MIT OR Apache-2.0 OR Zlib | all features |
248
+ | glutin_wgl_sys | 0.6.1 | Apache-2.0 | all features |
249
+ | gpu-allocator | 0.28.0 | MIT OR Apache-2.0 | all features |
250
+ | gpu-descriptor | 0.3.2 | MIT OR Apache-2.0 | all features |
251
+ | gpu-descriptor-types | 0.2.0 | MIT OR Apache-2.0 | all features |
252
+ | half | 2.7.1 | MIT OR Apache-2.0 | default |
253
+ | hashbrown | 0.13.2 | MIT OR Apache-2.0 | all features |
254
+ | hashbrown | 0.15.5 | MIT OR Apache-2.0 | all features |
255
+ | hashbrown | 0.16.1 | MIT OR Apache-2.0 | all features |
256
+ | hashbrown | 0.17.1 | MIT OR Apache-2.0 | default |
257
+ | heck | 0.5.0 | MIT OR Apache-2.0 | all features |
258
+ | hermit-abi | 0.5.3 | MIT OR Apache-2.0 | all features |
259
+ | hexf-parse | 0.2.1 | CC0-1.0 | all features |
260
+ | hmac-sha256 | 1.1.14 | ISC | restore-model |
261
+ | home | 0.5.12 | MIT OR Apache-2.0 | all features |
262
+ | http | 1.5.0 | MIT OR Apache-2.0 | default |
263
+ | http-body | 1.1.0 | MIT | default |
264
+ | http-body-util | 0.1.5 | MIT | default |
265
+ | httparse | 1.10.1 | MIT OR Apache-2.0 | default |
266
+ | httpdate | 1.0.3 | MIT OR Apache-2.0 | default |
267
+ | hyper | 1.11.1 | MIT | default |
268
+ | hyper-util | 0.1.20 | MIT | default |
269
+ | ident_case | 1.0.1 | MIT/Apache-2.0 | all features |
270
+ | image | 0.25.10 | MIT OR Apache-2.0 | default |
271
+ | image-webp | 0.2.4 | MIT OR Apache-2.0 | default |
272
+ | imagesize | 0.13.0 | MIT | default |
273
+ | indexmap | 2.14.1 | Apache-2.0 OR MIT | default |
274
+ | inflections | 1.1.1 | MIT | all features |
275
+ | is_terminal_polyfill | 1.70.2 | MIT OR Apache-2.0 | all features |
276
+ | itertools | 0.14.0 | MIT OR Apache-2.0 | all features |
277
+ | itoa | 1.0.18 | MIT OR Apache-2.0 | default |
278
+ | jni-sys | 0.3.1 | MIT OR Apache-2.0 | all features |
279
+ | jni-sys | 0.4.1 | MIT OR Apache-2.0 | all features |
280
+ | jni-sys-macros | 0.4.1 | MIT OR Apache-2.0 | all features |
281
+ | js-sys | 0.3.105 | MIT OR Apache-2.0 | default |
282
+ | khronos-egl | 6.0.0 | MIT/Apache-2.0 | all features |
283
+ | khronos_api | 3.1.0 | Apache-2.0 | all features |
284
+ | kurbo | 0.11.3 | Apache-2.0 OR MIT | default |
285
+ | lazy_static | 1.5.0 | MIT OR Apache-2.0 | default |
286
+ | libc | 0.2.189 | MIT OR Apache-2.0 | default |
287
+ | libloading | 0.8.9 | ISC | all features |
288
+ | libloading | 0.9.0 | ISC | all features |
289
+ | libm | 0.2.16 | MIT | all features |
290
+ | libredox | 0.1.24 | MIT | all features |
291
+ | linux-raw-sys | 0.12.1 | Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT | restore-model |
292
+ | linux-raw-sys | 0.4.15 | Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT | all features |
293
+ | litrs | 1.0.0 | MIT OR Apache-2.0 | all features |
294
+ | lock_api | 0.4.14 | MIT OR Apache-2.0 | all features |
295
+ | log | 0.4.34 | MIT OR Apache-2.0 | default |
296
+ | lzma-rust2 | 0.15.8 | Apache-2.0 | restore-model |
297
+ | macerator | 0.3.4 | MIT OR Apache-2.0 | all features |
298
+ | macerator-macros | 0.2.0 | MIT OR Apache-2.0 | all features |
299
+ | matchers | 0.2.0 | MIT | default |
300
+ | matchit | 0.8.4 | MIT AND BSD-3-Clause | default |
301
+ | matrixmultiply | 0.3.11 | MIT/Apache-2.0 | all features |
302
+ | md5 | 0.8.1 | Apache-2.0 OR MIT | all features |
303
+ | memchr | 2.8.3 | Unlicense OR MIT | default |
304
+ | memmap2 | 0.9.11 | MIT OR Apache-2.0 | all features |
305
+ | mime | 0.3.17 | MIT OR Apache-2.0 | default |
306
+ | miniz_oxide | 0.8.9 | MIT OR Zlib OR Apache-2.0 | default |
307
+ | miniz_oxide | 0.9.1 | MIT OR Zlib OR Apache-2.0 | default |
308
+ | mio | 1.2.3 | MIT | default |
309
+ | moddef | 0.3.0 | MIT | all features |
310
+ | moxcms | 0.8.1 | BSD-3-Clause OR Apache-2.0 | default |
311
+ | multer | 3.1.0 | MIT | default |
312
+ | multiversion | 0.9.0 | MIT OR Apache-2.0 | default |
313
+ | multiversion-macros | 0.9.0 | MIT OR Apache-2.0 | default |
314
+ | multiversion_no_op | 1.0.0 | Apache-2.0 OR MIT | default |
315
+ | naga | 29.0.4 | MIT OR Apache-2.0 | all features |
316
+ | native-tls | 0.2.18 | MIT OR Apache-2.0 | restore-model |
317
+ | nb | 0.1.3 | MIT OR Apache-2.0 | all features |
318
+ | nb | 1.1.0 | MIT OR Apache-2.0 | all features |
319
+ | ndarray | 0.17.2 | MIT OR Apache-2.0 | all features |
320
+ | ndk-sys | 0.6.0+11769913 | MIT OR Apache-2.0 | all features |
321
+ | nom | 8.0.0 | MIT | all features |
322
+ | nu-ansi-term | 0.50.3 | MIT | default |
323
+ | num | 0.4.3 | MIT OR Apache-2.0 | all features |
324
+ | num-bigint | 0.4.8 | MIT OR Apache-2.0 | all features |
325
+ | num-complex | 0.4.6 | MIT OR Apache-2.0 | all features |
326
+ | num-integer | 0.1.47 | MIT OR Apache-2.0 | all features |
327
+ | num-iter | 0.1.46 | MIT OR Apache-2.0 | all features |
328
+ | num-rational | 0.4.2 | MIT OR Apache-2.0 | all features |
329
+ | num-traits | 0.2.19 | MIT OR Apache-2.0 | default |
330
+ | num_cpus | 1.17.0 | MIT OR Apache-2.0 | all features |
331
+ | objc2 | 0.6.4 | MIT | all features |
332
+ | objc2-core-foundation | 0.3.2 | Zlib OR Apache-2.0 OR MIT | all features |
333
+ | objc2-encode | 4.1.0 | MIT | all features |
334
+ | objc2-foundation | 0.3.2 | MIT | all features |
335
+ | objc2-metal | 0.3.2 | Zlib OR Apache-2.0 OR MIT | all features |
336
+ | objc2-quartz-core | 0.3.2 | Zlib OR Apache-2.0 OR MIT | all features |
337
+ | object | 0.37.3 | Apache-2.0 OR MIT | all features |
338
+ | once_cell | 1.21.4 | MIT OR Apache-2.0 | default |
339
+ | once_cell_polyfill | 1.70.2 | MIT OR Apache-2.0 | all features |
340
+ | oneshot | 0.2.1 | MIT OR Apache-2.0 | all features |
341
+ | onnx-ir | 0.21.0 | MIT OR Apache-2.0 | all features |
342
+ | onnx-ir-derive | 0.21.0 | MIT OR Apache-2.0 | all features |
343
+ | openssl | 0.10.81 | Apache-2.0 | restore-model |
344
+ | openssl-macros | 0.1.1 | MIT/Apache-2.0 | restore-model |
345
+ | openssl-probe | 0.2.1 | MIT OR Apache-2.0 | restore-model |
346
+ | openssl-sys | 0.9.117 | MIT | restore-model |
347
+ | option-ext | 0.2.0 | MPL-2.0 | all features |
348
+ | ordered-float | 5.5.0 | MIT | all features |
349
+ | ort | 2.0.0-rc.13 | MIT OR Apache-2.0 | restore-model |
350
+ | ort-sys | 2.0.0-rc.13 | MIT OR Apache-2.0 | restore-model |
351
+ | parking | 2.2.1 | Apache-2.0 OR MIT | all features |
352
+ | parking_lot | 0.12.5 | MIT OR Apache-2.0 | all features |
353
+ | parking_lot_core | 0.9.12 | MIT OR Apache-2.0 | all features |
354
+ | paste | 1.0.15 | MIT OR Apache-2.0 | all features |
355
+ | pem-rfc7468 | 1.0.0 | Apache-2.0 OR MIT | restore-model |
356
+ | percent-encoding | 2.3.2 | MIT OR Apache-2.0 | default |
357
+ | petgraph | 0.8.3 | MIT OR Apache-2.0 | all features |
358
+ | pico-args | 0.5.0 | MIT | default |
359
+ | pin-project-lite | 0.2.17 | Apache-2.0 OR MIT | default |
360
+ | pkg-config | 0.3.34 | MIT OR Apache-2.0 | restore-model |
361
+ | png | 0.17.16 | MIT OR Apache-2.0 | default |
362
+ | png | 0.18.1 | MIT OR Apache-2.0 | default |
363
+ | portable-atomic | 1.15.0 | Apache-2.0 OR MIT | all features |
364
+ | portable-atomic-util | 0.2.8 | Apache-2.0 OR MIT | all features |
365
+ | presser | 0.3.1 | MIT OR Apache-2.0 | all features |
366
+ | prettyplease | 0.1.25 | MIT OR Apache-2.0 | all features |
367
+ | prettyplease | 0.2.37 | MIT OR Apache-2.0 | all features |
368
+ | proc-macro2 | 1.0.107 | MIT OR Apache-2.0 | default |
369
+ | profiling | 1.0.18 | MIT OR Apache-2.0 | all features |
370
+ | protobuf | 3.7.2 | MIT | all features |
371
+ | protobuf-codegen | 3.7.2 | MIT | all features |
372
+ | protobuf-parse | 3.7.2 | MIT | all features |
373
+ | protobuf-support | 3.7.2 | MIT | all features |
374
+ | pulp | 0.22.3 | MIT | all features |
375
+ | pulp-wasm-simd-flag | 0.1.1 | MIT | all features |
376
+ | pxfm | 0.1.30 | BSD-3-Clause OR Apache-2.0 | default |
377
+ | pyo3 | 0.29.2 | MIT OR Apache-2.0 | all features |
378
+ | pyo3-build-config | 0.29.2 | MIT OR Apache-2.0 | all features |
379
+ | pyo3-ffi | 0.29.2 | MIT OR Apache-2.0 | all features |
380
+ | pyo3-macros | 0.29.2 | MIT OR Apache-2.0 | all features |
381
+ | pyo3-macros-backend | 0.29.2 | MIT OR Apache-2.0 | all features |
382
+ | quick-error | 2.0.1 | MIT/Apache-2.0 | default |
383
+ | quote | 1.0.47 | MIT OR Apache-2.0 | default |
384
+ | r-efi | 6.0.0 | MIT OR Apache-2.0 OR LGPL-2.1-or-later | restore-model |
385
+ | rand | 0.10.2 | MIT OR Apache-2.0 | all features |
386
+ | rand_core | 0.10.1 | MIT OR Apache-2.0 | all features |
387
+ | rand_distr | 0.6.0 | MIT OR Apache-2.0 | all features |
388
+ | range-alloc | 0.1.5 | MIT OR Apache-2.0 | all features |
389
+ | raw-cpuid | 11.6.0 | MIT | all features |
390
+ | raw-window-handle | 0.6.2 | MIT OR Apache-2.0 OR Zlib | all features |
391
+ | raw-window-metal | 1.1.0 | MIT OR Apache-2.0 | all features |
392
+ | rawpointer | 0.2.1 | MIT/Apache-2.0 | all features |
393
+ | rayon | 1.12.0 | MIT OR Apache-2.0 | default |
394
+ | rayon-core | 1.13.0 | MIT OR Apache-2.0 | default |
395
+ | reborrow | 0.5.5 | MIT | all features |
396
+ | redox_syscall | 0.5.18 | MIT | all features |
397
+ | redox_users | 0.5.2 | MIT | all features |
398
+ | ref-cast | 1.0.27 | MIT OR Apache-2.0 | default |
399
+ | ref-cast-impl | 1.0.27 | MIT OR Apache-2.0 | default |
400
+ | regex | 1.13.1 | MIT OR Apache-2.0 | all features |
401
+ | regex-automata | 0.4.18 | MIT OR Apache-2.0 | default |
402
+ | regex-syntax | 0.8.11 | MIT OR Apache-2.0 | default |
403
+ | renderdoc-sys | 1.1.0 | MIT OR Apache-2.0 | all features |
404
+ | resvg | 0.45.1 | Apache-2.0 OR MIT | default |
405
+ | rgb | 0.8.53 | MIT | default |
406
+ | rmp | 0.8.15 | MIT | all features |
407
+ | rmp-serde | 1.3.1 | MIT | all features |
408
+ | robust | 1.2.0 | MIT OR Apache-2.0 | default |
409
+ | roxmltree | 0.20.0 | MIT OR Apache-2.0 | default |
410
+ | rust-format | 0.3.4 | MIT OR Apache-2.0 | all features |
411
+ | rustc-demangle | 0.1.28 | MIT/Apache-2.0 | all features |
412
+ | rustc-hash | 1.1.0 | Apache-2.0/MIT | all features |
413
+ | rustc-hash | 2.1.3 | Apache-2.0 OR MIT | all features |
414
+ | rustc_version | 0.4.1 | MIT OR Apache-2.0 | all features |
415
+ | rustix | 0.38.44 | Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT | all features |
416
+ | rustix | 1.1.4 | Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT | restore-model |
417
+ | rustls-pki-types | 1.15.1 | MIT OR Apache-2.0 | restore-model |
418
+ | rustversion | 1.0.23 | MIT OR Apache-2.0 | default |
419
+ | ryu | 1.0.23 | Apache-2.0 OR BSL-1.0 | default |
420
+ | safetensors | 0.7.0 | Apache-2.0 | all features |
421
+ | same-file | 1.0.6 | Unlicense/MIT | all features |
422
+ | sanitize-filename | 0.6.0 | MIT | all features |
423
+ | schannel | 0.1.29 | MIT | restore-model |
424
+ | schemars | 1.2.2 | MIT | default |
425
+ | schemars_derive | 1.2.2 | MIT | default |
426
+ | scopeguard | 1.2.0 | MIT OR Apache-2.0 | default |
427
+ | security-framework | 3.7.0 | MIT OR Apache-2.0 | restore-model |
428
+ | security-framework-sys | 2.17.0 | MIT OR Apache-2.0 | restore-model |
429
+ | semver | 1.0.28 | MIT OR Apache-2.0 | all features |
430
+ | seq-macro | 0.3.6 | MIT OR Apache-2.0 | all features |
431
+ | serde | 1.0.229 | MIT OR Apache-2.0 | default |
432
+ | serde_bytes | 0.11.19 | MIT OR Apache-2.0 | all features |
433
+ | serde_core | 1.0.229 | MIT OR Apache-2.0 | default |
434
+ | serde_derive | 1.0.229 | MIT OR Apache-2.0 | default |
435
+ | serde_derive_internals | 0.30.0 | MIT OR Apache-2.0 | default |
436
+ | serde_json | 1.0.151 | MIT OR Apache-2.0 | default |
437
+ | serde_path_to_error | 0.1.20 | MIT OR Apache-2.0 | default |
438
+ | serde_spanned | 1.1.1 | MIT OR Apache-2.0 | all features |
439
+ | serde_urlencoded | 0.7.1 | MIT/Apache-2.0 | default |
440
+ | sha2 | 0.10.9 | MIT OR Apache-2.0 | default |
441
+ | sharded-slab | 0.1.7 | MIT | default |
442
+ | shlex | 2.0.1 | MIT OR Apache-2.0 | restore-model |
443
+ | signal-hook-registry | 1.4.8 | MIT OR Apache-2.0 | default |
444
+ | simd-adler32 | 0.3.10 | MIT | default |
445
+ | simdutf8 | 0.1.5 | MIT OR Apache-2.0 | default |
446
+ | simplecss | 0.2.2 | Apache-2.0 OR MIT | default |
447
+ | siphasher | 1.0.3 | MIT/Apache-2.0 | default |
448
+ | slab | 0.4.12 | MIT | default |
449
+ | slotmap | 1.1.1 | Zlib | all features |
450
+ | smallvec | 1.15.2 | MIT OR Apache-2.0 | default |
451
+ | socket2 | 0.6.5 | MIT OR Apache-2.0 | default |
452
+ | socks | 0.3.4 | MIT/Apache-2.0 | restore-model |
453
+ | spin | 0.10.1 | MIT | all features |
454
+ | spin | 0.9.9 | MIT | default |
455
+ | spirv | 0.4.0+sdk-1.4.341.0 | Apache-2.0 | all features |
456
+ | stable-vec | 0.4.3 | MIT/Apache-2.0 | all features |
457
+ | static_assertions | 1.1.0 | MIT OR Apache-2.0 | all features |
458
+ | strict-num | 0.1.1 | MIT | default |
459
+ | strsim | 0.11.1 | MIT | all features |
460
+ | strum | 0.28.0 | MIT | all features |
461
+ | strum_macros | 0.28.0 | MIT | all features |
462
+ | svgtypes | 0.15.3 | Apache-2.0 OR MIT | default |
463
+ | syn | 1.0.109 | MIT OR Apache-2.0 | all features |
464
+ | syn | 2.0.119 | MIT OR Apache-2.0 | default |
465
+ | syn | 3.0.4 | MIT OR Apache-2.0 | default |
466
+ | sync_wrapper | 1.0.2 | Apache-2.0 | default |
467
+ | sysctl | 0.6.0 | MIT | all features |
468
+ | target-lexicon | 0.13.5 | Apache-2.0 WITH LLVM-exception | all features |
469
+ | tempfile | 3.27.0 | MIT OR Apache-2.0 | restore-model |
470
+ | text_placeholder | 0.5.1 | MIT | all features |
471
+ | textdistance | 1.1.1 | MIT | all features |
472
+ | thiserror | 1.0.69 | MIT OR Apache-2.0 | all features |
473
+ | thiserror | 2.0.20 | MIT OR Apache-2.0 | all features |
474
+ | thiserror-impl | 1.0.69 | MIT OR Apache-2.0 | all features |
475
+ | thiserror-impl | 2.0.20 | MIT OR Apache-2.0 | all features |
476
+ | thread-tree | 0.3.3 | MIT OR Apache-2.0 | all features |
477
+ | thread_local | 1.1.10 | MIT OR Apache-2.0 | default |
478
+ | tiff | 0.11.3 | MIT | default |
479
+ | tiny-keccak | 2.0.2 | CC0-1.0 | all features |
480
+ | tiny-skia | 0.11.4 | BSD-3-Clause | default |
481
+ | tiny-skia-path | 0.11.4 | BSD-3-Clause | default |
482
+ | tokio | 1.53.1 | MIT | default |
483
+ | tokio-macros | 2.7.2 | MIT | default |
484
+ | toml | 1.1.6+spec-1.1.0 | MIT OR Apache-2.0 | all features |
485
+ | toml_datetime | 1.1.1+spec-1.1.0 | MIT OR Apache-2.0 | all features |
486
+ | toml_parser | 1.1.3+spec-1.1.0 | MIT OR Apache-2.0 | all features |
487
+ | toml_writer | 1.1.2+spec-1.1.0 | MIT OR Apache-2.0 | all features |
488
+ | tower | 0.5.3 | MIT | default |
489
+ | tower-http | 0.6.11 | MIT | default |
490
+ | tower-layer | 0.3.3 | MIT | default |
491
+ | tower-service | 0.3.3 | MIT | default |
492
+ | tracing | 0.1.44 | MIT | default |
493
+ | tracing-attributes | 0.1.31 | MIT | default |
494
+ | tracing-core | 0.1.36 | MIT | default |
495
+ | tracing-log | 0.2.0 | MIT | default |
496
+ | tracing-subscriber | 0.3.23 | MIT | default |
497
+ | tynm | 0.2.0 | MIT OR Apache-2.0 | all features |
498
+ | type-map | 0.5.1 | MIT/Apache-2.0 | all features |
499
+ | typenum | 1.20.1 | MIT OR Apache-2.0 | default |
500
+ | unicode-ident | 1.0.24 | (MIT OR Apache-2.0) AND Unicode-3.0 | default |
501
+ | unicode-segmentation | 1.13.3 | MIT OR Apache-2.0 | all features |
502
+ | unicode-width | 0.2.2 | MIT OR Apache-2.0 | all features |
503
+ | unicode-xid | 0.2.6 | MIT OR Apache-2.0 | all features |
504
+ | unty | 0.0.4 | MIT OR Apache-2.0 | all features |
505
+ | ureq | 3.4.2 | MIT OR Apache-2.0 | restore-model |
506
+ | ureq-proto | 0.6.3 | MIT OR Apache-2.0 | restore-model |
507
+ | usvg | 0.45.1 | Apache-2.0 OR MIT | default |
508
+ | utf8-zero | 0.8.1 | MIT OR Apache-2.0 | restore-model |
509
+ | utf8parse | 0.2.2 | Apache-2.0 OR MIT | all features |
510
+ | uuid | 1.26.1 | Apache-2.0 OR MIT | all features |
511
+ | variadics_please | 1.1.0 | MIT OR Apache-2.0 | all features |
512
+ | vcpkg | 0.2.15 | MIT/Apache-2.0 | restore-model |
513
+ | version_check | 0.9.5 | MIT/Apache-2.0 | default |
514
+ | void | 1.0.2 | MIT | all features |
515
+ | walkdir | 2.5.0 | Unlicense/MIT | all features |
516
+ | wasi | 0.11.1+wasi-snapshot-preview1 | Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT | default |
517
+ | wasm-bindgen | 0.2.128 | MIT OR Apache-2.0 | default |
518
+ | wasm-bindgen-futures | 0.4.78 | MIT OR Apache-2.0 | all features |
519
+ | wasm-bindgen-macro | 0.2.128 | MIT OR Apache-2.0 | default |
520
+ | wasm-bindgen-macro-support | 0.2.128 | MIT OR Apache-2.0 | default |
521
+ | wasm-bindgen-rayon | 1.3.0 | Apache-2.0 | all features |
522
+ | wasm-bindgen-shared | 0.2.128 | MIT OR Apache-2.0 | default |
523
+ | wasm_sync | 0.1.2 | MIT OR Apache-2.0 | all features |
524
+ | wayland-sys | 0.31.11 | MIT | all features |
525
+ | web-sys | 0.3.105 | MIT OR Apache-2.0 | all features |
526
+ | web-time | 1.1.0 | MIT OR Apache-2.0 | default |
527
+ | webpki-root-certs | 1.0.9 | CDLA-Permissive-2.0 | restore-model |
528
+ | weezl | 0.1.12 | MIT OR Apache-2.0 | default |
529
+ | wgpu | 29.0.4 | MIT OR Apache-2.0 | all features |
530
+ | wgpu-core | 29.0.4 | MIT OR Apache-2.0 | all features |
531
+ | wgpu-core-deps-apple | 29.0.4 | MIT OR Apache-2.0 | all features |
532
+ | wgpu-core-deps-emscripten | 29.0.4 | MIT OR Apache-2.0 | all features |
533
+ | wgpu-core-deps-windows-linux-android | 29.0.4 | MIT OR Apache-2.0 | all features |
534
+ | wgpu-hal | 29.0.4 | MIT OR Apache-2.0 | all features |
535
+ | wgpu-naga-bridge | 29.0.4 | MIT OR Apache-2.0 | all features |
536
+ | wgpu-types | 29.0.4 | MIT OR Apache-2.0 | all features |
537
+ | which | 4.4.2 | MIT | all features |
538
+ | winapi | 0.3.9 | MIT/Apache-2.0 | restore-model |
539
+ | winapi-i686-pc-windows-gnu | 0.4.0 | MIT/Apache-2.0 | restore-model |
540
+ | winapi-util | 0.1.11 | Unlicense OR MIT | all features |
541
+ | winapi-x86_64-pc-windows-gnu | 0.4.0 | MIT/Apache-2.0 | restore-model |
542
+ | windows | 0.62.2 | MIT OR Apache-2.0 | all features |
543
+ | windows-collections | 0.3.2 | MIT OR Apache-2.0 | all features |
544
+ | windows-core | 0.62.2 | MIT OR Apache-2.0 | all features |
545
+ | windows-future | 0.3.2 | MIT OR Apache-2.0 | all features |
546
+ | windows-implement | 0.60.2 | MIT OR Apache-2.0 | all features |
547
+ | windows-interface | 0.59.3 | MIT OR Apache-2.0 | all features |
548
+ | windows-link | 0.2.1 | MIT OR Apache-2.0 | default |
549
+ | windows-numerics | 0.3.1 | MIT OR Apache-2.0 | all features |
550
+ | windows-result | 0.4.1 | MIT OR Apache-2.0 | all features |
551
+ | windows-strings | 0.5.1 | MIT OR Apache-2.0 | all features |
552
+ | windows-sys | 0.59.0 | MIT OR Apache-2.0 | all features |
553
+ | windows-sys | 0.61.2 | MIT OR Apache-2.0 | default |
554
+ | windows-targets | 0.52.6 | MIT OR Apache-2.0 | all features |
555
+ | windows-threading | 0.2.1 | MIT OR Apache-2.0 | all features |
556
+ | windows_aarch64_gnullvm | 0.52.6 | MIT OR Apache-2.0 | all features |
557
+ | windows_aarch64_msvc | 0.52.6 | MIT OR Apache-2.0 | all features |
558
+ | windows_i686_gnu | 0.52.6 | MIT OR Apache-2.0 | all features |
559
+ | windows_i686_gnullvm | 0.52.6 | MIT OR Apache-2.0 | all features |
560
+ | windows_i686_msvc | 0.52.6 | MIT OR Apache-2.0 | all features |
561
+ | windows_x86_64_gnu | 0.52.6 | MIT OR Apache-2.0 | all features |
562
+ | windows_x86_64_gnullvm | 0.52.6 | MIT OR Apache-2.0 | all features |
563
+ | windows_x86_64_msvc | 0.52.6 | MIT OR Apache-2.0 | all features |
564
+ | winnow | 1.0.4 | MIT | all features |
565
+ | xml-rs | 0.8.29 | MIT | all features |
566
+ | xmlwriter | 0.1.0 | MIT | default |
567
+ | xxhash-rust | 0.8.18 | BSL-1.0 | all features |
568
+ | zerocopy | 0.8.56 | BSD-2-Clause OR Apache-2.0 OR MIT | default |
569
+ | zerocopy-derive | 0.8.56 | BSD-2-Clause OR Apache-2.0 OR MIT | default |
570
+ | zeroize | 1.9.0 | Apache-2.0 OR MIT | restore-model |
571
+ | zmij | 1.0.23 | MIT | default |
572
+ | zune-core | 0.5.3 | MIT OR Apache-2.0 OR Zlib | default |
573
+ | zune-jpeg | 0.5.15 | MIT OR Apache-2.0 OR Zlib | default |
studio/assets/denoiser.worker-ER2QG0XM.js ADDED
@@ -0,0 +1 @@
 
 
1
+ const r=self;let l="",i="",d="",g="",a=null;function h(){return a||(a=import(new URL(`denoise.js${i?`?v=${i}`:""}`,l).href),a.catch(()=>{a=null})),a}async function u(n){const t=await h();let e=0;const{backend:s}=await t.load({url:d,sha256:g,onProgress:n?o=>{const c=performance.now();(o.cached||o.received===o.total||c-e>200)&&(e=c,r.postMessage({type:"progress",got:o.received,total:o.total||null}))}:void 0});return s}async function y(n){const t=new Int32Array(n.shared,0,2);try{await u(!1);const e=await(await h()).run(n.input,n.width,n.height);new Float32Array(n.shared,8,e.length).set(e),Atomics.store(t,0,1)}catch(e){const s=new TextEncoder().encode(String(e?.message??e)).slice(0,n.shared.byteLength-8);new Uint8Array(n.shared,8,s.length).set(s),Atomics.store(t,1,s.length),Atomics.store(t,0,2)}Atomics.notify(t,0)}r.onmessage=n=>{const t=n.data;if(t.type==="init"&&({base:l,token:i,url:d,sha256:g}=t),t.type==="init"||t.type==="port"){t.port.onmessage=e=>{e.data?.type==="run"&&y(e.data)};return}t.type==="download"&&u(!0).then(e=>r.postMessage({type:"done",ok:!0,backend:e}),e=>r.postMessage({type:"done",ok:!1,message:String(e?.message??e)}))};
studio/assets/engine.worker-Cn2MnOae.js ADDED
@@ -0,0 +1 @@
 
 
1
+ const i=self;let o=null,g=null,y=null,p=null,u=null;async function h(e){const t=typeof crossOriginIsolated<"u"&&crossOriginIsolated,s=t?"pkg-threads":"pkg",r=e.token?`?v=${e.token}`:"";o=await import(new URL(`${s}/inkvec_studio_wasm.js${r}`,e.base).href),g=(await o.default({module_or_path:new URL(`${s}/inkvec_studio_wasm_bg.wasm${r}`,e.base)})).memory??null;let l=1,d=null;if(t&&o.initThreadPool){const c=Math.max(1,Math.min(navigator.hardwareConcurrency||4,16)-1);try{await o.initThreadPool(c),l=c+1}catch(f){d=String(f?.message??f)}}p=e.generations?new Int32Array(e.generations):null,u=e.denoiserPort,u&&t&&(w(u),o.enable_denoiser()),y=new o.Studio,i.postMessage({type:"ready",threads:l,poolError:d,isolated:t,version:o.version(),denoiserUrl:o.denoiser_model_url(),denoiserSha256:o.denoiser_model_sha256(),denoiserRepo:o.denoiser_model_repo()})}function w(e){i.inkvecDenoiseSync=(t,s,r)=>{const n=t.length,a=new SharedArrayBuffer(8+Math.max(n*4,4096)),l=new Int32Array(a,0,2);if(e.postMessage({type:"run",input:t.slice(),width:s,height:r,shared:a}),Atomics.wait(l,0,0,6e5)==="timed-out")throw new Error("the denoiser did not answer in ten minutes");if(Atomics.load(l,0)!==1){const c=new TextDecoder().decode(new Uint8Array(a,8,Atomics.load(l,1)).slice());throw new Error(c||"the denoiser failed")}return new Float32Array(a,8,n).slice()}}function S(e){return p?Atomics.load(p,0)===e:!0}function _(e){const t=y;if(!t)throw new Error("the engine is not loaded");switch(e.op){case"capabilities":return JSON.parse(t.capabilities(!!e.supported,!!e.installed,e.bytes??void 0));case"open_bytes":return JSON.parse(t.open_bytes(e.bytes,e.name??void 0));case"trace":{const s=e.generation,r=t.trace(JSON.stringify(e.request),e.draftPx,e.draftSeconds,s,(n,a)=>i.postMessage({type:"stage",generation:s,name:n,ms:a}),S);return r===void 0?null:JSON.parse(r)}case"preview":return JSON.parse(t.preview(JSON.stringify(e.request),e.draftPx,e.draftSeconds));case"export":return t.export_files(JSON.stringify({request:e.request}),!!e.zip).map(r=>({name:r.name,data:r.data}));case"close":return t.close(),null;default:return JSON.parse(t.call(e.op,JSON.stringify(e.args??{})))}}function v(e){return e instanceof WebAssembly.RuntimeError||e instanceof RangeError&&/memory|allocation/i.test(e.message)||/unreachable|out of memory|memory access out of bounds/i.test(String(e?.message??e))}let m=Promise.resolve();i.onmessage=e=>{const t=e.data;m=m.then(async()=>{if(t.type==="init"){try{await h(t)}catch(r){i.postMessage({type:"loadfail",error:String(r?.stack??r)})}return}const s=performance.now();try{const r=_(t),n=[];if(t.op==="export")for(const a of r)n.push(a.data.buffer);i.postMessage({type:"reply",id:t.id,ok:!0,value:r,ms:performance.now()-s,mem:g?.buffer.byteLength??null},n)}catch(r){const n=String(r?.message??r);i.postMessage({type:"reply",id:t.id,ok:!1,error:n,crashed:v(r)})}})};
studio/assets/main-B-nuHqfb.css ADDED
@@ -0,0 +1 @@
 
 
1
+ @font-face{font-family:Inter Studio;src:url(../fonts/inter-latin.woff2) format("woff2");font-weight:100 900;font-style:normal;font-display:swap;unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Playfair Studio;src:url(../fonts/playfair-latin.woff2) format("woff2");font-weight:400 900;font-style:normal;font-display:swap;unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}:root,:root[data-theme=dark]{color-scheme:dark;--void: #0c0a09;--stage: #141210;--paper: #1a1816;--card: #211f1c;--surface: #2a2724;--highlight: #35322e;--ink: #faf8f5;--dim: rgba(250, 248, 245, .75);--faint: rgba(250, 248, 245, .55);--muted: rgba(250, 248, 245, .4);--rule: rgba(250, 248, 245, .08);--rule2: #2a2724;--accent: #c9754a;--accent-text: #d4896a;--accent-hover: #d4896a;--accent-ink: #1a1816;--accent-soft: rgba(201, 117, 74, .12);--accent-subtle: rgba(201, 117, 74, .08);--gold: #b8976c;--gold-soft: rgba(184, 151, 108, .15);--good: #34d399;--goodbg: rgba(52, 211, 153, .15);--bad: #f87171;--badbg: rgba(248, 113, 113, .15);--anchor: #f87171;--handle: #b8976c;--wire: #faf8f5;--vt: #9a938c;--checker-a: #191715;--checker-b: #141210;--focus: rgba(201, 117, 74, .35);--focus-line: #c9754a;--state-draft: #b8976c;--state-final: #34d399;--state-stale: #c9754a;--shadow-sm: 0 4px 12px -2px rgba(12, 10, 9, .4);--shadow: 0 8px 24px -4px rgba(12, 10, 9, .5);--shadow-lg: 0 20px 50px -12px rgba(12, 10, 9, .6);--shadow-xl: 0 30px 70px -20px rgba(12, 10, 9, .7);--glow: 0 6px 20px rgba(201, 117, 74, .25)}:root[data-theme=light]{color-scheme:light;--void: #e6e1d9;--stage: #f0ece6;--paper: #faf8f5;--card: #ffffff;--surface: #eae5dd;--highlight: #ded8ce;--ink: #1a1816;--dim: rgba(26, 24, 22, .75);--faint: rgba(26, 24, 22, .58);--muted: rgba(26, 24, 22, .46);--rule: rgba(26, 24, 22, .1);--rule2: #d8d2c8;--accent: #c9754a;--accent-text: #9c5730;--accent-hover: #b3603a;--accent-ink: #faf8f5;--accent-soft: rgba(201, 117, 74, .14);--accent-subtle: rgba(201, 117, 74, .08);--gold: #8a6a3f;--gold-soft: rgba(138, 106, 63, .14);--good: #1c7a55;--goodbg: rgba(28, 122, 85, .14);--bad: #b83232;--badbg: rgba(184, 50, 50, .13);--anchor: #b83232;--handle: #8a6a3f;--wire: #1a1816;--vt: #6f6862;--checker-a: #ffffff;--checker-b: #e8e3db;--focus: rgba(201, 117, 74, .45);--focus-line: #9c5730;--state-draft: #8a6a3f;--state-final: #1c7a55;--state-stale: #9c5730;--shadow-sm: 0 4px 12px -2px rgba(90, 76, 60, .12);--shadow: 0 8px 24px -4px rgba(90, 76, 60, .16);--shadow-lg: 0 20px 50px -12px rgba(90, 76, 60, .2);--shadow-xl: 0 30px 70px -20px rgba(90, 76, 60, .24);--glow: 0 6px 20px rgba(201, 117, 74, .28)}:root{--font-display: "Playfair Studio", "Playfair Display", Georgia, serif;--font-body: "Inter Studio", Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;--h-compact: 28px;--h-control: 32px;--h-pill: 36px;--h-appbar: 46px;--h-status: 26px;--h-row: 30px;--t-chrome: 12.5px;--t-panel: 13px;--t-label: 11.5px;--t-eyebrow: 10px;--s1: 4px;--s2: 8px;--s3: 12px;--s4: 16px;--s5: 24px;--s6: 32px;--rail-pad: 14px;--rail-w: 352px;--radius-sm: 6px;--radius: 8px;--radius-lg: 12px;--radius-xl: 16px;--radius-full: 9999px;--ease-out-expo: cubic-bezier(.16, 1, .3, 1);--ease-smooth: cubic-bezier(.4, 0, .2, 1);--d-micro: .15s;--d-fast: .2s;--d-normal: .4s}@media(prefers-reduced-motion:reduce){:root{--d-micro: 0ms;--d-fast: 0ms;--d-normal: 0ms}}*,*:before,*:after{box-sizing:border-box}html,body{height:100%;margin:0;overflow:hidden}body{background:var(--paper);color:var(--ink);font:400 var(--t-panel) / 1.5 var(--font-body);-webkit-font-smoothing:antialiased;user-select:none;cursor:default}#app{height:100%;display:flex;flex-direction:column}:focus{outline:none}:focus-visible{outline:2px solid var(--focus-line);outline-offset:2px;border-radius:var(--radius-sm)}a{color:var(--accent-text);text-decoration:none}a:hover{text-decoration:underline}button{font:inherit;color:inherit;background:none;border:none;padding:0;cursor:pointer}.num{font-variant-numeric:tabular-nums}.mono{font-family:var(--font-mono);font-variant-numeric:tabular-nums}.serif{font-family:var(--font-display);letter-spacing:-.03em}.eyebrow{font-size:var(--t-eyebrow);letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}.dim{color:var(--dim)}.faint{color:var(--faint)}.muted{color:var(--muted)}.sep{width:1px;height:18px;background:var(--rule2);flex:none}.spacer{flex:1}kbd{font:500 10.5px var(--font-mono);border:1px solid var(--highlight);border-radius:4px;padding:1px 5px;color:var(--faint)}.btn{height:var(--h-control);padding:0 16px;border-radius:var(--radius-full);border:1px solid var(--rule2);background:transparent;color:var(--dim);font-weight:500;font-size:var(--t-chrome);display:inline-flex;align-items:center;justify-content:center;gap:7px;white-space:nowrap;transition:transform var(--d-micro) var(--ease-smooth),background var(--d-micro),border-color var(--d-micro),box-shadow var(--d-micro)}.btn:hover:not(:disabled){border-color:var(--highlight);color:var(--ink)}.btn:active:not(:disabled){transform:scale(.98)}.btn:disabled{opacity:.45;cursor:default}.btn.primary{height:var(--h-pill);border-color:var(--accent);background:var(--accent);color:var(--accent-ink);font-weight:600;font-size:var(--t-panel);box-shadow:var(--glow)}.btn.primary:hover:not(:disabled){background:var(--accent-hover);border-color:var(--accent-hover);color:var(--accent-ink);transform:translateY(-2px)}.btn.ghost{border-color:transparent}.btn.ghost:hover:not(:disabled){background:var(--surface)}.btn.compact{height:var(--h-compact);padding:0 11px;border-radius:var(--radius);font-size:var(--t-chrome)}.btn.icon{width:var(--h-control);padding:0}.btn.icon.compact{width:var(--h-compact)}.btn.danger{color:var(--bad)}.seg{display:inline-flex;gap:2px;padding:2px;background:var(--card);border:1px solid var(--rule2);border-radius:7px}.seg>button{font-size:var(--t-label);padding:4px 11px;border-radius:5px;color:var(--faint);white-space:nowrap;transition:background var(--d-micro),color var(--d-micro)}.seg>button:hover{color:var(--dim)}.seg>button[aria-pressed=true]{background:var(--highlight);color:var(--ink);font-weight:500}.seg>button:disabled{color:var(--muted);cursor:default}.toggle{font-size:var(--t-label);padding:3px 9px;border-radius:var(--radius-sm);border:1px solid transparent;color:var(--faint)}.toggle:hover{color:var(--dim)}.toggle[aria-pressed=true]{border-color:var(--highlight);background:var(--rule2);color:var(--ink)}.switch{width:32px;height:18px;flex:none;border-radius:var(--radius-full);background:var(--highlight);position:relative;transition:background var(--d-micro)}.switch:after{content:"";position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;background:var(--faint);transition:transform var(--d-micro) var(--ease-smooth),background var(--d-micro)}.switch[aria-checked=true]{background:var(--accent)}.switch[aria-checked=true]:after{transform:translate(14px);background:var(--accent-ink)}.checkbox{width:15px;height:15px;flex:none;border-radius:4px;border:1px solid var(--highlight);display:grid;place-items:center;color:var(--accent-ink)}.checkbox[aria-checked=true]{background:var(--accent);border-color:var(--accent)}.checkbox:not([aria-checked=true])>svg{visibility:hidden}.appbar{height:var(--h-appbar);flex:none;display:flex;align-items:center;gap:12px;padding:0 12px;background:var(--stage);border-bottom:1px solid var(--rule2);-webkit-app-region:drag}.appbar button,.appbar .seg,.appbar .filechip,.appbar .nodrag{-webkit-app-region:no-drag}.brand{display:flex;align-items:center;gap:8px;font-size:var(--t-chrome);font-weight:600;letter-spacing:-.01em;padding-right:4px}.brand>svg{color:var(--accent)}.filechip{display:flex;align-items:center;gap:8px;height:var(--h-compact);padding:0 10px;background:var(--card);border:1px solid var(--rule2);border-radius:var(--radius-sm);font-size:var(--t-chrome);max-width:340px}.filechip .name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wincontrols{display:flex;gap:2px;margin-left:4px}.wincontrols button{width:30px;height:26px;display:grid;place-items:center;border-radius:var(--radius-sm);color:var(--faint)}.wincontrols button:hover{background:var(--surface);color:var(--ink)}.wincontrols button.close:hover{background:var(--bad);color:#fff}.wincontrols i{display:block;background:currentColor}.wincontrols .min i{width:10px;height:1px}.wincontrols .max i{width:9px;height:9px;background:none;border:1px solid currentColor;border-radius:2px}.body{flex:1;min-height:0;display:flex}.stage{flex:1;min-width:0;display:flex;flex-direction:column;background:var(--stage);position:relative}.viewertools{min-height:38px;flex:none;display:flex;align-items:center;flex-wrap:wrap;gap:8px 12px;padding:5px 12px;border-bottom:1px solid var(--rule2);background:color-mix(in srgb,var(--stage) 92%,transparent)}.legend{display:flex;align-items:center;gap:10px;font-size:11px;color:var(--faint)}.legend span{display:flex;align-items:center;gap:5px}.legend i{display:block}.legend .anchor{width:7px;height:7px;border-radius:50%;background:var(--anchor)}.legend .handle{width:7px;height:7px;background:var(--handle);transform:rotate(45deg)}.legend .band{width:12px;height:6px;border-radius:2px}.legend .band.sure,.overlay .certainty .sure{--band: #30a46c}.legend .band.soft,.overlay .certainty .soft{--band: #f5a524}.legend .band.unsure,.overlay .certainty .unsure{--band: #e5484d}.legend .band{background:var(--band)}.overlay .certainty path{fill:var(--band);fill-rule:evenodd;fill-opacity:.45;stroke:var(--band);stroke-width:1;vector-effect:non-scaling-stroke}.legend .wire{width:12px;height:2px;background:var(--wire)}.panes{flex:1;min-height:0;display:flex;position:relative;overflow:hidden}.pane{flex:1;min-width:0;position:relative;overflow:hidden;display:grid;place-items:center;background-color:var(--stage);background-image:repeating-conic-gradient(var(--checker-a) 0% 25%,var(--checker-b) 0% 50%);background-size:16px 16px;cursor:grab;touch-action:none}.pane:active{cursor:grabbing}.pane.hidden{display:none}.panes.stacked .pane{position:absolute;inset:0}.panelabel{position:absolute;top:10px;left:12px;z-index:3;pointer-events:none}.chip{position:absolute;top:8px;right:12px;z-index:3;display:inline-flex;align-items:center;gap:6px;height:24px;padding:0 10px;border-radius:var(--radius-full);font-size:var(--t-label);border:1px solid;pointer-events:none}.chip i{width:6px;height:6px;border-radius:50%;background:currentColor;display:block}.chip.draft{color:var(--state-draft);border-color:color-mix(in srgb,var(--state-draft) 45%,transparent);background:color-mix(in srgb,var(--state-draft) 15%,transparent)}.chip.final{color:var(--state-final);border-color:color-mix(in srgb,var(--state-final) 40%,transparent);background:color-mix(in srgb,var(--state-final) 15%,transparent)}.chip.stale{color:var(--state-stale);border-color:color-mix(in srgb,var(--state-stale) 45%,transparent);background:color-mix(in srgb,var(--state-stale) 15%,transparent)}.chip.swapped:after{content:"";position:absolute;left:10px;right:10px;bottom:-3px;height:1.5px;background:var(--accent);border-radius:1px;transform-origin:left;animation:sweep var(--d-normal) var(--ease-out-expo)}@keyframes sweep{0%{transform:scaleX(0)}to{transform:scaleX(1)}}.art{position:absolute;left:0;top:0;transform-origin:0 0;will-change:transform;pointer-events:none}.art img{display:block;image-rendering:pixelated}.art svg{display:block;overflow:visible}.art.swapping{animation:crossfade var(--d-normal) var(--ease-out-expo)}@keyframes crossfade{0%{opacity:.25}to{opacity:1}}.art.centred{position:static;place-self:stretch;min-width:0;min-height:0;padding:44px 32px 32px}.panes.onlight{--stage: #f3f0ea;--checker-a: #ffffff;--checker-b: #ebe7df}.panes.ondark{--stage: #1a1816;--checker-a: #26231f;--checker-b: #211f1c}.overlay{position:absolute;left:0;top:0;overflow:visible;pointer-events:none}.overlay .wireframe path{fill:none;stroke:var(--wire);stroke-width:1px;vector-effect:non-scaling-stroke}.overlay .handles path{fill:none;stroke:var(--handle);vector-effect:non-scaling-stroke}.overlay .handles .lines{stroke-width:.8px}.overlay .handles .knobs{stroke-width:2.4px;stroke-linecap:square}.pane>canvas.anchors{position:absolute;left:0;top:0;pointer-events:none}.wipehandle{position:absolute;top:0;bottom:0;width:2px;background:var(--ink);z-index:4;cursor:ew-resize;opacity:.7}.wipehandle:after{content:"";position:absolute;left:50%;top:50%;width:26px;height:26px;margin:-13px 0 0 -13px;border-radius:50%;border:2px solid var(--ink);background:var(--stage)}.detailpane{position:absolute;inset:0;z-index:5;background:var(--stage);display:flex;flex-direction:column}.detailhead{flex:none;display:flex;align-items:center;gap:10px;padding:8px 12px;border-bottom:1px solid var(--rule2);font-size:var(--t-label);color:var(--dim)}.detailbody{flex:1;min-height:0;position:relative;overflow:hidden;display:grid;place-items:center}.detailfoot{flex:none;padding:8px 12px;border-top:1px solid var(--rule2);font-size:var(--t-label);color:var(--faint)}.pixelgrid{position:absolute;inset:0;background-image:linear-gradient(to right,rgba(250,248,245,.07) 1px,transparent 1px),linear-gradient(to bottom,rgba(250,248,245,.07) 1px,transparent 1px);pointer-events:none}:root[data-theme=light] .pixelgrid{background-image:linear-gradient(to right,rgba(26,24,22,.1) 1px,transparent 1px),linear-gradient(to bottom,rgba(26,24,22,.1) 1px,transparent 1px)}.stagestate{position:absolute;inset:0;z-index:6;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:11px;padding:32px;text-align:center;background:var(--stage)}.stagestate .title{font-size:16px;font-weight:500}.stagestate .body{display:block;font-size:var(--t-chrome);line-height:1.6;color:var(--faint);max-width:46ch}.stagestate .action{font-size:var(--t-chrome);color:var(--accent-text);margin-top:2px}.statusstrip{height:var(--h-status);flex:none;display:flex;align-items:center;gap:10px;padding:0 12px;border-top:1px solid var(--rule2);background:var(--stage);font-size:var(--t-label);color:var(--faint);font-variant-numeric:tabular-nums}.statusstrip .lead{color:var(--dim)}.statusstrip .privacy{margin-left:auto}.statusstrip .updatechip{display:inline-flex;align-items:center;gap:6px;color:var(--gold)}.statusstrip .updatechip i{width:6px;height:6px;border-radius:50%;background:currentColor;display:block}.rail{width:var(--rail-w);flex:none;border-left:1px solid var(--rule2);background:var(--paper);display:flex;flex-direction:column;position:relative}.railscroll{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;padding:var(--rail-pad);display:flex;flex-direction:column;gap:var(--rail-pad)}.railscroll::-webkit-scrollbar{width:10px}.railscroll::-webkit-scrollbar-thumb{background:var(--rule2);border-radius:5px;border:3px solid var(--paper)}.railscroll::-webkit-scrollbar-thumb:hover{background:var(--highlight)}.card{border:1px solid var(--rule2);background:var(--card);border-radius:var(--radius-lg);padding:13px;display:flex;flex-direction:column;gap:10px}.cardhead{display:flex;align-items:baseline;justify-content:space-between;gap:8px}.railfoot{flex:none;border-top:1px solid var(--rule2);background:var(--stage);padding:12px var(--rail-pad);display:flex;flex-direction:column;gap:8px}.railfoot .row{display:flex;gap:8px}.railfoot .note{display:flex;justify-content:space-between;font-size:var(--t-label);color:var(--muted)}.presets{display:flex;flex-wrap:wrap;gap:5px}.preset{display:inline-flex;align-items:center;padding:5px 10px;border-radius:999px;border:1px solid var(--rule2);background:var(--card);font-size:var(--t-chrome);color:var(--dim);transition:border-color var(--d-micro),background var(--d-micro),color var(--d-micro)}.preset:hover{border-color:var(--highlight);color:var(--ink)}.preset[aria-pressed=true]{border-color:var(--accent);background:var(--accent-soft);color:var(--ink);font-weight:500}.preset.saved{padding-right:22px}.preset{position:relative}.preset .forget{position:absolute;top:50%;margin-top:-8px;right:4px;width:16px;height:16px;border-radius:5px;opacity:0;transition:opacity var(--d-micro),background var(--d-micro)}.preset .forget:before,.preset .forget:after{content:"";position:absolute;left:4px;top:7.5px;width:8px;height:1.5px;border-radius:1px;background:var(--muted)}.preset .forget:before{transform:rotate(45deg)}.preset .forget:after{transform:rotate(-45deg)}.preset:hover .forget,.preset .forget:focus-visible{opacity:1}.preset .forget:hover{background:var(--highlight)}.preset .forget:hover:before,.preset .forget:hover:after{background:var(--bad)}.traybar{display:flex;align-items:baseline;justify-content:space-between;gap:8px;font-size:11px}.railmodes{flex:none;display:grid;grid-template-columns:1.75fr 1fr;gap:8px;padding:10px var(--rail-pad) 0}.mode{min-width:0;display:flex;flex-direction:column;gap:8px;padding:10px 11px 11px;border:1px solid var(--rule2);border-radius:var(--radius-lg);background:var(--card)}.modehead{display:flex;align-items:baseline;justify-content:space-between;gap:8px;min-height:16px}.modetitle{font-size:12.5px;font-weight:600;color:var(--ink)}.modestate{font-size:10.5px;color:var(--muted);white-space:nowrap}.seg.big{display:flex;width:100%;padding:3px}.seg.big>button{flex:1;padding:7px 0;font-size:12.5px;text-align:center}.seg.big>button[aria-pressed=true]{background:var(--accent);color:var(--accent-ink);font-weight:600}.bigswitch{display:flex;align-items:center;gap:8px;height:34px;padding:0 4px;border:1px solid var(--rule2);border-radius:999px;background:var(--paper);color:var(--dim);font-size:12.5px;font-weight:600;transition:background var(--d-micro),border-color var(--d-micro),color var(--d-micro)}.bigswitch .knob{flex:none;width:24px;height:24px;border-radius:50%;background:var(--highlight);transition:background var(--d-micro)}.bigswitch .state{flex:1;text-align:center;padding-right:4px}.bigswitch[aria-checked=true]{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}.bigswitch[aria-checked=true]{flex-direction:row-reverse}.bigswitch[aria-checked=true] .knob{background:var(--accent-ink)}.bigswitch[aria-checked=true] .state{padding-right:0;padding-left:4px}.railtabs{flex:none;background:var(--stage);border-bottom:1px solid var(--rule2)}.railseg{display:flex;width:100%}.railseg>button{position:relative;flex:1;display:flex;align-items:baseline;justify-content:center;gap:8px;height:46px;padding:14px 12px 0;color:var(--muted);transition:color var(--d-micro),background var(--d-micro)}.railseg>button:hover:not([aria-selected=true]){color:var(--dim);background:color-mix(in srgb,var(--ink) 4%,transparent)}.railseg>button[aria-selected=true]{color:var(--ink);background:var(--paper)}.railseg>button:after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;background:transparent;transition:background var(--d-micro)}.railseg>button[aria-selected=true]:after{background:var(--accent)}.railseg .tablabel{font-size:14px;font-weight:600;letter-spacing:-.005em}.railseg .tabnote{font-size:11px;font-weight:500;font-variant-numeric:tabular-nums;color:var(--faint)}.railseg .tabnote:empty{display:none}.railseg>button[aria-selected=true] .tabnote{color:var(--accent-text)}.tabcaption{margin:0;padding:7px var(--rail-pad) 9px;background:var(--paper);font-size:11.5px;color:var(--muted)}.presetblock{display:flex;flex-direction:column;gap:8px}.presetblock .traybar .faint{min-width:0}.rail section.group{gap:0;border:1px solid var(--rule2);background:var(--card);border-radius:var(--radius-lg)}.rail section.group .grouphead{align-items:center;padding-right:13px}.groupbtn{flex:1;display:flex;align-items:center;gap:7px;padding:11px 9px 11px 13px;color:var(--muted);text-align:left;border-radius:var(--radius-lg)}.groupbtn:hover{color:var(--dim)}.groupbtn .changed{font-size:10.5px;color:var(--accent-text)}.groupbody{display:flex;flex-direction:column;gap:13px;padding:2px 13px 14px}.control.changed .controlhead .label:before{content:"";display:inline-block;width:5px;height:5px;margin-right:6px;border-radius:50%;background:var(--accent);vertical-align:1px}.emptycard p{margin:0;font-size:var(--t-chrome);line-height:1.55;color:var(--dim)}.structure .srow{display:grid;grid-template-columns:1fr auto;column-gap:8px;row-gap:5px;align-items:baseline}.structure .srow .k{font-size:var(--t-chrome);color:var(--dim)}.structure .srow .v{font-size:var(--t-panel);font-variant-numeric:tabular-nums}.structure .srow .v .of{margin-left:6px;font-size:10.5px;color:var(--muted)}.sbar{grid-column:1 / -1;position:relative;height:4px;margin-bottom:4px;border-radius:2px;background:var(--highlight)}.sbar i{position:absolute;inset:0 auto 0 0;border-radius:2px;background:var(--accent);transition:width var(--d-normal) var(--ease-out-expo)}.sbar b{position:absolute;top:-3px;bottom:-3px;width:2px;margin-left:-1px;border-radius:1px;background:var(--dim)}.readout{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;min-height:54px;background:var(--rule2);border:1px solid var(--rule2);border-radius:var(--radius);overflow:hidden}.readout .cell{min-width:0;display:flex;flex-direction:column;gap:1px;padding:6px 10px;background:var(--paper)}.readout .v{font-size:15px;font-weight:500;line-height:1.25}.readout .k{font-size:10px;color:var(--muted)}.delta{font-size:10.5px;font-variant-numeric:tabular-nums;color:var(--muted)}.delta.better{color:var(--good)}.delta.worse{color:var(--gold)}.readout.busy,.readout.idle{display:flex;align-items:center;gap:8px;padding:0 12px;background:var(--paper);font-size:var(--t-chrome)}.readout .stage{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--state-stale)}.pulse{flex:none;width:7px;height:7px;border-radius:50%;background:var(--state-stale);animation:pulse 1s ease-in-out infinite}@keyframes pulse{50%{opacity:.3}}.headline{display:flex;align-items:flex-end;gap:12px}.headline .figure{font-family:var(--font-display);font-size:52px;line-height:.85;letter-spacing:-.03em}.headline .of{display:flex;flex-direction:column;gap:2px;padding-bottom:4px}.meter{position:relative;height:6px;border-radius:3px;background:linear-gradient(90deg,var(--good),var(--gold) 55%,var(--bad))}.meter .threshold{position:absolute;top:-3px;bottom:-3px;width:1px;background:var(--dim)}.meter .needle{position:absolute;top:-4px;width:2px;height:14px;background:var(--ink);border-radius:1px;transition:left var(--d-normal) var(--ease-out-expo)}.meterscale{display:flex;justify-content:space-between;font-size:10.5px;color:var(--muted)}.stats{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:var(--rule2);border:1px solid var(--rule2);border-radius:var(--radius);overflow:hidden;font-variant-numeric:tabular-nums}.stats>div{background:var(--paper);padding:8px 10px;display:flex;flex-direction:column;gap:2px}.stats .k{font-size:10.5px;color:var(--muted)}.stats .v{font-size:var(--t-panel)}.benchmark{display:flex;gap:8px;padding:8px 10px;border:1px dashed var(--highlight);border-radius:var(--radius);background:color-mix(in srgb,var(--ink) 2%,transparent)}.benchmark .label{flex:none;padding-top:1px}.benchmark p{margin:0;font-size:var(--t-label);line-height:1.45;color:var(--faint)}.loss{display:flex;gap:9px;padding-bottom:9px;border-bottom:1px solid var(--rule2)}.loss:last-of-type{border-bottom:none;padding-bottom:0}.loss .glyph{flex:none;padding-top:2px;color:var(--gold)}.loss .text{font-size:var(--t-chrome);line-height:1.45;color:var(--dim)}.loss .meta{font-size:var(--t-label);color:var(--muted);display:flex;gap:6px;flex-wrap:wrap}.loss .why{font-size:var(--t-label);line-height:1.5;color:var(--faint);margin-top:4px;padding-left:9px;border-left:1px solid var(--rule2)}.loss .expand{color:var(--muted)}.loss .expand:hover{color:var(--dim)}.nothinglost{display:flex;gap:9px;align-items:center;font-size:var(--t-chrome);color:var(--faint)}.nothinglost .glyph{color:var(--good);flex:none;display:flex}.ink{display:flex;align-items:center;gap:9px;padding:2px 0;border-radius:var(--radius-sm);width:100%;text-align:left}.ink:hover{background:var(--surface)}.swatch{width:22px;height:22px;flex:none;border-radius:5px;border:1px solid color-mix(in srgb,var(--ink) 12%,transparent);background-image:repeating-conic-gradient(var(--checker-a) 0% 25%,var(--checker-b) 0% 50%);background-size:8px 8px;position:relative;overflow:hidden}.swatch i{position:absolute;inset:0;display:block}.swatch.snapped{border:2px solid var(--accent)}.ink .hex{font-size:var(--t-chrome);font-variant-numeric:tabular-nums;color:var(--dim);width:72px}.ink .share{font-size:var(--t-label);color:var(--muted);font-variant-numeric:tabular-nums;width:44px}.ink .snap{margin-left:auto;font-size:var(--t-label);color:var(--muted)}.ink .snap.on{color:var(--accent-text)}.ink{gap:6px;touch-action:none}.ink.grouped .hex{color:var(--accent-text)}.inkpick{width:16px;height:16px;flex:none;border-radius:4px;border:1px solid var(--highlight);display:grid;place-items:center;color:var(--accent-ink)}.inkpick[aria-checked=true]{background:var(--accent);border-color:var(--accent)}.inkmain{display:flex;align-items:center;gap:9px;flex:1;min-width:0;text-align:left}.inkmain[aria-disabled=true]{cursor:grab}.swatch.mini{width:16px;height:16px;border-radius:4px}.swatch.mini.ramp{width:26px}.inklist{display:flex;flex-direction:column;gap:1px;border-radius:var(--radius-sm)}.inklist,.cgroup{transition:box-shadow var(--d-fast),background var(--d-fast)}.mergebar{display:flex;align-items:center;gap:10px;font-size:var(--t-label)}.cgroups{display:flex;flex-direction:column;gap:7px}.cgroupshead{display:flex;align-items:baseline;justify-content:space-between;gap:8px}.cgroup{border:1px solid var(--rule2);border-radius:var(--radius);background:var(--paper);padding:8px;display:flex;flex-direction:column;gap:7px}.cgroup.suggested{border-style:dashed;background:transparent}.cchips{display:flex;flex-wrap:wrap;gap:4px}.cchip{display:inline-flex;align-items:center;border:1px solid var(--highlight);border-radius:999px;background:var(--card);touch-action:none;font-size:var(--t-label);color:var(--dim)}.cchip.target{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent) inset}.cchip.unmatched{border-color:var(--gold);border-style:dashed}.cchipmain{display:inline-flex;align-items:center;gap:5px;padding:2px 4px 2px 3px;border-radius:999px}.cchipmain .swatch.mini{border-radius:999px}.cchipx{display:grid;place-items:center;width:18px;height:18px;margin-right:2px;border-radius:999px;color:var(--muted)}.cchipx:hover{color:var(--ink);background:var(--surface)}.cresult{display:flex;align-items:center;gap:6px;font-size:var(--t-label)}.cresult>span{white-space:nowrap}.cresult .arrow{color:var(--muted)}.cresultchip{display:inline-flex;align-items:center;gap:5px;color:var(--dim)}.cactions{display:flex;align-items:center;gap:6px}.creport{font-size:11px;line-height:1.4;display:inline-flex;align-items:center;gap:5px;min-width:0}.creport.warn{color:var(--gold)}.creport.warn svg{flex:none}.simplifyrow{display:flex;align-items:center;gap:5px;font-size:var(--t-label)}.numberfield.simplify{min-width:0;width:40px;text-align:center}.dragghost{position:fixed;z-index:60;pointer-events:none;filter:drop-shadow(0 2px 6px rgba(0,0,0,.45))}body.dragging-ink,body.dragging-ink *{cursor:grabbing!important}body.dragging-ink [data-drop=list]{box-shadow:0 0 0 1px var(--rule2)}.dropping{box-shadow:0 0 0 2px var(--accent)!important;background:var(--accent-subtle)!important}.control{display:flex;flex-direction:column;gap:5px}.controlhead{display:flex;align-items:baseline;gap:8px}.controlhead .label{flex:1;font-size:var(--t-chrome);color:var(--dim)}.controlhead .unit{font-size:var(--t-label);color:var(--muted)}.numberfield{height:24px;min-width:58px;padding:0 6px;border:1px solid var(--highlight);border-radius:var(--radius-sm);background:var(--paper);color:var(--ink);font:400 var(--t-chrome) var(--font-body);font-variant-numeric:tabular-nums;text-align:center}.numberfield:focus-visible{border-color:var(--accent)}.slider{appearance:none;-webkit-appearance:none;width:100%;height:14px;background:none;margin:2px 0 0;cursor:pointer}.slider::-webkit-slider-runnable-track{height:3px;border-radius:2px;background:var(--highlight)}.slider::-webkit-slider-thumb{-webkit-appearance:none;width:11px;height:11px;margin-top:-4px;border-radius:50%;background:var(--ink);border:none}.slider::-moz-range-track{height:3px;border-radius:2px;background:var(--highlight)}.slider::-moz-range-thumb{width:11px;height:11px;border:none;border-radius:50%;background:var(--ink)}.stops{display:flex;justify-content:space-between;gap:8px;font-size:10px;color:var(--muted);white-space:nowrap}.group{display:flex;flex-direction:column;gap:9px}.grouphead{display:flex;align-items:baseline;justify-content:space-between}.reset{font-size:var(--t-label);color:var(--accent-text)}.reset:disabled{color:var(--muted);cursor:default}.stagelist{display:flex;flex-direction:column;gap:5px;font-variant-numeric:tabular-nums}.stagerow{display:flex;align-items:baseline;gap:8px;font-size:var(--t-label);color:var(--muted)}.stagerow.done{color:var(--dim)}.stagerow .mark{width:10px;text-align:center;color:var(--muted)}.stagerow.done .mark{color:var(--good)}.stagerow .name{flex:1}.sweep{height:2px;background:var(--rule2);border-radius:2px;overflow:hidden}.sweep i{display:block;width:30%;height:100%;background:var(--accent);animation:sweepacross 1.6s var(--ease-out-expo) infinite}@keyframes sweepacross{0%{transform:translate(-100%)}to{transform:translate(340%)}}@media(prefers-reduced-motion:reduce){.sweep i{animation:none;width:100%;opacity:.4}.chip.swapped:after,.art.swapping,.callout,.pulse{animation:none}.dragging .drop{transition:none}}.firstrun{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:34px;background:var(--stage);padding:24px}.drop{width:min(620px,80%);padding:44px 24px;min-height:220px;justify-content:center;border:1.5px dashed var(--highlight);border-radius:var(--radius-xl);display:flex;flex-direction:column;align-items:center;gap:16px;background:color-mix(in srgb,var(--ink) 1.5%,transparent);text-align:center;transition:border-color var(--d-fast),background var(--d-fast)}.drop .glyph{color:var(--muted)}[hidden]{display:none!important}.drop.solid{background:var(--paper);border-style:solid;border-color:var(--rule2)}.panehint{max-width:34ch;text-align:center;font-size:12.5px;line-height:1.55}.drop .headline{font-family:var(--font-display);font-size:26px;letter-spacing:-.02em;display:block}.drop .release,.dragging .drop .resting{display:none}.dragging .drop .release{display:block}.dragging .drop{width:min(640px,90%);min-height:320px;transition:width var(--d-fast) var(--ease-out-expo),min-height var(--d-fast) var(--ease-out-expo),border-color var(--d-fast),background var(--d-fast)}.samples{display:flex;flex-direction:column;align-items:center;gap:12px}.samplerow{display:flex;gap:12px}.sample{width:112px;display:flex;flex-direction:column;gap:7px;align-items:center}.sample .thumb{width:112px;height:88px;border:1px solid var(--rule2);border-radius:10px;background-color:var(--card);background-image:repeating-conic-gradient(var(--checker-a) 0% 25%,var(--checker-b) 0% 50%);background-size:12px 12px;display:grid;place-items:center;overflow:hidden;transition:border-color var(--d-micro),transform var(--d-micro)}.sample:hover .thumb{border-color:var(--accent);transform:translateY(-2px)}.sample img{max-width:76px;max-height:68px}.sample .label{font-size:var(--t-label);color:var(--faint)}.dragging .drop{border-color:var(--accent);background:var(--accent-soft)}.dragging .drop .glyph{color:var(--accent)}.dragging:after{content:"";position:fixed;inset:0;border:2px solid var(--accent);pointer-events:none;z-index:60}.dragging .stage>*:not(.stagestate){opacity:.6}.callout{position:absolute;left:20px;bottom:20px;z-index:8;max-width:320px;display:flex;flex-direction:column;gap:5px;padding:10px 13px;border-radius:var(--radius-lg);border:1px solid var(--rule2);background:color-mix(in srgb,var(--card) 92%,transparent);backdrop-filter:blur(8px);font-size:11.5px;line-height:1.5;color:var(--dim);animation:rise var(--d-fast) var(--ease-out-expo)}.callout .head{display:flex;align-items:baseline;justify-content:space-between;gap:12px}#overlays:empty{display:none}.scrim{position:fixed;inset:0;z-index:40;background:color-mix(in srgb,var(--void) 62%,transparent);display:grid;place-items:center;padding:24px}.modal{width:min(460px,100%);max-height:86vh;overflow-y:auto;background:var(--card);border:1px solid var(--highlight);border-radius:var(--radius-xl);padding:22px;display:flex;flex-direction:column;gap:13px;box-shadow:var(--shadow-xl)}.modal h2{margin:0;font-family:var(--font-display);font-size:22px;font-weight:500;letter-spacing:-.02em}.modal p{margin:0;font-size:var(--t-panel);line-height:1.7;color:var(--dim)}.modal .actions{display:flex;gap:8px;justify-content:flex-end}.modal.composer{width:min(1040px,100%);max-height:92vh;padding:0;gap:0;overflow:hidden}.composerhead{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:18px 22px 15px;border-bottom:1px solid var(--rule2)}.composerhead p{margin-top:3px;font-size:var(--t-chrome)}.composerbody{display:grid;grid-template-columns:minmax(0,1fr) 312px;min-height:0;overflow-y:auto}.composerpreview{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:22px;min-width:0;background:var(--stage)}.cardstage{--ar: 1.7778;position:relative;width:min(100%,calc(58vh * var(--ar)));aspect-ratio:var(--ar);border-radius:var(--radius);overflow:hidden;background:var(--paper);box-shadow:var(--shadow-lg)}.cardstage img{display:block;width:100%;height:100%;object-fit:contain}.cardbusy{position:absolute;inset:0;display:grid;place-items:center;opacity:0;pointer-events:none;background:color-mix(in srgb,var(--paper) 45%,transparent);transition:opacity var(--d-micro)}.cardstage.busy .cardbusy{opacity:1;transition-delay:.26s}.cardspin{width:20px;height:20px;border-radius:50%;border:2px solid var(--highlight);border-top-color:var(--accent);animation:cardspin .8s linear infinite}@keyframes cardspin{to{transform:rotate(360deg)}}.composerside{display:flex;flex-direction:column;gap:18px;padding:20px 22px;border-left:1px solid var(--rule2)}.optgroup{display:flex;flex-direction:column;gap:8px}.cardseg{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:2px;padding:2px;border:1px solid var(--rule2);border-radius:var(--radius);background:var(--paper)}.cardseg button{display:flex;flex-direction:column;align-items:center;gap:1px;padding:6px 8px;border-radius:calc(var(--radius) - 2px);font-size:var(--t-chrome);color:var(--faint)}.cardseg button small{font-size:10px;color:var(--muted);font-variant-numeric:tabular-nums}.cardseg button:hover:not([aria-checked=true]){color:var(--ink)}.cardseg button[aria-checked=true]{color:var(--ink);background:var(--accent-soft);box-shadow:inset 0 0 0 1px var(--accent)}.optlist{display:flex;flex-direction:column;border:1px solid var(--rule2);border-radius:var(--radius);background:var(--paper)}.optlist>*+*{border-top:1px solid var(--rule2)}.optrow{display:flex;align-items:center;gap:12px;width:100%;padding:9px 11px;text-align:left}.optrow:hover{background:var(--rule2)}.optext{display:flex;flex:1;flex-direction:column;gap:1px;min-width:0}.optlabel{font-size:12.5px;color:var(--ink)}.optnote{font-size:11px;line-height:1.4;color:var(--muted)}.optslider{display:flex;flex-direction:column;gap:4px;padding:9px 11px 8px;transition:opacity var(--d-micro)}.optslider.off{opacity:.4}.optslider.off .slider{cursor:default}.optsliderhead{display:flex;justify-content:space-between;font-size:12px;color:var(--dim)}.composeractions{display:flex;flex-direction:column;gap:8px;margin-top:auto}.composeractions .btn{justify-content:center;gap:7px}@media(max-width:860px){.composerbody{grid-template-columns:minmax(0,1fr)}.composerside{border-left:0;border-top:1px solid var(--rule2)}}.popover{position:fixed;z-index:45;background:var(--card);border:1px solid var(--highlight);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);overflow:hidden}.menu{padding:6px;min-width:260px}.menu .item{display:flex;align-items:center;gap:9px;padding:7px 9px;border-radius:var(--radius);width:100%;text-align:left;font-size:var(--t-chrome);color:var(--dim)}.menu .item:hover{background:var(--surface);color:var(--ink)}.menu .item .when{margin-left:auto;font-size:var(--t-label);color:var(--muted)}.menu .rule{height:1px;background:var(--rule2);margin:5px 0}.sheet{position:absolute;inset:0;z-index:20;background:color-mix(in srgb,var(--void) 55%,transparent);display:flex;align-items:flex-end}.sheetbody{width:100%;max-height:100%;overflow-y:auto;background:var(--card);border-top:1px solid var(--highlight);border-radius:var(--radius-xl) var(--radius-xl) 0 0;padding:14px;display:flex;flex-direction:column;gap:11px;box-shadow:0 -20px 50px color-mix(in srgb,var(--void) 60%,transparent);animation:rise var(--d-fast) var(--ease-out-expo)}@keyframes rise{0%{transform:translateY(12px);opacity:0}}.format{display:flex;align-items:center;gap:9px;padding:7px 9px;border:1px solid var(--rule2);border-radius:var(--radius);background:var(--paper);width:100%;text-align:left;font-size:var(--t-chrome);color:var(--dim)}.format:hover{border-color:var(--highlight)}.format .size{margin-left:auto;font-size:var(--t-label);color:var(--muted);font-variant-numeric:tabular-nums}.tooltip{position:fixed;z-index:70;max-width:300px;background:var(--highlight);border:1px solid color-mix(in srgb,var(--ink) 10%,transparent);border-radius:var(--radius);padding:10px 12px;font-size:var(--t-chrome);line-height:1.6;color:var(--dim);box-shadow:var(--shadow);pointer-events:none}#toasts{position:fixed;left:50%;bottom:40px;transform:translate(-50%);z-index:80;display:flex;flex-direction:column;gap:8px;align-items:center}.toast{width:min(460px,90vw);background:var(--highlight);border:1px solid color-mix(in srgb,var(--ink) 10%,transparent);border-radius:10px;padding:11px 13px;display:flex;align-items:center;gap:11px;box-shadow:var(--shadow-lg);animation:risein var(--d-fast) var(--ease-out-expo)}@keyframes risein{0%{transform:translateY(8px);opacity:0}}.toast .text{flex:1;font-size:var(--t-chrome);color:var(--dim)}.toast .glyph{display:flex}.toast .glyph.good{color:var(--good)}.toast .glyph.bad{color:var(--bad)}.screen{position:absolute;inset:0;z-index:30;background:var(--paper);display:flex;flex-direction:column}.screenbar{height:var(--h-appbar);flex:none;display:flex;align-items:center;gap:12px;padding:0 12px;background:var(--stage);border-bottom:1px solid var(--rule2);-webkit-app-region:drag}.screenbar button{-webkit-app-region:no-drag}.screenbody{flex:1;min-height:0;overflow-y:auto;background:var(--stage)}.settingsgrid{width:min(1128px,100%);margin:0 auto;padding:24px;display:grid;grid-template-columns:repeat(auto-fit,minmax(420px,1fr));gap:16px;align-content:start}.settinggroup{border:1px solid var(--rule2);background:var(--card);border-radius:var(--radius-lg);overflow:hidden;align-self:start}.settinggroup>.head{padding:11px 14px;border-bottom:1px solid var(--rule2)}.settingrow{display:flex;align-items:center;gap:16px;padding:11px 14px;border-bottom:1px solid color-mix(in srgb,var(--ink) 5%,transparent)}.settingrow:last-child{border-bottom:none}.settingrow .about{flex:1;display:flex;flex-direction:column;gap:3px;min-width:0}.settingrow .label{font-size:var(--t-panel);color:var(--dim)}.settingrow .help{font-size:var(--t-label);line-height:1.5;color:var(--muted)}.settingrow .control{flex:none}.settingrow select,.settingrow input[type=text],.settingrow input[type=number]{height:var(--h-compact);padding:0 8px;border:1px solid var(--rule2);border-radius:7px;background:var(--paper);color:var(--ink);font:400 var(--t-chrome) var(--font-body);font-variant-numeric:tabular-nums;max-width:220px}.privacycard{border:1px solid var(--rule2);background:var(--card);border-radius:var(--radius-lg);padding:14px;display:flex;flex-direction:column;gap:8px;align-self:start}.privacycard .line{font-family:var(--font-display);font-size:19px;letter-spacing:-.02em}.about{display:flex;min-height:100%}.aboutleft{width:520px;flex:none;background:var(--stage);border-right:1px solid var(--rule2);display:flex;flex-direction:column;justify-content:center;gap:22px;padding:56px}.aboutleft .mark{color:var(--accent)}.aboutright{flex:1;padding:56px;display:flex;flex-direction:column;gap:20px;justify-content:center;background:var(--paper)}.credit{border:1px solid var(--highlight);border-radius:var(--radius-lg);padding:20px;display:flex;flex-direction:column;gap:10px;background:var(--gold-soft)}.notices{border:1px solid var(--rule2);border-radius:var(--radius-lg);overflow:hidden}.notices .head{padding:11px 14px;border-bottom:1px solid var(--rule2);font-size:var(--t-chrome);color:var(--dim);display:flex;justify-content:space-between}.notices pre{margin:0;height:220px;overflow:auto;padding:12px 14px;font:11.5px / 1.75 var(--font-mono);color:var(--muted);background:var(--stage);white-space:pre-wrap;user-select:text}.minifyrail{width:400px;flex:none;border-left:1px solid var(--rule2);background:var(--paper);display:flex;flex-direction:column}.minifyresult{display:flex;flex-direction:column;gap:5px}.minifyresult .figure{font-family:var(--font-display);font-size:66px;line-height:.85;letter-spacing:-.04em;color:var(--accent-text)}.sentence{font-size:var(--t-panel);line-height:2;color:var(--dim)}.sentence .inlinefield{display:inline-flex;align-items:center;height:24px;padding:0 4px;border:1px solid var(--rule2);border-radius:var(--radius-sm);background:var(--paper);color:var(--ink);font:400 var(--t-chrome) var(--font-body);font-variant-numeric:tabular-nums;width:58px;text-align:center}.sentence .inlinefield.accent{border-color:var(--accent);background:var(--accent-soft)}.batchbar{height:44px;flex:none;display:flex;align-items:center;gap:8px;padding:0 14px;border-bottom:1px solid var(--rule2);background:var(--stage)}.batchhead,.batchrow{display:grid;grid-template-columns:24px minmax(0,1.4fr) 120px 104px 84px 104px 96px minmax(0,1.2fr);align-items:center;gap:12px;padding:0 14px}.batchhead{height:34px;flex:none;border-bottom:1px solid var(--rule2)}.batchrow{height:var(--h-row);border-bottom:1px solid color-mix(in srgb,var(--ink) 4%,transparent);font-size:var(--t-chrome);font-variant-numeric:tabular-nums}.batchrow.failed{background:color-mix(in srgb,var(--bad) 8%,transparent)}.batchrow.running{background:var(--accent-subtle)}.batchrow .trunc,.batchhead .trunc{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.batchrow .right,.batchhead .right{text-align:right}.batchrow .state{display:flex;align-items:center;gap:6px}.batchrow .state i{width:6px;height:6px;border-radius:50%;background:currentColor;display:block;flex:none}.state.queued,.state.skipped{color:var(--muted)}.state.running{color:var(--accent-text)}.state.done{color:var(--good)}.state.failed{color:var(--bad)}.batchviewport{flex:1;min-height:0;overflow-y:auto;position:relative}.batchfoot{height:52px;flex:none;display:flex;align-items:center;gap:18px;padding:0 14px;border-top:1px solid var(--rule2);background:var(--stage);font-size:var(--t-chrome);font-variant-numeric:tabular-nums}.progress{height:3px;border-radius:2px;background:var(--highlight);overflow:hidden}.progress i{display:block;height:100%;background:var(--accent);transition:width var(--d-fast) var(--ease-smooth)}@media(max-width:1400px){:root{--rail-w: 330px}}@media(max-width:1180px){:root{--rail-w: 310px}.legend{display:none}}.chooser{position:absolute;left:50%;bottom:16px;transform:translate(-50%);z-index:8;width:min(560px,calc(100% - 32px));max-height:calc(100% - 70px);overflow-y:auto;display:flex;flex-direction:column;gap:9px;padding:10px 12px 11px;background:var(--card);border:1px solid var(--highlight);border-radius:var(--radius-xl);box-shadow:var(--shadow-lg);animation:rise var(--d-fast) var(--ease-out-expo)}.choosehead{display:flex;align-items:center;justify-content:space-between;gap:10px;min-width:0}.choosehead .eyebrow{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.chooseintro{font-size:var(--t-label);line-height:1.5;color:var(--dim);padding:7px 10px;border-radius:var(--radius);background:var(--accent-subtle);border:1px solid var(--accent-soft)}.choices{display:flex;flex-direction:column;gap:6px}.choice{display:grid;grid-template-columns:92px 1fr auto;align-items:center;gap:12px;padding:8px 8px 8px 12px;border:1px solid var(--rule2);border-radius:var(--radius-lg);background:var(--paper);min-width:0}.choice .btn{min-width:104px}.choicename{display:flex;align-items:center;gap:7px;font-family:var(--font-display);font-size:17px;letter-spacing:-.02em;color:var(--ink)}.choicename svg{color:var(--accent-text)}.choicebody{font-size:var(--t-chrome);line-height:1.5;color:var(--faint)}.choosenews{display:flex;flex-direction:column;gap:6px;padding-top:9px;border-top:1px solid var(--rule2)}.remember{display:flex;align-items:center;gap:7px;font-size:var(--t-label);color:var(--faint);cursor:pointer;align-self:flex-start}.remember input{accent-color:var(--accent);margin:0}.autochose{display:flex;flex-direction:column;gap:7px;font-size:var(--t-chrome)}.autolead{color:var(--dim);line-height:1.5}.autorow{display:flex;align-items:center;gap:10px;justify-content:space-between}.autorow.moved{padding-top:7px;border-top:1px dashed var(--rule2)}.autotext{display:flex;flex-direction:column;gap:2px;min-width:0}.autotitle{color:var(--ink)}.autotext .muted{font-size:var(--t-label)}.autobtns{display:flex;align-items:center;gap:10px;flex:none}.autorow .btn{flex:none}.autotaken{font-size:var(--t-label);color:var(--state-final);flex:none}.card.autocard{border-color:var(--accent-soft);background:color-mix(in srgb,var(--accent) 4%,var(--card))}.guideline{display:flex;align-items:baseline;justify-content:space-between;gap:10px;font-size:var(--t-label)}.rail.wizarding{width:max(var(--rail-w),400px)}.sheet.wizsheet{align-items:stretch;background:var(--paper)}.sheetbody.wizbody{height:100%;border-radius:0;border-top:none;box-shadow:none;padding:0;gap:0;overflow:hidden;background:var(--paper)}.wizhead{flex:none;display:flex;flex-direction:column;gap:9px;padding:14px 16px 12px;border-bottom:1px solid var(--rule2)}.wiztitle{font-size:24px;font-weight:500;line-height:1.1;color:var(--ink)}.wizdots{display:flex;gap:6px}.wizdots button{flex:1;height:4px;border-radius:2px;background:var(--highlight);transition:background var(--d-micro)}.wizdots button.done{background:color-mix(in srgb,var(--accent) 45%,var(--highlight))}.wizdots button[aria-selected=true]{background:var(--accent)}.wizdots button:hover{background:var(--accent-hover)}.wizcompare{display:flex;align-items:center;gap:8px;font-size:var(--t-label)}.wizcompare .seg>button{padding:3px 9px}.wizscroll{flex:1;min-height:0;overflow-y:auto;padding:14px 16px 18px;display:flex;flex-direction:column;gap:14px}.wizlead{font-size:var(--t-panel);line-height:1.55;color:var(--dim)}.wizguide{display:flex;flex-direction:column;gap:8px;padding-top:12px;border-top:1px solid var(--rule2)}.wizexplain{display:grid;grid-template-columns:auto 1fr;gap:5px 12px;margin:0;font-size:var(--t-chrome);line-height:1.5}.wizexplain dt{font-size:var(--t-eyebrow);letter-spacing:.12em;text-transform:uppercase;color:var(--muted);padding-top:3px;white-space:nowrap}.wizexplain dd{margin:0;color:var(--dim)}.wizlearn{font-size:var(--t-label);color:var(--accent-text);align-self:flex-start;text-decoration:none}.wizlearn:hover{text-decoration:underline}.wizcontrols{display:flex;flex-direction:column;gap:12px;padding:12px;border:1px solid var(--rule2);border-radius:var(--radius-lg);background:var(--card)}.wizlive{display:flex;flex-direction:column;gap:12px}.wizrow{display:flex;align-items:center;justify-content:space-between;gap:10px;font-size:var(--t-chrome)}.wizsmall{font-size:var(--t-label);line-height:1.5}.wizwhy{font-size:var(--t-chrome);line-height:1.5;color:var(--dim)}.wizchoices{display:grid;grid-template-columns:1fr 1fr;gap:8px}.wizchoice{display:flex;flex-direction:column;align-items:flex-start;gap:4px;padding:10px 11px;text-align:left;border:1px solid var(--rule2);border-radius:var(--radius);background:var(--paper);font-size:var(--t-label);line-height:1.45}.wizchoice .name{font-size:13px;font-weight:600;color:var(--ink)}.wizchoice:hover{border-color:var(--highlight)}.wizchoice[aria-pressed=true]{border-color:var(--accent);background:var(--accent-subtle)}.wiznote{display:flex;flex-direction:column;align-items:flex-start;gap:8px;padding:10px 11px;border-radius:var(--radius);background:var(--accent-subtle);font-size:var(--t-label);line-height:1.5;color:var(--dim)}.wiznav{flex:none;display:flex;align-items:center;gap:12px;padding:12px 16px;border-top:1px solid var(--rule2);background:var(--paper)}.kinds{display:grid;grid-template-columns:1fr 1fr;gap:9px}.kind{display:flex;flex-direction:column;align-items:stretch;gap:4px;padding:7px 7px 9px;text-align:left;border:1px solid var(--rule2);border-radius:var(--radius-lg);background:var(--card);min-width:0;transition:border-color var(--d-micro),background var(--d-micro)}.kind:hover{border-color:var(--highlight)}.kind[aria-checked=true]{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 7%,var(--card));box-shadow:0 0 0 1px var(--accent)}.kthumb{position:relative;height:104px;border-radius:var(--radius);background-color:var(--stage);background-image:repeating-conic-gradient(var(--checker-a) 0% 25%,var(--checker-b) 0% 50%);background-size:10px 10px;display:grid;place-items:center;overflow:hidden;margin-bottom:3px}.kthumb img{max-width:92%;max-height:92%;object-fit:contain;image-rendering:auto}.kspin{position:absolute;inset:auto 0 0;height:2px;overflow:hidden;display:none}.kind.busy .kspin{display:block}.kspin:after{content:"";position:absolute;top:0;bottom:0;left:0;width:30%;background:var(--accent);animation:sweepacross 1.6s var(--ease-out-expo) infinite}@media(prefers-reduced-motion:reduce){.kspin:after{animation:none;width:100%;opacity:.5}}.kname{display:flex;align-items:baseline;justify-content:space-between;gap:6px;font-size:12.5px;font-weight:600;color:var(--ink);padding:0 2px}.ksugg{font-size:9.5px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--accent-text)}.kwhy,.knote,.kstat{font-size:11px;line-height:1.4;padding:0 2px}.kwhy{color:var(--faint)}.knote{color:var(--muted);font-style:italic}.kstat{color:var(--muted);margin-top:2px}.wizreadout table{width:100%;border-collapse:collapse;font-size:var(--t-chrome)}.wizreadout th,.wizreadout td{padding:4px 0;text-align:right;font-weight:400}.wizreadout thead th{font-size:var(--t-eyebrow);letter-spacing:.12em;text-transform:uppercase;color:var(--muted)}.wizreadout tbody th{text-align:left;color:var(--faint)}.wizreadout td{color:var(--ink);padding-left:10px}.wizreadout td.delta{width:70px}.wizreadout td.delta.same{color:var(--muted)}.wizchanges .wizchange{display:flex;justify-content:space-between;gap:10px;font-size:var(--t-chrome);color:var(--faint)}.wizchanges .wizchange .num{color:var(--ink)}.pane.source.comparing .panelabel{color:var(--accent-text)}.intro{width:min(620px,80%);display:flex;flex-direction:column;gap:12px;padding:16px 18px;border:1px solid var(--accent-soft);border-radius:var(--radius-xl);background:color-mix(in srgb,var(--accent) 5%,var(--paper))}.intro ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:9px}.intro li{display:flex;gap:11px;align-items:baseline;font-size:var(--t-chrome);line-height:1.5}.intro li>div{display:flex;flex-direction:column}.introstep{width:20px;height:20px;flex:none;border-radius:50%;display:grid;place-items:center;font-size:11px;font-weight:600;background:var(--accent);color:var(--accent-ink)}.introtitle{color:var(--ink);font-weight:500}.introfoot{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:var(--t-label)}.boot{position:fixed;inset:0;z-index:50;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;background:var(--paper);color:var(--ink)}.boot .bootname{font-family:var(--font-display);font-size:28px}.boot .bootline{font-size:12.5px;color:var(--faint)}.boot .bootline:after{content:"";display:block;width:160px;height:2px;margin-top:12px;background:linear-gradient(90deg,transparent,var(--accent),transparent);background-size:200% 100%;animation:bootsweep 1.2s linear infinite}@keyframes bootsweep{0%{background-position:100% 0}to{background-position:-100% 0}}@media(prefers-reduced-motion:reduce){.boot .bootline:after{animation:none}}.webcontrols{display:flex;gap:2px;margin-left:4px}.webcontrols .btn{gap:6px}.phonenote{position:fixed;inset:0;z-index:60;display:grid;place-items:center;padding:16px;background:color-mix(in srgb,var(--void) 82%,transparent)}.phonecard{max-width:420px;display:flex;flex-direction:column;gap:12px;padding:22px;border-radius:var(--radius-lg, 12px);background:var(--card);box-shadow:var(--shadow-lg)}.phonecard p{margin:0;font-size:13.5px;line-height:1.65;color:var(--dim)}.sc-loading{padding:40px;text-align:center}.sc-page{width:min(1320px,100%);margin:0 auto;padding:24px;display:flex;flex-direction:column;gap:18px}.sc-head h1{margin:0 0 6px;font-size:28px;font-weight:600}.sc-head p,.sc-results>p{margin:0;max-width:96ch;font-size:13px;line-height:1.6}.sc-main{display:grid;grid-template-columns:200px 1fr;gap:16px;min-height:0}.sc-list{display:flex;flex-direction:column;gap:6px}.sc-case{display:grid;grid-template-columns:44px 1fr;grid-template-rows:auto auto;column-gap:10px;align-items:center;text-align:left;padding:6px 8px;border:1px solid var(--rule2);border-radius:var(--radius-sm);background:var(--card);color:var(--ink);cursor:pointer}.sc-case[aria-pressed=true]{border-color:var(--accent);background:var(--accent-subtle)}.sc-thumb{grid-row:1 / 3;width:44px;height:44px;border-radius:6px;background:#fff;display:grid;place-items:center;overflow:hidden}.sc-thumb img{width:100%;height:100%;object-fit:contain}.sc-name{font-size:12.5px;font-weight:600}.sc-what{font-size:11px;color:var(--faint)}.sc-stagecol{display:flex;flex-direction:column;gap:10px;min-width:0}.sc-tools{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.sc-tools .eyebrow{margin-left:6px}.sc-legend{margin-left:auto;display:inline-flex;align-items:center;gap:6px;font-size:11.5px}.sc-dot{display:inline-block;width:8px;height:8px;border-radius:50%}.sc-dot.a{background:var(--anchor)}.sc-dot.hd{background:var(--handle);margin-left:6px}.sc-viewer{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}.sc-pane{position:relative;aspect-ratio:1;overflow:hidden;border:1px solid var(--rule2);border-radius:var(--radius-sm);background-color:var(--stage);background-image:repeating-conic-gradient(var(--checker-a) 0% 25%,var(--checker-b) 0% 50%);background-size:16px 16px;cursor:grab;touch-action:none;user-select:none}.sc-pane:active{cursor:grabbing}.sc-cam{position:absolute;left:0;top:0;width:100%;height:100%;transform-origin:0 0}.sc-cam>img,.sc-layer,.sc-layer>svg{position:absolute;inset:0;width:100%;height:100%;display:block}.sc-cam>img{object-fit:contain}.sc-tag{position:absolute;top:8px;left:8px;padding:4px 7px;border-radius:6px;font-size:11px;font-weight:600;background:color-mix(in srgb,var(--paper) 85%,transparent);color:var(--ink);pointer-events:none}.sc-wire path,.sc-wire circle,.sc-wire ellipse,.sc-wire rect,.sc-wire polygon{fill:none!important;stroke:var(--wire);stroke-width:1px;vector-effect:non-scaling-stroke;stroke-opacity:.9}.sc-ov{pointer-events:none}.sc-ov .h{stroke:var(--handle);stroke-width:1px;vector-effect:non-scaling-stroke;fill:none;stroke-opacity:.85}.sc-ov .hd{stroke:var(--handle);stroke-width:3.5px;vector-effect:non-scaling-stroke;stroke-linecap:round;fill:none}.sc-ov .a{stroke:var(--anchor);stroke-width:5px;vector-effect:non-scaling-stroke;stroke-linecap:round;fill:none}.sc-chips{display:flex;flex-wrap:wrap;gap:6px}.sc-chip{font-size:12px;padding:4px 9px;border-radius:999px;border:1px solid var(--rule2);color:var(--dim);font-variant-numeric:tabular-nums}.sc-chip.win{border-color:transparent;background:var(--goodbg);color:var(--good)}.sc-results{display:flex;flex-direction:column;gap:12px;padding-top:8px;border-top:1px solid var(--rule2)}.sc-results h2{margin:8px 0 0;font-size:22px;font-weight:600}.sc-bignums{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}.sc-bignum{display:flex;flex-direction:column;gap:4px;padding:12px 14px;border:1px solid var(--rule2);border-radius:var(--radius-lg);background:var(--card);font-size:12px}.sc-bignum .v{font-size:28px;color:var(--accent);line-height:1.1}.sc-table{width:100%;border-collapse:collapse;font-size:12.5px;background:var(--card);border:1px solid var(--rule2);border-radius:var(--radius-lg);overflow:hidden}.sc-table th,.sc-table td{padding:8px 12px;text-align:right;border-bottom:1px solid var(--rule2);white-space:nowrap}.sc-table th:first-child,.sc-table td:first-child{text-align:left}.sc-table th{font-size:11px;font-weight:600;color:var(--faint);text-transform:uppercase;letter-spacing:.04em}.sc-table td.num{font-variant-numeric:tabular-nums;color:var(--dim)}.sc-table tr.win td{color:var(--ink)}.sc-table tr.win td:first-child{color:var(--accent);font-weight:600}.sc-note{font-size:12px!important}
studio/assets/main-x93uzIN_.js ADDED
The diff for this file is too large to render. See raw diff
 
studio/assets/showcase-Ip4y7DPQ.js ADDED
The diff for this file is too large to render. See raw diff
 
studio/assets/zip-DlX9-WSC.js ADDED
@@ -0,0 +1 @@
 
 
1
+ const b=(()=>{const u=new Uint32Array(256);for(let n=0;n<256;n++){let t=n;for(let c=0;c<8;c++)t=t&1?3988292384^t>>>1:t>>>1;u[n]=t>>>0}return u})();function m(u){let n=4294967295;for(let t=0;t<u.length;t++)n=b[(n^u[t])&255]^n>>>8;return(n^4294967295)>>>0}function v(u){const n=new TextEncoder,t=[],c=[];let l=0;const h=0,g=33;for(const r of u){const i=n.encode(r.name),y=m(r.data),U=r.data.length,a=new Uint8Array(30+i.length),s=new DataView(a.buffer);s.setUint32(0,67324752,!0),s.setUint16(4,20,!0),s.setUint16(6,2048,!0),s.setUint16(8,0,!0),s.setUint16(10,h,!0),s.setUint16(12,g,!0),s.setUint32(14,y,!0),s.setUint32(18,U,!0),s.setUint32(22,U,!0),s.setUint16(26,i.length,!0),s.setUint16(28,0,!0),a.set(i,30),t.push(a,r.data);const f=new Uint8Array(46+i.length),e=new DataView(f.buffer);e.setUint32(0,33639248,!0),e.setUint16(4,20,!0),e.setUint16(6,20,!0),e.setUint16(8,2048,!0),e.setUint16(10,0,!0),e.setUint16(12,h,!0),e.setUint16(14,g,!0),e.setUint32(16,y,!0),e.setUint32(20,U,!0),e.setUint32(24,U,!0),e.setUint16(28,i.length,!0),e.setUint32(42,l,!0),f.set(i,46),c.push(f),l+=a.length+U}const D=c.reduce((r,i)=>r+i.length,0),w=new Uint8Array(22),o=new DataView(w.buffer);o.setUint32(0,101010256,!0),o.setUint16(8,u.length,!0),o.setUint16(10,u.length,!0),o.setUint32(12,D,!0),o.setUint32(16,l,!0);const d=[...t,...c,w],p=new Uint8Array(d.reduce((r,i)=>r+i.length,0));let A=0;for(const r of d)p.set(r,A),A+=r.length;return p}export{m as crc32,v as zipStore};
denoise.js → studio/denoise.js RENAMED
File without changes
logo.svg → studio/favicon.svg RENAMED
File without changes
studio/fonts/inter-latin.woff2 ADDED
Binary file (48.3 kB). View file
 
studio/fonts/playfair-latin.woff2 ADDED
Binary file (38.4 kB). View file
 
studio/guide/batch.html ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <meta name="inkvec-guide" content="studio">
7
+ <title>Batch · Inkvec Studio guide</title>
8
+ <link rel="stylesheet" href="guide.css">
9
+ </head>
10
+ <body>
11
+ <div class="shell">
12
+ <aside class="side"><a class="guidebrand" href="index.html"><img src="logo-mono.svg" alt=""> <span>Inkvec Studio</span></a><div class="grp"><h4>User guide</h4><a href="index.html">Overview</a><a href="install.html">Install and first launch</a><a href="getting-started.html">Getting started</a><a href="viewer.html">The viewer</a><a href="result.html">Result</a><a href="tune.html">Tune</a><a href="palette.html">Palette and colour groups</a><a href="export.html">Export</a><a href="minify.html">Minify SVG</a><a href="fabricate.html">Fabricate</a><a href="batch.html" aria-current="page">Batch</a><a href="settings.html">Settings</a><a href="shortcuts.html">Keyboard and mouse</a><a href="troubleshooting.html">Troubleshooting</a></div><div class="grp"><h4>Tutorials</h4><a href="tutorials/jpeg-logo.html">Clean up a JPEG logo</a><a href="tutorials/favicon-asset-pack.html">A favicon and an asset pack</a><a href="tutorials/vinyl-htv.html">Layered vinyl and iron-on</a><a href="tutorials/laser.html">Laser: DXF and G-code</a></div><div class="grp"><h4>Online</h4><a href="https://logolabs.github.io/inkvec/">Inkvec documentation</a><a href="https://logolabs.github.io/inkvec/studio/batch.html">This page on the web</a></div><p class="guidenote">This copy of the guide is part of the app and works without a network.</p></aside>
13
+ <main><article><h1 id="batch">Batch</h1>
14
+ <p>The <strong>Batch</strong> tab traces every image in a folder and writes one SVG for each. It is for a set of
15
+ icons, a folder of partner logos, or a brand library.</p>
16
+ <p><img alt="The Batch tab with a folder of twelve images queued" src="img/batch.webp"></p>
17
+ <h2 id="running-a-batch">Running a batch</h2>
18
+ <ol>
19
+ <li><strong>Choose a folder…</strong> picks the folder of images. Every PNG, JPEG, WebP, GIF, BMP and TIFF in
20
+ it is listed, sorted by name. Subfolders are not included, and SVG files are skipped.</li>
21
+ <li><strong>Output</strong> is where the SVGs go. It starts as a folder called <code>svg</code> inside the input folder;
22
+ press it to choose another. It is created if it does not exist.</li>
23
+ <li><strong>Preset for all</strong> chooses the preset every queued file uses. To give one file a different
24
+ preset, click the preset in its row and choose; the rest stay as they are.</li>
25
+ <li><strong>Skip existing</strong> (on at first) leaves a file alone if its SVG is already in the output folder,
26
+ so a batch that was stopped can be run again to finish. Turn it off to overwrite.</li>
27
+ <li><strong>Start</strong>.</li>
28
+ </ol>
29
+ <p>Each output file has the image's name with <code>.svg</code>: <code>acme-mark.png</code> becomes <code>acme-mark.svg</code>.</p>
30
+ <p>Files are traced one at a time, each at full quality: the tracer already uses every processor core
31
+ on the file it is working on, so tracing several at once would not be faster. If you trace
32
+ something in the Vectorize tab during a batch, it goes first, and the batch waits for it.</p>
33
+ <p><strong>Pause</strong> stops before the next file, and <strong>Resume</strong> carries on; <strong>Cancel</strong> stops the run after
34
+ the file in progress. The file being traced is always finished, never left half-written.</p>
35
+ <h2 id="what-each-row-says">What each row says</h2>
36
+ <table>
37
+ <thead>
38
+ <tr>
39
+ <th>Column</th>
40
+ <th>Shows</th>
41
+ </tr>
42
+ </thead>
43
+ <tbody>
44
+ <tr>
45
+ <td>File</td>
46
+ <td>The image's name.</td>
47
+ </tr>
48
+ <tr>
49
+ <td>Preset</td>
50
+ <td>The preset for this file. Once a row has run it cannot be changed, because the figures beside it were measured with that preset.</td>
51
+ </tr>
52
+ <tr>
53
+ <td>Status</td>
54
+ <td><em>queued</em>, <em>running</em>, <em>done</em>, <em>skipped</em> or <em>failed</em>.</td>
55
+ </tr>
56
+ <tr>
57
+ <td>dE00</td>
58
+ <td>The mean colour difference of this file's trace, as in the <a href="result.html#the-quality-report">quality report</a>.</td>
59
+ </tr>
60
+ <tr>
61
+ <td>Coordinates</td>
62
+ <td>The coordinates in its SVG.</td>
63
+ </tr>
64
+ <tr>
65
+ <td>Output</td>
66
+ <td>The SVG's size.</td>
67
+ </tr>
68
+ <tr>
69
+ <td>Destination</td>
70
+ <td>Where the SVG was written, or, for a failed row, why it failed. Hover a row to read the whole message.</td>
71
+ </tr>
72
+ </tbody>
73
+ </table>
74
+ <p>The footer shows progress, an estimate of the time left, and once rows have finished, the mean
75
+ colour difference, the bytes written, and how much smaller that is than the source images.</p>
76
+ <p>Failures stay listed after the run. <strong>Failures first</strong> sorts them to the top, so a failed file
77
+ cannot scroll away unnoticed. <strong>Export stats.csv</strong> saves every row (file, preset, status, colour
78
+ difference, coordinates, bytes, seconds, destination, message) as a spreadsheet.</p>
79
+ <h2 id="which-settings-a-batch-uses">Which settings a batch uses</h2>
80
+ <p>A batch starts from the controls of your <strong>last trace</strong> in the Vectorize tab, then applies each
81
+ row's preset on top: the settings a preset changes from the defaults (Precision, Speckle floor,
82
+ Trace size, Max colours, Colour merging, the denoiser, Black &amp; white, Line art, Fewer paths) come
83
+ from the preset, and everything else, the Output settings such as <strong>Minify</strong> and
84
+ <strong>Transparent background</strong> included, comes from your last trace. Set the Output group the way you
85
+ want it in Vectorize before starting a batch.</p>
86
+ <p>Colour groups are never used: they belong to one image.</p>
87
+ <p>In version 0.2.0 the <strong>Editable</strong> preset does not turn on Editable structure in a batch (it is not
88
+ one of the settings listed above). To batch editable SVGs, turn <strong>Editable</strong> on in the Vectorize
89
+ tab, trace any image, and run the batch.</p>
90
+ <p>The batch writes SVGs only. For PNGs, favicons or an asset pack, export each image from Vectorize.</p>
91
+ <h2 id="dropping-files">Dropping files</h2>
92
+ <p>Several files dropped on the window switch to this tab, but are not queued: a batch works on a
93
+ folder. Choose the folder they are in.</p>
94
+ <h2 id="studio-lite">Studio Lite</h2>
95
+ <p>The Batch tab needs to read and write folders on disk, so it is not in Studio Lite. Trace the
96
+ images one at a time in Vectorize, or use the <code>inkvec</code> command line in a shell loop, one
97
+ <code>inkvec logo.png -o svg/logo.svg</code> per file.</p><nav class="pagenav"><a class="prev" href="fabricate.html"><span class="dir">Previous</span><span class="lbl">Fabricate</span></a><a class="next" href="settings.html"><span class="dir">Next</span><span class="lbl">Settings</span></a></nav></article></main>
98
+ <aside class="rail"><h5>On this page</h5><ul><ul><li class="l2"><a href="#running-a-batch">Running a batch</a></li><li class="l2"><a href="#what-each-row-says">What each row says</a></li><li class="l2"><a href="#which-settings-a-batch-uses">Which settings a batch uses</a></li><li class="l2"><a href="#dropping-files">Dropping files</a></li><li class="l2"><a href="#studio-lite">Studio Lite</a></li></ul></ul></aside>
99
+ </div>
100
+ </body>
101
+ </html>
studio/guide/export.html ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <meta name="inkvec-guide" content="studio">
7
+ <title>Export · Inkvec Studio guide</title>
8
+ <link rel="stylesheet" href="guide.css">
9
+ </head>
10
+ <body>
11
+ <div class="shell">
12
+ <aside class="side"><a class="guidebrand" href="index.html"><img src="logo-mono.svg" alt=""> <span>Inkvec Studio</span></a><div class="grp"><h4>User guide</h4><a href="index.html">Overview</a><a href="install.html">Install and first launch</a><a href="getting-started.html">Getting started</a><a href="viewer.html">The viewer</a><a href="result.html">Result</a><a href="tune.html">Tune</a><a href="palette.html">Palette and colour groups</a><a href="export.html" aria-current="page">Export</a><a href="minify.html">Minify SVG</a><a href="fabricate.html">Fabricate</a><a href="batch.html">Batch</a><a href="settings.html">Settings</a><a href="shortcuts.html">Keyboard and mouse</a><a href="troubleshooting.html">Troubleshooting</a></div><div class="grp"><h4>Tutorials</h4><a href="tutorials/jpeg-logo.html">Clean up a JPEG logo</a><a href="tutorials/favicon-asset-pack.html">A favicon and an asset pack</a><a href="tutorials/vinyl-htv.html">Layered vinyl and iron-on</a><a href="tutorials/laser.html">Laser: DXF and G-code</a></div><div class="grp"><h4>Online</h4><a href="https://logolabs.github.io/inkvec/">Inkvec documentation</a><a href="https://logolabs.github.io/inkvec/studio/export.html">This page on the web</a></div><p class="guidenote">This copy of the guide is part of the app and works without a network.</p></aside>
13
+ <main><article><h1 id="export">Export</h1>
14
+ <p>When the drawing is right, three buttons at the foot of the rail take it out of the app:
15
+ <strong>Export</strong> (files in a folder), <strong>Copy SVG</strong> (the clipboard) and the comparison card.</p>
16
+ <h2 id="the-export-sheet">The export sheet</h2>
17
+ <p><strong>Export</strong>, or <kbd>Ctrl</kbd>+<kbd>E</kbd> (<kbd>⌘</kbd>+<kbd>E</kbd> on a Mac), opens the
18
+ export sheet over the rail.</p>
19
+ <p><img alt="The export sheet: a checklist of formats, each with its size, and the destination" src="img/export.webp"></p>
20
+ <p>Tick what you want:</p>
21
+ <table>
22
+ <thead>
23
+ <tr>
24
+ <th>Row</th>
25
+ <th>Files written</th>
26
+ <th>Ticked at first</th>
27
+ </tr>
28
+ </thead>
29
+ <tbody>
30
+ <tr>
31
+ <td><strong>SVG</strong></td>
32
+ <td><code>name.svg</code>: the drawing as traced</td>
33
+ <td>yes</td>
34
+ </tr>
35
+ <tr>
36
+ <td><strong>SVG (minified)</strong></td>
37
+ <td><code>name.min.svg</code>: the same drawing with no ids, no groups and no trailing zeros</td>
38
+ <td>yes</td>
39
+ </tr>
40
+ <tr>
41
+ <td><strong>PNG · 512 / 1024 / 2048</strong></td>
42
+ <td><code>png/name-512.png</code>, <code>png/name-1024.png</code>, <code>png/name-2048.png</code></td>
43
+ <td>yes</td>
44
+ </tr>
45
+ <tr>
46
+ <td><strong>ICO and favicon set</strong></td>
47
+ <td><code>favicon/favicon.ico</code> (16, 32 and 48 px inside), and <code>favicon/favicon-16.png</code>, <code>-32.png</code>, <code>-48.png</code></td>
48
+ <td>no</td>
49
+ </tr>
50
+ <tr>
51
+ <td><strong>Asset pack (.zip)</strong></td>
52
+ <td><code>name-assets.zip</code>: everything above, plus <code>palette.json</code> and a <code>README.txt</code></td>
53
+ <td>yes</td>
54
+ </tr>
55
+ </tbody>
56
+ </table>
57
+ <p><code>name</code> is the name of the image you opened. The size beside each row is the real size of the files
58
+ it will write: the app builds them all in memory first and reports what it built, so nothing is an
59
+ estimate. The button at the bottom says how many files and how many bytes in total.</p>
60
+ <p><strong>To</strong> is the destination folder. It starts at the <em>Default output folder</em> from
61
+ <a href="settings.html#general">Settings</a> if you set one; <strong>Choose</strong> or <strong>Change</strong> picks another. With none
62
+ chosen, Export asks for one. <strong>Close</strong>, or a click outside the sheet, closes it.</p>
63
+ <p><strong>Export</strong> always runs a <strong>fresh full trace</strong> first, then writes the files. What is on screen may be
64
+ a draft, and a draft should never be shipped by accident. When the files are written, a note says
65
+ where, with <strong>Show in folder</strong>.</p>
66
+ <h3 id="the-asset-pack">The asset pack</h3>
67
+ <p>The zip always holds the complete set, whichever loose rows are ticked:</p>
68
+ <div class="codehilite"><pre><span></span>name.svg
69
+ name.min.svg
70
+ png/name-512.png, name-1024.png, name-2048.png
71
+ favicon/favicon.ico, favicon-16.png, favicon-32.png, favicon-48.png
72
+ palette.json
73
+ README.txt
74
+ </pre></div>
75
+
76
+ <p><code>palette.json</code> lists every ink with its hex value, the colour that was measured (<code>traced</code>), and its
77
+ share of the canvas; a gradient also lists its stops. <code>README.txt</code> is written for whoever opens the
78
+ pack later: the source file and its size, the size it was traced at, the colour difference and
79
+ coordinate count, what each file is, and the first item from
80
+ <a href="result.html#what-this-trace-could-not-recover">what this trace could not recover</a>, if there was
81
+ one.</p>
82
+ <p>Without the asset pack, <code>palette.json</code> is written loose beside the SVG.</p>
83
+ <h3 id="things-to-know">Things to know</h3>
84
+ <ul>
85
+ <li><strong>PNG and favicon files are square.</strong> In version 0.2.0 each PNG is drawn at exactly 512×512,
86
+ 1024×1024 or 2048×2048 pixels, and a drawing that is not square is <strong>stretched</strong> to fill it. For a
87
+ wide or tall logo, take the SVG and render it at the size you need elsewhere, or trace a square
88
+ version of the mark for the favicon (see the
89
+ <a href="tutorials/favicon-asset-pack.html">favicon tutorial</a>).</li>
90
+ <li><strong>Snapped colours are not exported.</strong> The fresh trace measures the colours again, so a snap made
91
+ in the palette does not reach the files. Use <strong>Copy SVG</strong> for a drawing with snapped colours, or
92
+ set the colour through a colour group (see <a href="palette.html#snapping-an-ink-to-an-exact-colour">the palette</a>).</li>
93
+ <li>The SVG always has the image's full size, whatever size it was traced at.</li>
94
+ </ul>
95
+ <h2 id="copy-svg">Copy SVG</h2>
96
+ <p><strong>Copy SVG</strong> puts the drawing on the clipboard as SVG text, ready to paste into Figma, Illustrator,
97
+ Inkscape or a code editor. It copies the drawing exactly as it is on screen, snapped colours
98
+ included. If the status strip says <em>draft shown</em>, wait for the full trace before copying.</p>
99
+ <h2 id="the-comparison-card">The comparison card</h2>
100
+ <p>The button with the share icon, beside Copy SVG, makes a poster of the result: the image and the
101
+ SVG side by side, and optionally the numbers and a zoomed detail where the vector edge cuts through
102
+ the source's pixels.</p>
103
+ <ul>
104
+ <li><strong>Format</strong>: <em>Landscape</em> (1600 × 900) or <em>Square</em> (1080 × 1080).</li>
105
+ <li><strong>Appearance</strong>: dark or light.</li>
106
+ <li><strong>On the card</strong>: <em>The numbers</em> (colour difference, coordinates, file size), <em>A zoomed detail</em>
107
+ (with its magnification, 4× to 24×), and <em>The file name</em>. The file name is off by default, so a
108
+ card of an unreleased logo does not give its name away.</li>
109
+ </ul>
110
+ <p><strong>Save PNG</strong> writes it (as <code>name-card.png</code>, by default); <strong>Copy image</strong> puts it on the clipboard.</p>
111
+ <h2 id="studio-lite">Studio Lite</h2>
112
+ <p>In Studio Lite there is no destination folder: Export and Save PNG download the files through your
113
+ browser, into its downloads folder.</p><nav class="pagenav"><a class="prev" href="palette.html"><span class="dir">Previous</span><span class="lbl">Palette and colour groups</span></a><a class="next" href="minify.html"><span class="dir">Next</span><span class="lbl">Minify SVG</span></a></nav></article></main>
114
+ <aside class="rail"><h5>On this page</h5><ul><ul><li class="l2"><a href="#the-export-sheet">The export sheet</a><ul><li class="l3"><a href="#the-asset-pack">The asset pack</a></li><li class="l3"><a href="#things-to-know">Things to know</a></li></ul></li><li class="l2"><a href="#copy-svg">Copy SVG</a></li><li class="l2"><a href="#the-comparison-card">The comparison card</a></li><li class="l2"><a href="#studio-lite">Studio Lite</a></li></ul></ul></aside>
115
+ </div>
116
+ </body>
117
+ </html>
studio/guide/fabricate.html ADDED
@@ -0,0 +1,328 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <meta name="inkvec-guide" content="studio">
7
+ <title>Fabricate · Inkvec Studio guide</title>
8
+ <link rel="stylesheet" href="guide.css">
9
+ </head>
10
+ <body>
11
+ <div class="shell">
12
+ <aside class="side"><a class="guidebrand" href="index.html"><img src="logo-mono.svg" alt=""> <span>Inkvec Studio</span></a><div class="grp"><h4>User guide</h4><a href="index.html">Overview</a><a href="install.html">Install and first launch</a><a href="getting-started.html">Getting started</a><a href="viewer.html">The viewer</a><a href="result.html">Result</a><a href="tune.html">Tune</a><a href="palette.html">Palette and colour groups</a><a href="export.html">Export</a><a href="minify.html">Minify SVG</a><a href="fabricate.html" aria-current="page">Fabricate</a><a href="batch.html">Batch</a><a href="settings.html">Settings</a><a href="shortcuts.html">Keyboard and mouse</a><a href="troubleshooting.html">Troubleshooting</a></div><div class="grp"><h4>Tutorials</h4><a href="tutorials/jpeg-logo.html">Clean up a JPEG logo</a><a href="tutorials/favicon-asset-pack.html">A favicon and an asset pack</a><a href="tutorials/vinyl-htv.html">Layered vinyl and iron-on</a><a href="tutorials/laser.html">Laser: DXF and G-code</a></div><div class="grp"><h4>Online</h4><a href="https://logolabs.github.io/inkvec/">Inkvec documentation</a><a href="https://logolabs.github.io/inkvec/studio/fabricate.html">This page on the web</a></div><p class="guidenote">This copy of the guide is part of the app and works without a network.</p></aside>
13
+ <main><article><h1 id="fabricate">Fabricate</h1>
14
+ <p>The <strong>Fabricate</strong> tab turns a drawing into files a cutting machine can use: adhesive vinyl in one
15
+ colour or several, iron-on (heat-transfer) vinyl, print-then-cut stickers, stencils, pen and
16
+ scoring lines, and laser or CNC cuts with DXF and G-code. It works in real sizes, in millimetres or
17
+ inches, and checks the job before anything is cut: a gradient that has to become one vinyl, a
18
+ sliver too thin to weed, a file a cutter's software will refuse.</p>
19
+ <p><img alt="The Fabricate tab: seven vinyl sheets stacked, with the thin parts marked, and the material and size on the right" src="img/fabricate-vinyl.webp"></p>
20
+ <p>Everything is recomputed on each change, in tens of milliseconds, so the sheets on the stage are
21
+ always the ones that will be saved.</p>
22
+ <h2 id="bringing-a-drawing-in">Bringing a drawing in</h2>
23
+ <ul>
24
+ <li><strong>Use the current trace</strong> takes what the Vectorize tab just traced. (Once a drawing is loaded,
25
+ the same button is <strong>Current trace</strong>, at the top of the rail.)</li>
26
+ <li><strong>Open an SVG</strong> (or <strong>Open…</strong>) takes any SVG file.</li>
27
+ <li><strong>Drop an SVG</strong> on the window while this tab is showing.</li>
28
+ </ul>
29
+ <p>When a drawing arrives, the tab measures it, selects every colour except the page background, and,
30
+ if there is more than one colour, switches to <strong>Layered</strong>.</p>
31
+ <h2 id="material">Material</h2>
32
+ <p>The quickest start is the material you are cutting. Each button sets several options at once; the
33
+ line under the buttons says what it chose.</p>
34
+ <table>
35
+ <thead>
36
+ <tr>
37
+ <th>Material</th>
38
+ <th>Makes</th>
39
+ <th>What it sets</th>
40
+ </tr>
41
+ </thead>
42
+ <tbody>
43
+ <tr>
44
+ <td><strong>Adhesive vinyl</strong></td>
45
+ <td>Cricut, Silhouette, Brother</td>
46
+ <td>Filled shapes, one sheet per colour stacked with a 0.8 mm overlap, registration marks, nothing narrower than 0.8 mm</td>
47
+ </tr>
48
+ <tr>
49
+ <td><strong>Iron-on</strong></td>
50
+ <td>Heat-transfer vinyl</td>
51
+ <td>As adhesive vinyl, but every sheet mirrored (HTV is cut face down), a 0.3 mm overlap (0.25 to 0.38 mm is the press-safe range), nothing narrower than 1 mm</td>
52
+ </tr>
53
+ <tr>
54
+ <td><strong>Sticker</strong></td>
55
+ <td>Print, then cut</td>
56
+ <td>The artwork with a contour 3 mm outside it</td>
57
+ </tr>
58
+ <tr>
59
+ <td><strong>Stencil</strong></td>
60
+ <td>Mylar or card, for paint or etching cream</td>
61
+ <td>The artwork cut out of one sheet, 1.5 mm bridges, a 10 mm border, nothing narrower than 1.5 mm</td>
62
+ </tr>
63
+ <tr>
64
+ <td><strong>Pen or score</strong></td>
65
+ <td>A pen, scoring or foil tool, plotter, or laser engraving lines</td>
66
+ <td>Each line drawn once down its middle, 0.4 mm tip, DXF saved too</td>
67
+ </tr>
68
+ <tr>
69
+ <td><strong>Laser or sign cutter</strong></td>
70
+ <td>Laser, CNC, sign cutter</td>
71
+ <td>Hairline cuts with each sheet in its own colour, inner shapes cut first, parts grown for a 0.15 mm kerf, nothing narrower than 0.3 mm, no registration marks, DXF saved too</td>
72
+ </tr>
73
+ </tbody>
74
+ </table>
75
+ <p>Glitter, holographic and puff HTV go on top of a stack only; the Iron-on note says so too. You can
76
+ change anything a material set, below; the material button then lets go.</p>
77
+ <h2 id="making">Making</h2>
78
+ <p>What is being made, in six modes:</p>
79
+ <table>
80
+ <thead>
81
+ <tr>
82
+ <th>Mode</th>
83
+ <th>Makes</th>
84
+ </tr>
85
+ </thead>
86
+ <tbody>
87
+ <tr>
88
+ <td><strong>One colour</strong></td>
89
+ <td>Everything selected, joined into one sheet of one material.</td>
90
+ </tr>
91
+ <tr>
92
+ <td><strong>Layered</strong></td>
93
+ <td>One sheet per colour. Each runs under the colours above it by the <em>bleed</em>, so the stacked result has no gaps; registration marks line the sheets up.</td>
94
+ </tr>
95
+ <tr>
96
+ <td><strong>Inlay</strong></td>
97
+ <td>One sheet per colour, cut exactly and laid edge to edge. Thinner than layered, but unforgiving to line up.</td>
98
+ </tr>
99
+ <tr>
100
+ <td><strong>Sticker</strong></td>
101
+ <td>The artwork with a contour around it, to print and then cut.</td>
102
+ </tr>
103
+ <tr>
104
+ <td><strong>Stencil</strong></td>
105
+ <td>A sheet with the artwork cut out. Pieces that would fall out, like the middle of an O, are held by thin bridges.</td>
106
+ </tr>
107
+ <tr>
108
+ <td><strong>Lines</strong></td>
109
+ <td>For a pen, a scoring blade or a laser line: every line in the drawing is followed once, along its centre, instead of around both edges. Strokes in the file are used as drawn; lines inside filled shapes are found and checked against the shape.</td>
110
+ </tr>
111
+ </tbody>
112
+ </table>
113
+ <h2 id="size">Size</h2>
114
+ <p><em>The design is</em> <strong>100</strong> <em>mm wide and</em> <strong>100</strong> <em>mm tall.</em> Type either number; the other follows,
115
+ keeping the drawing's proportions. <strong>mm</strong> and <strong>in</strong> switch every length on the tab, including the
116
+ ones in the findings.</p>
117
+ <p><strong>Cut a size-check square</strong> adds a small square (20 mm, or 1 in) below the design. Measure it once
118
+ it is cut: any other size means the cutter's program rescaled the file on import, which is the
119
+ most common complaint about cutter files.</p>
120
+ <p><strong>The files state their size in</strong> decides how the saved SVG says how big it is:</p>
121
+ <table>
122
+ <thead>
123
+ <tr>
124
+ <th>Choice</th>
125
+ <th>Read correctly by</th>
126
+ </tr>
127
+ </thead>
128
+ <tbody>
129
+ <tr>
130
+ <td><strong>Millimetres</strong></td>
131
+ <td>Most programs; exact by the SVG standard. The default.</td>
132
+ </tr>
133
+ <tr>
134
+ <td><strong>Pixels, 96/in</strong></td>
135
+ <td>Inkscape, LightBurn, Carbide Create, Fusion, and browsers</td>
136
+ </tr>
137
+ <tr>
138
+ <td><strong>Pixels, 72/in</strong></td>
139
+ <td>Cricut Design Space and Silhouette Studio</td>
140
+ </tr>
141
+ </tbody>
142
+ </table>
143
+ <p>If the program you use imports the file at the wrong size, choose the pixel rate it uses.</p>
144
+ <h2 id="colours">Colours</h2>
145
+ <p>Each colour of the drawing, with its share of the design and a switch to cut it or leave it out.
146
+ Badges mark the <em>page</em> (the background, left out at first), a <em>gradient</em> and a <em>translucent</em>
147
+ colour. In <strong>Layered</strong>, the list is the stack, bottom sheet first, and <strong>↓</strong> <strong>↑</strong> move a colour
148
+ down or up. The largest colour starts at the bottom, which is how a traced logo's colours stack in
149
+ nearly every case.</p>
150
+ <h2 id="cutting">Cutting</h2>
151
+ <p>What this card shows depends on the mode.</p>
152
+ <table>
153
+ <thead>
154
+ <tr>
155
+ <th>Option</th>
156
+ <th>Modes</th>
157
+ <th>What it does</th>
158
+ </tr>
159
+ </thead>
160
+ <tbody>
161
+ <tr>
162
+ <td>Each colour runs <em>x</em> under the colours above it</td>
163
+ <td>Layered</td>
164
+ <td>The bleed: how far each sheet reaches under the ones on top, so they overlap instead of leaving a gap. Default 0.8 mm.</td>
165
+ </tr>
166
+ <tr>
167
+ <td>The contour is <em>x</em> outside the artwork</td>
168
+ <td>Sticker</td>
169
+ <td>Default 3 mm.</td>
170
+ </tr>
171
+ <tr>
172
+ <td>Bridges are <em>x</em> wide; the sheet reaches <em>y</em> past the artwork</td>
173
+ <td>Stencil</td>
174
+ <td>Defaults 1.5 mm and 10 mm.</td>
175
+ </tr>
176
+ <tr>
177
+ <td>Parts narrower than <em>x</em> are too thin to weed</td>
178
+ <td>All but Lines</td>
179
+ <td>The smallest width the material holds. Parts narrower than this are reported (and drawn in red with <strong>Show problems</strong>).</td>
180
+ </tr>
181
+ <tr>
182
+ <td>Remove them</td>
183
+ <td>All but Lines</td>
184
+ <td>Drops those slivers and necks from the sheets instead of reporting them.</td>
185
+ </tr>
186
+ <tr>
187
+ <td>Registration marks</td>
188
+ <td>Layered, Inlay</td>
189
+ <td>Crosses at the same place on every sheet, to line them up.</td>
190
+ </tr>
191
+ <tr>
192
+ <td>Weeding border <em>x</em> outside</td>
193
+ <td>All but Lines</td>
194
+ <td>A frame around the design that makes weeding easier; 0 for none.</td>
195
+ </tr>
196
+ <tr>
197
+ <td>Also save a DXF</td>
198
+ <td>All</td>
199
+ <td>Every sheet as a layer of closed polylines in millimetres, curves as true arcs, for CAD, CNC and laser programs.</td>
200
+ </tr>
201
+ <tr>
202
+ <td>Also save G-code</td>
203
+ <td>All</td>
204
+ <td>For GRBL lasers and plotters (see below).</td>
205
+ </tr>
206
+ <tr>
207
+ <td>Mirror</td>
208
+ <td>Not Sticker or Stencil</td>
209
+ <td>Flips every sheet, for heat-transfer vinyl, which is cut from the back.</td>
210
+ </tr>
211
+ <tr>
212
+ <td>Cut lines as: Filled shapes / Hairlines</td>
213
+ <td>All but Lines</td>
214
+ <td><em>Filled shapes</em> is what Cricut Design Space and Silhouette Studio expect; they cut around every shape. <em>Hairlines</em> is the laser and sign-cutter convention: only a hairline is a cut, and each sheet keeps its colour so a laser program can give it its own operation.</td>
215
+ </tr>
216
+ <tr>
217
+ <td>The cut removes <em>x</em> (kerf)</td>
218
+ <td>Hairlines</td>
219
+ <td>The width the beam or blade removes. Parts are grown by half of it so they come out at the drawn size.</td>
220
+ </tr>
221
+ <tr>
222
+ <td>Router bit <em>x</em> across</td>
223
+ <td>All but Lines</td>
224
+ <td>Adds a dogbone to every inside corner, so parts cut with a round bit seat square; 0 for none.</td>
225
+ </tr>
226
+ <tr>
227
+ <td>Cuts stay within <em>x</em> of the drawing</td>
228
+ <td>All</td>
229
+ <td>How closely the cut paths follow the drawing. Default 0.05 mm. A larger value gives fewer segments.</td>
230
+ </tr>
231
+ </tbody>
232
+ </table>
233
+ <p>In <strong>Lines</strong> mode the card is <strong>Drawing</strong> instead: <em>The pen or tool draws</em> <strong>0.4</strong> <em>mm wide</em> (the
234
+ preview shows what the pen will leave), <em>Lines up to</em> <strong>0</strong> <em>mm wide are drawn once</em> (0 for any
235
+ width; wider parts are drawn round their outline), the DXF and G-code switches, and the tolerance.</p>
236
+ <h3 id="g-code">G-code</h3>
237
+ <p><strong>Also save G-code</strong> writes a <code>.gcode</code> file for GRBL lasers and plotters: curves as G2/G3 arcs,
238
+ holes and inner parts cut before the part around them, millimetres, origin at the lower left of
239
+ the job (marks and borders included). Jog the head to the lower left of the material and zero it
240
+ there. The sentence under the switch sets the feed (default 1000 mm/min), the power as GRBL's <code>S</code>
241
+ value (default 1000, GRBL's usual maximum), and the number of passes.</p>
242
+ <p>The file uses GRBL's laser mode (<code>M4</code>, power follows speed): turn it on with <code>$32=1</code> so the beam is
243
+ off between cuts. Test on scrap first: speed and power depend entirely on your machine and material.</p>
244
+ <h2 id="before-you-cut">Before you cut</h2>
245
+ <p>This card summarises the job (sheets, pieces, path segments, the size of the whole job) and lists
246
+ anything that will go wrong. With nothing to report it says <em>Nothing here will trouble the
247
+ cutter.</em></p>
248
+ <table>
249
+ <thead>
250
+ <tr>
251
+ <th>Finding</th>
252
+ <th>What to do</th>
253
+ </tr>
254
+ </thead>
255
+ <tbody>
256
+ <tr>
257
+ <td><em>#colour</em> is a gradient. Vinyl is one colour, so it is cut as its average colour.</td>
258
+ <td>Choose a vinyl close to the average, or leave the colour out.</td>
259
+ </tr>
260
+ <tr>
261
+ <td><em>#colour</em> is partly transparent. Vinyl is opaque, so it is cut at full strength.</td>
262
+ <td>As above.</td>
263
+ </tr>
264
+ <tr>
265
+ <td>No colour is selected.</td>
266
+ <td>Switch at least one colour on.</td>
267
+ </tr>
268
+ <tr>
269
+ <td>The file contains something with no cut line (such as an image) and it is left out.</td>
270
+ <td>Convert it to shapes first, or trace it.</td>
271
+ </tr>
272
+ <tr>
273
+ <td><em>N</em> mm² in <em>M</em> places is narrower than <em>x</em> mm and may tear or not stay stuck.</td>
274
+ <td>Make the design larger, or turn on <strong>Remove them</strong>.</td>
275
+ </tr>
276
+ <tr>
277
+ <td><em>N</em> mm² of waste is narrower than <em>x</em> mm between cuts and will lift with the design when weeding.</td>
278
+ <td>Make the design larger, or weed those spots by hand.</td>
279
+ </tr>
280
+ <tr>
281
+ <td><em>N</em> pieces are smaller than <em>x</em> mm² and are easily lost when weeding.</td>
282
+ <td>Make the design larger, or accept losing them.</td>
283
+ </tr>
284
+ <tr>
285
+ <td>A sheet has more than 5,000 separate cut paths.</td>
286
+ <td>Cricut Design Space is reported to refuse such files: turn on <strong>Remove them</strong> or raise the smallest width.</td>
287
+ </tr>
288
+ <tr>
289
+ <td>A sheet has more than 2,000 path segments.</td>
290
+ <td>Cutter software gets slow; a larger tolerance lowers it.</td>
291
+ </tr>
292
+ <tr>
293
+ <td>Holes and gaps are narrower than the router bit.</td>
294
+ <td>The bit cannot enter them: use a smaller bit, or make the design larger.</td>
295
+ </tr>
296
+ </tbody>
297
+ </table>
298
+ <p>Some findings are information rather than warnings: how many bridges hold a stencil together, how
299
+ many inside corners got dogbones, how many lines Lines mode draws once, and what the size-check
300
+ square is for.</p>
301
+ <h2 id="the-stage">The stage</h2>
302
+ <p><strong>All sheets</strong> shows every sheet stacked, as the finished piece will look; the numbered buttons
303
+ show one sheet each (hover one for its material size, pieces and segments). The size of the whole
304
+ job is at the right, with <em>marks included</em> or <em>border included</em> when they add to it. Sheets are
305
+ shown on a light ground, where a thin cut line and a pale vinyl are both visible.</p>
306
+ <p><strong>Show problems</strong> (on while there are any) draws the parts too thin to weed in red, the waste gaps
307
+ too narrow to weed in amber, and rings the loose specks.</p>
308
+ <p>The <strong>Cut list</strong> at the bottom of the rail is the shopping list: each sheet with the piece of
309
+ material it needs and how many pieces it has. Click a row to show that sheet.</p>
310
+ <h2 id="saving">Saving</h2>
311
+ <p><strong>Save <em>N</em> sheets…</strong> asks for a folder and writes:</p>
312
+ <ul>
313
+ <li>one SVG per sheet: <code>name-1-colour.svg</code>, <code>name-2-colour.svg</code> and so on, bottom sheet first (or
314
+ <code>name-cut.svg</code> when there is only one);</li>
315
+ <li><code>name-all.svg</code>, every sheet in one file as separate groups, which cutter software turns into
316
+ layers on import (often the only file you need);</li>
317
+ <li><code>name.dxf</code> and <code>name.gcode</code>, if those switches are on.</li>
318
+ </ul>
319
+ <p><strong>Copy</strong> puts the sheet on screen (or all of them, in one file) on the clipboard, to paste into
320
+ Design Space, Silhouette Studio or LightBurn. The foot of the rail repeats the real width.</p>
321
+ <p>The <a href="tutorials/vinyl-htv.html">layered vinyl tutorial</a> and the <a href="tutorials/laser.html">laser tutorial</a>
322
+ take a drawing through this tab from start to finish.</p>
323
+ <h2 id="studio-lite">Studio Lite</h2>
324
+ <p><strong>Save</strong> downloads the files instead of writing them to a folder.</p><nav class="pagenav"><a class="prev" href="minify.html"><span class="dir">Previous</span><span class="lbl">Minify SVG</span></a><a class="next" href="batch.html"><span class="dir">Next</span><span class="lbl">Batch</span></a></nav></article></main>
325
+ <aside class="rail"><h5>On this page</h5><ul><ul><li class="l2"><a href="#bringing-a-drawing-in">Bringing a drawing in</a></li><li class="l2"><a href="#material">Material</a></li><li class="l2"><a href="#making">Making</a></li><li class="l2"><a href="#size">Size</a></li><li class="l2"><a href="#colours">Colours</a></li><li class="l2"><a href="#cutting">Cutting</a><ul><li class="l3"><a href="#g-code">G-code</a></li></ul></li><li class="l2"><a href="#before-you-cut">Before you cut</a></li><li class="l2"><a href="#the-stage">The stage</a></li><li class="l2"><a href="#saving">Saving</a></li><li class="l2"><a href="#studio-lite">Studio Lite</a></li></ul></ul></aside>
326
+ </div>
327
+ </body>
328
+ </html>
studio/guide/getting-started.html ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <meta name="inkvec-guide" content="studio">
7
+ <title>Getting started · Inkvec Studio guide</title>
8
+ <link rel="stylesheet" href="guide.css">
9
+ </head>
10
+ <body>
11
+ <div class="shell">
12
+ <aside class="side"><a class="guidebrand" href="index.html"><img src="logo-mono.svg" alt=""> <span>Inkvec Studio</span></a><div class="grp"><h4>User guide</h4><a href="index.html">Overview</a><a href="install.html">Install and first launch</a><a href="getting-started.html" aria-current="page">Getting started</a><a href="viewer.html">The viewer</a><a href="result.html">Result</a><a href="tune.html">Tune</a><a href="palette.html">Palette and colour groups</a><a href="export.html">Export</a><a href="minify.html">Minify SVG</a><a href="fabricate.html">Fabricate</a><a href="batch.html">Batch</a><a href="settings.html">Settings</a><a href="shortcuts.html">Keyboard and mouse</a><a href="troubleshooting.html">Troubleshooting</a></div><div class="grp"><h4>Tutorials</h4><a href="tutorials/jpeg-logo.html">Clean up a JPEG logo</a><a href="tutorials/favicon-asset-pack.html">A favicon and an asset pack</a><a href="tutorials/vinyl-htv.html">Layered vinyl and iron-on</a><a href="tutorials/laser.html">Laser: DXF and G-code</a></div><div class="grp"><h4>Online</h4><a href="https://logolabs.github.io/inkvec/">Inkvec documentation</a><a href="https://logolabs.github.io/inkvec/studio/getting-started.html">This page on the web</a></div><p class="guidenote">This copy of the guide is part of the app and works without a network.</p></aside>
13
+ <main><article><h1 id="getting-started">Getting started</h1>
14
+ <p>This page opens an image, explains the choice the app offers when it does, and walks through the
15
+ Custom wizard. The fastest way to follow along is with one of the samples on the empty stage.</p>
16
+ <h2 id="opening-an-image">Opening an image</h2>
17
+ <p>Any of these opens an image in the <strong>Vectorize</strong> tab:</p>
18
+ <ul>
19
+ <li><strong>Open…</strong> in the app bar, <strong>Open an image</strong> on the empty stage, or <kbd>Ctrl</kbd>+<kbd>O</kbd>
20
+ (<kbd>⌘</kbd>+<kbd>O</kbd> on a Mac).</li>
21
+ <li><strong>Drag a file onto the window.</strong> The whole window takes the drop, not only the dashed box.</li>
22
+ <li><strong>Recent</strong> in the app bar: the last eight files you opened.</li>
23
+ <li><strong>A sample</strong> from the row under the drop area, on the empty stage: <em>Flat logo</em>, <em>Icon, 64 px</em>,
24
+ <em>Crest, filigree</em> and <em>Signature, B&amp;W</em>.</li>
25
+ <li><strong>Vectorize with Inkvec</strong> in your file manager's right-click menu, once you have added it in
26
+ <a href="settings.html#advanced">Settings</a> (Windows and Linux). If the app is already open, the file opens
27
+ in the window you have rather than a second copy.</li>
28
+ </ul>
29
+ <p>The app reads PNG, JPEG, WebP, GIF, BMP and TIFF. It also opens an <strong>SVG</strong>: the SVG is drawn at
30
+ 1024 px on its longer side and traced from that picture, which is how a messy drawing comes back
31
+ as clean shapes. To make an SVG smaller <em>without</em> re-drawing it, use <a href="minify.html">Minify SVG</a>
32
+ instead.</p>
33
+ <p>What a dropped file does depends on what it is:</p>
34
+ <table>
35
+ <thead>
36
+ <tr>
37
+ <th>You drop</th>
38
+ <th>What happens</th>
39
+ </tr>
40
+ </thead>
41
+ <tbody>
42
+ <tr>
43
+ <td>One image</td>
44
+ <td>Opens in Vectorize, whichever tab you were on.</td>
45
+ </tr>
46
+ <tr>
47
+ <td>One SVG, on the Vectorize tab</td>
48
+ <td>Opens in Vectorize, to be re-traced.</td>
49
+ </tr>
50
+ <tr>
51
+ <td>One SVG, on the Fabricate tab</td>
52
+ <td>Opens in Fabricate, to be cut.</td>
53
+ </tr>
54
+ <tr>
55
+ <td>One SVG, on another tab</td>
56
+ <td>Opens in Minify SVG.</td>
57
+ </tr>
58
+ <tr>
59
+ <td>Several files</td>
60
+ <td>Switches to Batch. The files are not queued: Batch works on a folder, so choose the folder they are in.</td>
61
+ </tr>
62
+ </tbody>
63
+ </table>
64
+ <p>The app bar shows the open file's name, its size in pixels and its format.</p>
65
+ <p><strong>Studio Lite:</strong> there is no right-click entry, and a dropped or chosen file is read by the browser.</p>
66
+ <h2 id="auto-traces-at-once">Auto traces at once</h2>
67
+ <p>The moment an image opens, <strong>Auto</strong> traces it. It uses the controls exactly as you left them the
68
+ last time (the first time, the <strong>Logo</strong> preset, which is the default). Nothing has to be chosen
69
+ first, and the trace is already on its way when the next thing appears.</p>
70
+ <h2 id="the-choice-card-keep-auto-or-customise">The choice card: Keep Auto or Customise</h2>
71
+ <p>Over the stage, a small card appears while Auto traces.</p>
72
+ <p><img alt="The card that appears when an image opens, with Auto's result and the Custom option" src="img/chooser.webp"></p>
73
+ <ul>
74
+ <li><strong>Auto</strong> shows the trace's progress and, once it lands, its colour difference, coordinates
75
+ and file size. <strong>Keep Auto</strong> closes the card.</li>
76
+ <li><strong>Custom</strong> opens the wizard (next section), which changes the settings a step at a time with
77
+ your result shown beside Auto's.</li>
78
+ <li><strong>Auto chose</strong> says what Auto used, and anything its own report suggests. There are at most
79
+ two suggestions, and each is a one-click preset change:</li>
80
+ </ul>
81
+ <table>
82
+ <thead>
83
+ <tr>
84
+ <th>Suggestion</th>
85
+ <th>When it appears</th>
86
+ <th>What <strong>Try</strong> does</th>
87
+ </tr>
88
+ </thead>
89
+ <tbody>
90
+ <tr>
91
+ <td>Looks like a photo, a scan or a screenshot</td>
92
+ <td>The file is a JPEG or a lossy WebP, or its pixels are noisy</td>
93
+ <td>Switches to <em>Photo or scan</em>, which uses the denoiser</td>
94
+ </tr>
95
+ <tr>
96
+ <td>Two colours, black and white</td>
97
+ <td>Exactly two inks, one dark and one light, both neutral</td>
98
+ <td>Switches to <em>Black &amp; white</em></td>
99
+ </tr>
100
+ <tr>
101
+ <td>Drawn with strokes</td>
102
+ <td>The report found line work traced as outlines</td>
103
+ <td>Switches to <em>Line art</em></td>
104
+ </tr>
105
+ <tr>
106
+ <td>A small flat mark</td>
107
+ <td>256 px or smaller, no gradients, at most 16 colours</td>
108
+ <td>Switches to <em>Icon</em></td>
109
+ </tr>
110
+ </tbody>
111
+ </table>
112
+ <p>If the palette has inks that look like the same colour measured twice, a line offers to
113
+ <strong>Accept</strong> them as colour groups (see <a href="palette.html#colour-groups">the palette</a>).
114
+ - <strong>Remember my choice</strong> makes the button you press next the default for every image. Change it
115
+ later in <a href="settings.html#general">Settings</a>, <em>When an image is opened</em>: <strong>Ask</strong> (this card),
116
+ <strong>Auto only</strong>, or <strong>Custom wizard</strong>.</p>
117
+ <p>Closing the card with <strong>×</strong> or <kbd>Esc</kbd>, or simply carrying on, keeps Auto. Once the card
118
+ is gone, the same <em>Auto chose</em> note stays at the top of the Result tab while it has something to
119
+ offer, with <strong>Customise</strong> and <strong>Hide</strong>.</p>
120
+ <p>Nothing here changes a trace by itself. A suggestion you take is an ordinary preset change, shown
121
+ under Tune like any other, and <strong>Back to Auto</strong> puts the controls back where Auto had them.</p>
122
+ <h2 id="the-custom-wizard">The Custom wizard</h2>
123
+ <p><strong>Customise…</strong> opens the wizard in place of the rail. The big view stays beside it, and its left
124
+ pane shows <strong>Auto's trace</strong> (or the <strong>Source</strong>, if you switch it) so you can compare as you go; the
125
+ right pane is yours.</p>
126
+ <p><img alt="The wizard's first step: small draft previews of the image under each kind of preset" src="img/wizard-kind.webp"></p>
127
+ <p>Each step says what it does, when to change it, what it costs, and links to the part of
128
+ <a href="https://logolabs.github.io/inkvec/algorithm/index.html">How Inkvec works</a> behind it. The steps are:</p>
129
+ <ol>
130
+ <li><strong>What is it?</strong> Tiles for the kinds of image, each a small draft of <em>this</em> image under that
131
+ preset: <em>Logo</em>, <em>Icon</em>, <em>Illustration or emoji</em> (the Fine detail preset), <em>Line art</em>,
132
+ <em>Black &amp; white</em> and <em>Photo or scan</em>, plus Auto's own result. Presets Auto suggested come first,
133
+ marked <em>suggested</em>. Hover a tile to see its draft large in the left pane; click it to choose it,
134
+ and the full trace follows on the right. The drafts are traced one at a time, after Auto's
135
+ trace, so they never hold it up.</li>
136
+ <li><strong>Clean-up.</strong> Only offered when the image looks damaged: a JPEG or a lossy WebP, or pixels that
137
+ measure noisy, and only in builds that include the denoiser. It says why it was offered.
138
+ <strong>Off</strong> traces the pixels as they are; <strong>Auto</strong> cleans compression damage first, where it finds
139
+ some. If the denoiser is not downloaded yet, the step offers the download (see
140
+ <a href="settings.html#denoiser">the denoiser</a>).</li>
141
+ <li><strong>Colours.</strong> The palette, with suggested colour groups, and <strong>Max colours</strong>. For an image with
142
+ transparency, also <strong>Trace transparency</strong>. Hover an ink or a group to single it out in the
143
+ drawing.</li>
144
+ <li><strong>Detail.</strong> <strong>Precision</strong> and <strong>Speckle floor</strong>, and a <em>Compare as</em> switch (side by side or
145
+ wipe).</li>
146
+ <li><strong>Shape.</strong> <strong>Editable structure</strong>, <strong>Fewer paths</strong>, <strong>Match repeated shapes</strong>, <strong>Curve cost</strong>
147
+ and <strong>Smooth-join angle</strong>.</li>
148
+ <li><strong>Output.</strong> <strong>Transparent background</strong>, <strong>Margin</strong> and <strong>Minify</strong>, and a list of everything
149
+ you changed from Auto.</li>
150
+ </ol>
151
+ <p>From step 4 on, a small table compares Auto's figures with yours: colour difference, nodes, paths
152
+ and file size, with the change in each.</p>
153
+ <p>What each control does is on the <a href="tune.html">Tune</a> page; the wizard shows the same controls, only
154
+ fewer at a time.</p>
155
+ <p>Along the bottom: <strong>Back</strong>, <strong>Skip to finish</strong> (jump to the last step, keeping everything chosen),
156
+ and <strong>Next</strong>. On the last step, <strong>Finish</strong> closes the wizard and <strong>Export now</strong> closes it and opens
157
+ the export sheet. At the top, <strong>Undo my changes</strong> puts every control and colour group back to where
158
+ they were when the wizard opened, and <strong>Close</strong> (or <kbd>Esc</kbd>) leaves, keeping what you chose.</p>
159
+ <p>Whatever the wizard changed is an ordinary setting. When it closes, the rail switches to <strong>Tune</strong>
160
+ with those controls marked as changed, and a note says how many moved from Auto.</p>
161
+ <p>To reopen the wizard for the image that is open, use <strong>Walk me through it</strong> at the top of the Tune
162
+ tab, or <strong>Customise</strong> on the <em>Auto chose</em> note.</p>
163
+ <h2 id="what-to-do-next">What to do next</h2>
164
+ <ul>
165
+ <li>Look at the result: <a href="viewer.html">the viewer</a> explains the comparison modes, zoom, and the
166
+ overlays that show nodes and edges.</li>
167
+ <li>Read the numbers: <a href="result.html">Result</a> explains the quality report.</li>
168
+ <li>Change something: <a href="tune.html">Tune</a> lists every control.</li>
169
+ <li>Save it: <a href="export.html">Export</a>.</li>
170
+ </ul><nav class="pagenav"><a class="prev" href="install.html"><span class="dir">Previous</span><span class="lbl">Install and first launch</span></a><a class="next" href="viewer.html"><span class="dir">Next</span><span class="lbl">The viewer</span></a></nav></article></main>
171
+ <aside class="rail"><h5>On this page</h5><ul><ul><li class="l2"><a href="#opening-an-image">Opening an image</a></li><li class="l2"><a href="#auto-traces-at-once">Auto traces at once</a></li><li class="l2"><a href="#the-choice-card-keep-auto-or-customise">The choice card: Keep Auto or Customise</a></li><li class="l2"><a href="#the-custom-wizard">The Custom wizard</a></li><li class="l2"><a href="#what-to-do-next">What to do next</a></li></ul></ul></aside>
172
+ </div>
173
+ </body>
174
+ </html>
studio/guide/guide.css ADDED
@@ -0,0 +1,224 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* LogoLabs design system: warm charcoal ramp, one copper accent, Playfair Display +
2
+ * Inter + IBM Plex Mono. Tokens match web/index.html and the design-system zip. */
3
+ :root{
4
+ --paper:#1a1816;--card:#211f1c;--stage:#141210;--void:#0c0a09;--surface:#2a2724;--highlight:#35322e;
5
+ --ink:#faf8f5;--dim:rgba(250,248,245,.75);--faint:rgba(250,248,245,.55);--muted:rgba(250,248,245,.4);
6
+ --rule:rgba(250,248,245,.08);--rule2:#2a2724;
7
+ --accent:#c9754a;--accent-hover:#d4896a;--accent-ink:#1a1816;--accent-soft:rgba(201,117,74,.12);
8
+ --gold:#b8976c;--good:#34d399;--bad:#f87171;
9
+ --font-display:"Playfair Display",Georgia,serif;--font-body:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
10
+ --font-mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,Consolas,monospace;
11
+ }
12
+ *{box-sizing:border-box}
13
+ html{color-scheme:dark}
14
+ body{margin:0;background:var(--paper);color:var(--ink);font:16px/1.65 var(--font-body);
15
+ -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
16
+ a{color:var(--accent);text-decoration:none}
17
+ a:hover{color:var(--accent-hover)}
18
+ ::selection{background:rgba(201,117,74,.35)}
19
+
20
+ /* top bar */
21
+ .top{position:sticky;top:0;z-index:10;display:flex;align-items:center;justify-content:space-between;
22
+ padding:0 20px;height:56px;background:rgba(26,24,22,.92);backdrop-filter:blur(8px);border-bottom:1px solid var(--rule)}
23
+ .brand{display:flex;align-items:center;gap:10px;color:var(--ink)}
24
+ .brand img{width:22px;height:22px}
25
+ .brand span{font-family:var(--font-display);font-weight:700;font-size:19px;letter-spacing:-.01em}
26
+ .toplinks{display:flex;gap:22px;font-size:13.5px;font-weight:500}
27
+ .toplinks a{color:var(--dim)}
28
+ .toplinks a:hover{color:var(--accent)}
29
+
30
+ /* shell: sidebar / article / toc rail */
31
+ .shell{display:grid;grid-template-columns:240px minmax(0,1fr) 200px;gap:0;max-width:1400px;margin:0 auto}
32
+ .side{border-right:1px solid var(--rule);padding:28px 18px 60px 24px;position:sticky;top:56px;
33
+ height:calc(100vh - 56px);overflow-y:auto;scrollbar-width:thin}
34
+ .side .grp{margin:0 0 22px}
35
+ .side .grp h4{margin:0 0 8px;font:500 10.5px/1 var(--font-mono);letter-spacing:.14em;text-transform:uppercase;
36
+ color:var(--muted)}
37
+ .side a{display:block;padding:4px 8px;margin:1px -8px;border-radius:6px;font-size:13.5px;color:var(--faint)}
38
+ .side a:hover{color:var(--ink);background:var(--card)}
39
+ .side a[aria-current]{color:var(--accent);background:var(--accent-soft)}
40
+ .side a .n{font:500 10.5px/1 var(--font-mono);color:var(--muted);margin-right:7px}
41
+ .side a[aria-current] .n{color:var(--accent)}
42
+
43
+ main{padding:44px 48px 90px;min-width:0}
44
+ article{max-width:46rem}
45
+ article h1,article h2,article h3,article h4{font-family:var(--font-display);font-weight:600;
46
+ letter-spacing:-.01em;line-height:1.2;color:var(--ink);scroll-margin-top:76px}
47
+ article h1{font-size:2.1rem;margin:0 0 18px}
48
+ article h2{font-size:1.45rem;margin:2.2em 0 .6em;padding-top:.7em;border-top:1px solid var(--rule)}
49
+ article h3{font-size:1.12rem;margin:1.8em 0 .5em}
50
+ article p{margin:0 0 1em;color:var(--dim)}
51
+ article li{color:var(--dim);margin:.3em 0}
52
+ article strong{color:var(--ink);font-weight:600}
53
+ article hr{border:0;border-top:1px solid var(--rule);margin:2.5em 0}
54
+ article img{max-width:100%;border-radius:10px;height:auto}
55
+ article a{text-decoration:underline;text-decoration-color:rgba(201,117,74,.35);text-underline-offset:3px}
56
+ article a:hover{text-decoration-color:var(--accent)}
57
+ .md-anchor{position:relative;top:-70px}
58
+
59
+ kbd{font-family:var(--font-mono);font-size:.8em;background:var(--surface);color:var(--ink);
60
+ border:1px solid var(--highlight);border-bottom-width:2px;border-radius:5px;padding:.05em .4em;white-space:nowrap}
61
+ code{font-family:var(--font-mono);font-size:.86em;background:var(--surface);
62
+ border:1px solid var(--rule);border-radius:5px;padding:.1em .35em;color:var(--ink)}
63
+ .codehilite{background:var(--stage)!important;border:1px solid var(--rule);border-radius:10px;
64
+ padding:14px 16px;overflow-x:auto;margin:0 0 1.2em}
65
+ .codehilite pre{margin:0;background:transparent!important}
66
+ .codehilite code{background:transparent;border:0;padding:0;font-size:13px;line-height:1.6}
67
+
68
+ table{border-collapse:collapse;width:100%;margin:0 0 1.2em;font-size:14px;display:block;overflow-x:auto}
69
+ th,td{border:1px solid var(--rule2);padding:7px 11px;text-align:left;vertical-align:top;color:var(--dim)}
70
+ th{background:var(--card);color:var(--ink);font-weight:600;font-size:13px}
71
+ tbody tr:nth-child(2n){background:rgba(250,248,245,.02)}
72
+ table code{white-space:nowrap}
73
+
74
+ blockquote{margin:0 0 1.2em;padding:10px 16px;border-left:3px solid var(--accent);
75
+ background:var(--accent-soft);border-radius:0 8px 8px 0}
76
+ blockquote p{margin:0 0 .5em;color:var(--ink)}
77
+ blockquote p:last-child{margin:0}
78
+
79
+ .math{overflow-x:auto;overflow-y:hidden;padding:6px 2px;margin:0 0 1.2em}
80
+ .katex-display{margin:.4em 0!important}
81
+ .katex{color:var(--ink)}
82
+
83
+ /* per-page toc rail */
84
+ .rail{padding:52px 20px 60px 0;position:sticky;top:56px;height:calc(100vh - 56px);overflow-y:auto}
85
+ .rail h5{margin:0 0 10px;font:500 10.5px/1 var(--font-mono);letter-spacing:.14em;text-transform:uppercase;
86
+ color:var(--muted)}
87
+ .rail ul{list-style:none;margin:0;padding:0}
88
+ .rail ul ul{padding-left:12px}
89
+ .rail a{display:block;padding:3px 0;font-size:12.5px;color:var(--muted);line-height:1.45}
90
+ .rail a:hover{color:var(--accent)}
91
+ .rail .l2>a{color:var(--faint)}
92
+
93
+ /* index hero */
94
+ .hero{padding:8px 0 34px;border-bottom:1px solid var(--rule);margin-bottom:34px}
95
+ .eyebrow{font:500 11px/1 var(--font-mono);letter-spacing:.22em;color:var(--accent);margin:0 0 14px}
96
+ .hero h1{font-family:var(--font-display);font-size:3.4rem;font-weight:700;letter-spacing:-.02em;margin:0 0 14px;line-height:1.05}
97
+ .hero .pitch{font-size:1.14rem;color:var(--faint);max-width:34rem;margin:0 0 24px}
98
+ .cta{display:flex;gap:12px;flex-wrap:wrap}
99
+ .btn{display:inline-block;padding:10px 20px;border-radius:999px;font-size:14px;font-weight:600;
100
+ border:1px solid var(--rule2);color:var(--ink);background:var(--card)}
101
+ .btn:hover{border-color:var(--highlight);color:var(--ink)}
102
+ .btn.primary{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
103
+ .btn.primary:hover{background:var(--accent-hover);border-color:var(--accent-hover);color:var(--accent-ink)}
104
+ .btn.ghost{background:transparent}
105
+
106
+ /* pointer to the diagram edition */
107
+ .plainlink{margin:-6px 0 1.6em;font-size:14px}
108
+ .plainlink a{font-weight:500}
109
+
110
+ /* the mark before the wordmark in the hero */
111
+ .heromark{height:.8em;width:auto;vertical-align:-.08em;margin-right:.22em}
112
+
113
+ /* about block on the landing page */
114
+ .about{margin-top:3.2em;padding-top:1.4em;border-top:1px solid var(--rule)}
115
+ .about p{color:var(--faint);max-width:38rem}
116
+
117
+ /* prev / next */
118
+ .pagenav{display:flex;justify-content:space-between;gap:14px;margin-top:3.2em;padding-top:1.2em;
119
+ border-top:1px solid var(--rule)}
120
+ .pagenav a{flex:1;border:1px solid var(--rule2);background:var(--card);border-radius:10px;padding:11px 15px;
121
+ text-decoration:none}
122
+ .pagenav a:hover{border-color:rgba(201,117,74,.45)}
123
+ .pagenav .dir{display:block;font:500 10.5px/1 var(--font-mono);letter-spacing:.12em;color:var(--muted);margin-bottom:4px}
124
+ .pagenav .lbl{color:var(--ink);font-weight:600;font-size:14px}
125
+ .pagenav .next{text-align:right}
126
+
127
+ footer{border-top:1px solid var(--rule);padding:26px 24px;display:flex;justify-content:space-between;
128
+ gap:16px;flex-wrap:wrap;font-size:13px;color:var(--muted)}
129
+ footer a{color:var(--dim)}
130
+ footer a:hover{color:var(--accent)}
131
+
132
+ @media (max-width:1150px){.rail{display:none}.shell{grid-template-columns:220px minmax(0,1fr)}}
133
+ @media (max-width:820px){
134
+ .shell{grid-template-columns:minmax(0,1fr)}
135
+ .side{position:static;height:auto;border-right:0;border-bottom:1px solid var(--rule);padding:18px 24px}
136
+ .side .grp{display:inline-block;vertical-align:top;margin:0 26px 14px 0}
137
+ main{padding:30px 22px 70px}
138
+ .hero h1{font-size:2.5rem}
139
+ }
140
+
141
+ @font-face{font-family:"Inter";src:url("../fonts/inter-latin.woff2") format("woff2");font-weight:100 900;font-display:swap}
142
+ @font-face{font-family:"Playfair Display";src:url("../fonts/playfair-latin.woff2") format("woff2");font-weight:400 900;font-display:swap}
143
+ :root{--font-mono:ui-monospace,SFMono-Regular,Consolas,"Liberation Mono",monospace}
144
+ .side,.rail{top:0;height:100vh}
145
+ .side .guidebrand{display:flex;align-items:center;gap:9px;margin:0 0 22px;color:var(--ink)}
146
+ .side .guidebrand img{width:20px;height:20px}
147
+ .side .guidebrand span{font-family:var(--font-display);font-weight:700;font-size:17px}
148
+ .side .guidebrand:hover{background:none}
149
+ .guidenote{font-size:12px;color:var(--muted);margin:26px 0 0;line-height:1.5}
150
+ .shell{max-width:1320px}
151
+
152
+ pre { line-height: 125%; }
153
+ td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
154
+ span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
155
+ td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
156
+ span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
157
+ .codehilite .hll { background-color: #2a2724 }
158
+ .codehilite { background: ; color: #FAF8F5 }
159
+ .codehilite .c { color: #8A837B; font-style: italic } /* Comment */
160
+ .codehilite .err { color: #F87171 } /* Error */
161
+ .codehilite .k { color: #C9754A } /* Keyword */
162
+ .codehilite .n { color: #FAF8F5 } /* Name */
163
+ .codehilite .o { color: #C9754A } /* Operator */
164
+ .codehilite .p { color: #BFB9B1 } /* Punctuation */
165
+ .codehilite .ch { color: #8A837B; font-style: italic } /* Comment.Hashbang */
166
+ .codehilite .cm { color: #8A837B; font-style: italic } /* Comment.Multiline */
167
+ .codehilite .cp { color: #8A837B; font-style: italic } /* Comment.Preproc */
168
+ .codehilite .cpf { color: #8A837B; font-style: italic } /* Comment.PreprocFile */
169
+ .codehilite .c1 { color: #8A837B; font-style: italic } /* Comment.Single */
170
+ .codehilite .cs { color: #8A837B; font-style: italic } /* Comment.Special */
171
+ .codehilite .gd { color: #F87171 } /* Generic.Deleted */
172
+ .codehilite .ge { font-style: italic } /* Generic.Emph */
173
+ .codehilite .gi { color: #34D399 } /* Generic.Inserted */
174
+ .codehilite .gs { font-weight: bold } /* Generic.Strong */
175
+ .codehilite .kc { color: #C9754A } /* Keyword.Constant */
176
+ .codehilite .kd { color: #C9754A } /* Keyword.Declaration */
177
+ .codehilite .kn { color: #C9754A } /* Keyword.Namespace */
178
+ .codehilite .kp { color: #C9754A } /* Keyword.Pseudo */
179
+ .codehilite .kr { color: #C9754A } /* Keyword.Reserved */
180
+ .codehilite .kt { color: #B8976C } /* Keyword.Type */
181
+ .codehilite .m { color: #B8976C } /* Literal.Number */
182
+ .codehilite .s { color: #34D399 } /* Literal.String */
183
+ .codehilite .na { color: #B8976C } /* Name.Attribute */
184
+ .codehilite .nb { color: #B8976C } /* Name.Builtin */
185
+ .codehilite .nc { color: #D4896A } /* Name.Class */
186
+ .codehilite .no { color: #FAF8F5 } /* Name.Constant */
187
+ .codehilite .nd { color: #D4896A } /* Name.Decorator */
188
+ .codehilite .ni { color: #FAF8F5 } /* Name.Entity */
189
+ .codehilite .ne { color: #FAF8F5 } /* Name.Exception */
190
+ .codehilite .nf { color: #D4896A } /* Name.Function */
191
+ .codehilite .nl { color: #FAF8F5 } /* Name.Label */
192
+ .codehilite .nn { color: #FAF8F5 } /* Name.Namespace */
193
+ .codehilite .nx { color: #FAF8F5 } /* Name.Other */
194
+ .codehilite .py { color: #FAF8F5 } /* Name.Property */
195
+ .codehilite .nt { color: #C9754A } /* Name.Tag */
196
+ .codehilite .nv { color: #FAF8F5 } /* Name.Variable */
197
+ .codehilite .ow { color: #C9754A } /* Operator.Word */
198
+ .codehilite .pm { color: #BFB9B1 } /* Punctuation.Marker */
199
+ .codehilite .w { color: #FAF8F5 } /* Text.Whitespace */
200
+ .codehilite .mb { color: #B8976C } /* Literal.Number.Bin */
201
+ .codehilite .mf { color: #B8976C } /* Literal.Number.Float */
202
+ .codehilite .mh { color: #B8976C } /* Literal.Number.Hex */
203
+ .codehilite .mi { color: #B8976C } /* Literal.Number.Integer */
204
+ .codehilite .mo { color: #B8976C } /* Literal.Number.Oct */
205
+ .codehilite .sa { color: #34D399 } /* Literal.String.Affix */
206
+ .codehilite .sb { color: #34D399 } /* Literal.String.Backtick */
207
+ .codehilite .sc { color: #34D399 } /* Literal.String.Char */
208
+ .codehilite .dl { color: #34D399 } /* Literal.String.Delimiter */
209
+ .codehilite .sd { color: #34D399 } /* Literal.String.Doc */
210
+ .codehilite .s2 { color: #34D399 } /* Literal.String.Double */
211
+ .codehilite .se { color: #34D399 } /* Literal.String.Escape */
212
+ .codehilite .sh { color: #34D399 } /* Literal.String.Heredoc */
213
+ .codehilite .si { color: #34D399 } /* Literal.String.Interpol */
214
+ .codehilite .sx { color: #34D399 } /* Literal.String.Other */
215
+ .codehilite .sr { color: #34D399 } /* Literal.String.Regex */
216
+ .codehilite .s1 { color: #34D399 } /* Literal.String.Single */
217
+ .codehilite .ss { color: #34D399 } /* Literal.String.Symbol */
218
+ .codehilite .bp { color: #B8976C } /* Name.Builtin.Pseudo */
219
+ .codehilite .fm { color: #D4896A } /* Name.Function.Magic */
220
+ .codehilite .vc { color: #FAF8F5 } /* Name.Variable.Class */
221
+ .codehilite .vg { color: #FAF8F5 } /* Name.Variable.Global */
222
+ .codehilite .vi { color: #FAF8F5 } /* Name.Variable.Instance */
223
+ .codehilite .vm { color: #FAF8F5 } /* Name.Variable.Magic */
224
+ .codehilite .il { color: #B8976C } /* Literal.Number.Integer.Long */
studio/guide/img/auto-chose-photo.webp ADDED
studio/guide/img/batch.webp ADDED
studio/guide/img/chooser.webp ADDED
studio/guide/img/detail-certainty.webp ADDED
studio/guide/img/export.webp ADDED
studio/guide/img/fabricate-htv-rail.webp ADDED
studio/guide/img/fabricate-laser-rail.webp ADDED
studio/guide/img/fabricate-vinyl.webp ADDED
studio/guide/img/first-run.webp ADDED
studio/guide/img/help.webp ADDED
studio/guide/img/minify.webp ADDED
studio/guide/img/overlays.webp ADDED
studio/guide/img/palette.webp ADDED
studio/guide/img/result.webp ADDED
studio/guide/img/settings.webp ADDED