From 4ef35365ab0659d894fbf2934dd11c5525512721 Mon Sep 17 00:00:00 2001 From: Victor Sandu Date: Sat, 12 Sep 2026 09:00:22 +0300 Subject: [PATCH 1/6] docs: expand illustrated feature guides and navigation --- CHANGELOG.md | 6 + docs/audits/2d-feature-coverage.md | 65 +++++ docs/audits/3d-feature-coverage.md | 115 ++++++++ docs/audits/calibration-feature-coverage.md | 119 +++++++++ docs/audits/feature-documentation.md | 72 +++++ package.json | 2 + playwright.docs.config.ts | 15 ++ scripts/generate-docs-seo-pages.mjs | 93 +++++-- scripts/verify-doc-illustrations.mjs | 73 +++++ .../diagrams/06_frontlit_hiding_distance.svg | 88 ++----- src/assets/diagrams/07_calibration_wedge.svg | 91 ++----- src/assets/diagrams/08_opacity_solve.svg | 69 ++--- src/assets/diagrams/09_palette_proof.svg | 89 ++----- src/assets/diagrams/10_physical_size.svg | 1 + src/assets/diagrams/11_manual_layers.svg | 1 + src/assets/diagrams/12_smooth_boundaries.svg | 1 + src/assets/diagrams/13_printable_detail.svg | 58 ++++ src/assets/diagrams/14_repeats_separation.svg | 1 + src/assets/diagrams/15_transition_height.svg | 1 + src/assets/diagrams/16_height_dithering.svg | 1 + .../diagrams/17_flat_paint_orientation.svg | 1 + src/assets/diagrams/18_optimizer_choices.svg | 1 + src/assets/diagrams/19_preview_only.svg | 1 + .../diagrams/20_calibration_choices.svg | 52 ++++ src/assets/diagrams/21_proof_rounds.svg | 37 +++ src/assets/diagrams/22_matrix_alignment.svg | 58 ++++ src/assets/diagrams/23_calibration_scope.svg | 42 +++ src/assets/diagrams/30_crop_resize_scale.svg | 5 + src/assets/diagrams/31_pixel_tools.svg | 5 + .../diagrams/32_adjustment_controls.svg | 5 + src/assets/diagrams/33_adjustment_bake.svg | 5 + .../diagrams/34_quantization_pipeline.svg | 5 + src/assets/diagrams/35_swatch_operations.svg | 5 + src/assets/diagrams/36_dedither_neighbors.svg | 5 + .../diagrams/40_build_export_snapshot.svg | 22 ++ src/assets/diagrams/41_swap_layers.svg | 17 ++ src/components/docs/DocsPage.tsx | 249 +++++++++++------- src/components/docs/MarkdownRenderer.tsx | 22 +- src/docs/3d-mode.md | 233 ++++++---------- src/docs/assets.ts | 19 +- src/docs/auto-paint.md | 196 ++++++++++++++ src/docs/calibration-theory.md | 2 +- src/docs/calibration-workflows.md | 218 +++++++++++++++ src/docs/dedithering-cleanup.md | 57 ++-- src/docs/faq.md | 20 +- src/docs/flat-paint.md | 70 +++++ src/docs/generating-exporting-output.md | 26 +- src/docs/image-adjustments.md | 67 +++++ src/docs/loading-images.md | 87 ++++-- src/docs/overview.md | 26 +- src/docs/quick-start.md | 8 +- src/docs/reducing-colors.md | 115 ++++---- src/docs/settings-and-controls.md | 30 ++- src/docs/troubleshooting.md | 30 ++- tests/docsContent.test.ts | 77 ++++++ tests/e2e/docs.spec.ts | 135 ++++++++++ 56 files changed, 2261 insertions(+), 653 deletions(-) create mode 100644 docs/audits/2d-feature-coverage.md create mode 100644 docs/audits/3d-feature-coverage.md create mode 100644 docs/audits/calibration-feature-coverage.md create mode 100644 docs/audits/feature-documentation.md create mode 100644 playwright.docs.config.ts create mode 100644 scripts/verify-doc-illustrations.mjs create mode 100644 src/assets/diagrams/10_physical_size.svg create mode 100644 src/assets/diagrams/11_manual_layers.svg create mode 100644 src/assets/diagrams/12_smooth_boundaries.svg create mode 100644 src/assets/diagrams/13_printable_detail.svg create mode 100644 src/assets/diagrams/14_repeats_separation.svg create mode 100644 src/assets/diagrams/15_transition_height.svg create mode 100644 src/assets/diagrams/16_height_dithering.svg create mode 100644 src/assets/diagrams/17_flat_paint_orientation.svg create mode 100644 src/assets/diagrams/18_optimizer_choices.svg create mode 100644 src/assets/diagrams/19_preview_only.svg create mode 100644 src/assets/diagrams/20_calibration_choices.svg create mode 100644 src/assets/diagrams/21_proof_rounds.svg create mode 100644 src/assets/diagrams/22_matrix_alignment.svg create mode 100644 src/assets/diagrams/23_calibration_scope.svg create mode 100644 src/assets/diagrams/30_crop_resize_scale.svg create mode 100644 src/assets/diagrams/31_pixel_tools.svg create mode 100644 src/assets/diagrams/32_adjustment_controls.svg create mode 100644 src/assets/diagrams/33_adjustment_bake.svg create mode 100644 src/assets/diagrams/34_quantization_pipeline.svg create mode 100644 src/assets/diagrams/35_swatch_operations.svg create mode 100644 src/assets/diagrams/36_dedither_neighbors.svg create mode 100644 src/assets/diagrams/40_build_export_snapshot.svg create mode 100644 src/assets/diagrams/41_swap_layers.svg create mode 100644 src/docs/auto-paint.md create mode 100644 src/docs/calibration-workflows.md create mode 100644 src/docs/flat-paint.md create mode 100644 src/docs/image-adjustments.md create mode 100644 tests/docsContent.test.ts create mode 100644 tests/e2e/docs.spec.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 2908e32d..f8f2365d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to Kromacut are documented in this file. +## Unreleased + +### Added + +- **Illustrated feature guides** - Expanded the 3D and 2D documentation with control-by-control explanations, physical layer and color examples, calibration workflows, and full-size vector illustrations. The guides distinguish preview-only controls from image and geometry edits, describe settings that interact, and explain what must match the slicer. Mobile navigation collapses to leave room for reading. Documentation checks cover navigation, image assets, and responsive rendering. + ## v4.0.0 - 2026-09-10 ### Upgrade notes diff --git a/docs/audits/2d-feature-coverage.md b/docs/audits/2d-feature-coverage.md new file mode 100644 index 00000000..f58adccd --- /dev/null +++ b/docs/audits/2d-feature-coverage.md @@ -0,0 +1,65 @@ +# 2D feature documentation audit + +Scope: current develop UI and source, inspected 2026-09-12. Covers all nontrivial 2D fields, toggles, image actions, and their downstream print effects. Source references identify the behavior used for documentation; illustrations are schematic explanations, not measured print predictions. + +## Coverage inventory + +| Feature and controls | Authoritative source | Documentation | Illustration | +| --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ----------------------------------------------- | +| Choose file; image MIME validation; first file on drop; 2D-only drop; default logo | `src/App.tsx:521`, `src/hooks/useDropzone.ts:13` | `loading-images#choose-a-source` | Context diagram 30 | +| Wheel zoom around pointer; left pan; middle pan while editing; crisp nearest-neighbor display | `src/components/CanvasPreview.tsx:204`, `:479`, `:957` | `loading-images#inspect-without-changing-the-image` | 30 distinguishes view vs data vs physical scale | +| Checkerboard background; Image/Crop pixel-size badge | `src/components/PreviewActions.tsx:426`, `src/components/CanvasPreview.tsx:1304`, `:1406` | `loading-images#inspect-without-changing-the-image` | 31, 35 show alpha checkerboard | +| Crop; rectangle move; corner/edge resize; Save crop; Cancel crop; source-pixel output | `src/components/CanvasPreview.tsx:1021`, `:1185`, `src/App.tsx:978` | `loading-images#crop` | 30 | +| Resize Scale 1–100%, default50; current/after dimensions; Apply; reset; downscale-only; repeated resampling | `src/components/ImageResizePanel.tsx:32`, `src/lib/imageResize.ts:1`, `src/App.tsx:541` | `loading-images#resize-image` | 30 | +| Resize smoothing introduces colors/alpha; distinction from Pixel Size and full opaque physical width | `src/App.tsx:575`, `src/hooks/useSwatches.ts:174` | `loading-images#physical-size-in-3d` | 30 | +| Brush; hard-edge circular footprint; size1–64 imagepx; opaque paint; one changed stroke/historystep | `src/components/PreviewActions.tsx:554`, `src/lib/touchup.ts:41`, `src/components/CanvasPreview.tsx:846` | `loading-images#touch-up-pixels` | 31 | +| Eraser; same brushsize; canonical alpha0 pixels; physical holes/disconnections | `src/components/CanvasPreview.tsx:846`, `src/lib/touchup.ts:96` | `loading-images#touch-up-pixels` | 31 | +| Fill; exact RGBA; four-connected floodfill; one region vs global swatch | `src/components/CanvasPreview.tsx:872`, `src/lib/touchup.ts:138` | `loading-images#touch-up-pixels` | 31, 35 | +| Picker; nontransparent source RGB; switches to Brush | `src/components/CanvasPreview.tsx:866`, `src/App.tsx:872` | `loading-images#touch-up-pixels` | 31 context | +| Tool color picker; imagepalette chips; six-digithex; popover-close commit; session-only toolsettings | `src/components/PreviewActions.tsx:473`, `src/App.tsx:287` | `loading-images#touch-up-pixels` | 31 | +| Text; size6–128px; multilines; wrap; move/resizehandles; livecolor/size; Apply/CtrlEnter/MetaEnter; discard/Escape; click-away/tool-switchcommit; rasterization | `src/components/PreviewActions.tsx:575`, `src/components/CanvasPreview.tsx:521`, `:702`, `:786`, `:885`, `:1330`, `src/lib/touchup.ts:208` | `loading-images#place-text` | 31 | +| Flat background removal through global alpha0 vs local eraser; no automatic AI removal | UI inventory `src/App.tsx:670`, `src/components/PreviewActions.tsx:156`; swatch `src/hooks/useAppHandlers.ts:316` | `loading-images#remove-a-background` | 35 | +| Undo/Redo image commits vs settings; new edit clears redo; session-onlyhistory; Remove image is not new historyentry | `src/hooks/useImageHistory.ts:42`, `:64`, `:85`, `:106`, `src/App.tsx:535` | `loading-images#undo-download-and-clear` | 33 explains live vs committed | +| PNG Download underlying full-resolution pixels; excludes overlays/unbakedadjustments; desktop save vs browserdownload | `src/components/CanvasPreview.tsx:1230`, `src/hooks/useAppHandlers.ts:111`, `src/hooks/saveBlobToFile.ts:33` | `loading-images#undo-download-and-clear` | 33 | +| Exposure ±3stops step.01; Contrast ±100; Highlights ±100; Shadows ±100; Whites ±100; Blacks ±100 | `src/components/sliderDefs.ts:12`, `src/lib/applyAdjustments.ts:144`, `:184`, `:251` | `image-adjustments#tone` | 32 all six explicitly | +| Saturation ±100; Vibrance ±100; Hue ±180deg; Temperature ±100 notKelvin; Tint ±100; Clarity ±100 | `src/components/sliderDefs.ts:68`, `src/lib/applyAdjustments.ts:198`, `:219`, `:275` | `image-adjustments#color-and-local-detail` | 32 all six explicitly | +| Adjustments preview oncommit; individualreset; allreset; Apply bake and zero sliders; Undo after bake | `src/components/AdjustmentsPanel.tsx:83`, `:108`, `:124`, `src/App.tsx:679`, `:687` | `image-adjustments#preview-versus-apply`, `#reset-and-undo-are-different` | 33 | +| Source vs adjusted pipeline for quantize/download/resize/3D vs Dedither; alphaunchanged by adjustment | `src/components/CanvasPreview.tsx:1230`, `:1252`, `src/hooks/useQuantize.ts:131`, `src/components/DeditherPanel.tsx:51`, `src/components/ThreeDView.tsx:866` | `image-adjustments#preview-versus-apply` | 33 | +| Palette Auto vs fixed; NumberofColors2–256 default16; fixedpalette disablescount; Weight2–256 default128; Apply; Reset | `src/components/ControlsPanel.tsx:99`, `:303`, `:336`, `src/App.tsx:739`, `:778` | `reducing-colors#the-two-stage-pipeline` | 34 | +| None postprocessonly (Weightdisabled); Posterize; Median-cut; K-means/randominit; Wu; Octree; intermediatepalette semantics | `src/hooks/useQuantize.ts:174`, `src/lib/algorithms.ts:95`, `:182`, `:326`, `:479`, `:645` | `reducing-colors#choose-an-algorithm` | 34 names methods and stages | +| Final upperlimit not guaranteedexactcount; fixedpalette Labmapping; partialalpha becomes255; alpha0stays0 | `src/hooks/useQuantize.ts:162`, `:208`, `src/lib/algorithms.ts:1232`, `:1362` | `reducing-colors#the-two-stage-pipeline`, `#fixed-and-supplier-palettes` | 34 | +| Supplier palettes unofficial, immutable; hexes not printcalibration; clone tocustom | `src/components/ControlsPanel.tsx:189`, `src/data/supplierFilaments.ts`, `src/hooks/usePaletteManager.ts:138` | `reducing-colors#fixed-and-supplier-palettes` | 34 fixedpalette branch | +| Palette create/name; edit; add; picker/hex#RGB/#RRGGBB; optionalcolorname; enable/disable; removerow; Save/Cancel; onevalidenabledrequired | `src/components/PaletteManager.tsx:46`, `:109`, `:279`, `:392`, `:437` | `reducing-colors#custom-palettes` | 34 enabled-color consequence | +| Clone built-in/custom; import .kpal summary; export; delete; localpersistence; enabled/totalcount; disabled/name preservation | `src/hooks/usePaletteManager.ts:25`, `:138`, `:183`, `:203`, `:221` | `reducing-colors#custom-palettes` | 34 fixedpalette consequence | +| Image colors count excludingtransparent; hex/alpha/pixelcounttooltip; bounded list; alpha-identicalmatch; picker;6digitretainscurrentalpha;8digitalpha | `src/hooks/useSwatches.ts:27`, `:123`, `src/components/SwatchesPanel.tsx:63`, `:115`, `:190`, `:267` | `reducing-colors#image-colors` | 35 | +| Swatch Apply global exactRGB/alpha; transparentbucket replacement; alpha0 deletion; Delete requantizes remainingpalette with activealgorithm; Close/Escape | `src/hooks/useAppHandlers.ts:296`, `:316`, `src/components/SwatchesPanel.tsx:132` | `reducing-colors#image-colors` | 35 | +| Dedither exact8neighborRGBA; Weight1–9 default4; Passes1–10 default1; resets; Apply; sequentialpasses; randomties; alpha/silhouettechange | `src/components/DeditherPanel.tsx:30`, `:75`, `:103`, `:132`, `:156`, `:248` | `dedithering-cleanup` allsections | 36 | +| Dedither distinct from quantize, photonoisereduction, nozzle simulation, and 3D heightdither | Sourcealgorithmabove and `src/lib/printableFeatures.ts` | `dedithering-cleanup#effect-on-the-print`, `#dedither-versus-height-dithering` | 36 and crosslink3D | + +## Important corrections made + +- Download, quantization, resize, and 3D do not automatically consume the live adjustment preview. Bake first. +- Six-digit swatch hex input preserves the current alpha; explicit eight-digit alpha or the picker controls opacity. +- Swatch Delete is requantization, not erasure. It can change other colors because the selected algorithm still runs. +- Weight is an intermediate palette budget, not generic grouping strength. +- Number of Colors is an upper limit and cannot restore earlier discarded colors. +- Resize resamples and may introduce new colors/alpha; changing XY scale alone does not reduce workload. +- Remove image is not a reliably undoable new clear-state history entry. +- Dedither can precede or follow quantization depending on exact source patterns. It is not restricted to post-quantization. +- Dedither Weight9 has only8neighbors, alpha participates, and tied alternatives are random. + +## Owned deliverables + +- Rewritten `src/docs/loading-images.md` +- New `src/docs/image-adjustments.md` (order35) +- Rewritten `src/docs/reducing-colors.md` +- Rewritten `src/docs/dedithering-cleanup.md` +- Seven accessible SVG assets `30_crop_resize_scale.svg` through `36_dedither_neighbors.svg`, each 960×540, explanatory title/description and 18pxminimum labels. + +## Local verification + +- Rendered all seven SVGs in headless Chromium with the installed Playwright dependency. +- Inspected contact sheet and fixed a label/image overlap and one panel-overflow label. +- Checked text bounding boxes against each viewBox and containing panel: no remaining overflow in the seven SVGs. +- Local inspection outputs: `tmp/docs-2d-illustrations.png`, `tmp/30_crop_resize_scale.png` through `tmp/36_dedither_neighbors.png`; helper `tmp/qa-docs-2d.cjs`. These are temporary review artifacts, not published docs assets. +- Root owns cross-page navigation, docs rendering/integration tests, build, and final full-page visual QA. diff --git a/docs/audits/3d-feature-coverage.md b/docs/audits/3d-feature-coverage.md new file mode 100644 index 00000000..11e4977f --- /dev/null +++ b/docs/audits/3d-feature-coverage.md @@ -0,0 +1,115 @@ +# 3D Feature Documentation Audit + +Audited on develop, 2026-09-12. Source code, not previous prose, is authoritative. This is an authoring inventory, not a user-facing guide or a claim that physical print predictions are verified. Calibration-dialog controls are inventoried separately. Root-owned export/global documentation and tests complete the cross-page checks. + +## Source Review And Corrections + +- `App.tsx:274,969-977` wires toolbar Undo/Redo to `useImageHistory`. `src/hooks/useImageHistory.ts:3,53,74` confirms image snapshots only. Old docs incorrectly described 3D-settings undo; the new guide explicitly excludes it. +- `src/hooks/useColorSlicing.ts:54-81,144-217` proves layer-height edits reset manual thicknesses, first-layer edits reset the first run, and order changes resnap first/later runs. Old prose omitted these consequential effects. +- `src/components/ThreeDControls.tsx:346` excludes saved profile appearance evidence while the working set is dirty. `FilamentRow.tsx:108-128,241-248` clears HD calibration on manual HD/TD conversion/wand; `src/lib/filamentUpdates.ts:9-31` preserves but deactivates calibration on color edits and can reactivate on revert. New docs distinguish these behaviors. +- `src/lib/autoPaint.ts:3175-3205` uses effective-filament dark-to-light luminance sorting when Enhanced matching is off, not row order. Newly documented. +- Independent review verified the second half of standard matching in `src/components/ThreeDView.tsx:1451-1503`: normalized source-image luminance maps between foundation and stack top, then snaps to the print grid. Equal-brightness hues can share a height. The Standard Matching section now distinguishes this from enhanced color-aware assignment, not just enhanced order search. +- Independent review verified `src/lib/autoPaint.ts:2673` returns an already-discrete palette height and `ThreeDView.tsx:1168-1201` reuses those cached target mappings. Height dithering only redistributes fractional-height error where it is present; many mapped regions may remain unchanged. The guide and diagram16 now explicitly present a conditional mechanism rather than a guaranteed visible before/after. +- `ThreeDControls.tsx:366-401` computes Flat Paint slab depth separately from normal appearance-stack height, including a carrier in the default layout. New docs do not call Max Height a carrier-inclusive slab cap. +- `ThreeDControls.tsx:417-447` uses the built snapshot for print instructions; `src/hooks/useAppHandlers.ts:128-182,187-280` exports the built mesh. Old docs underexplained how unapplied sidebar settings differ from built geometry. +- `AutoPaintTab.tsx:1673-1768` contains the entirely undocumented Suggest next filament workflow, including hypothetical HD and three independent metrics. New guide includes it. + +## Common Build, Dimensions, Manual Controls + +| Feature or control | Verified source and conditions | Documentation and visual coverage | +| ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | +| Build 3D Model | `ThreeDControls.tsx:452-574`: explicit apply; Auto-paint blocked while computing, when error exists, or when simulation/result/slice-grid mapping absent. Old preview can remain. | `3d-mode` introduction and Layer Preview; export workflow; root diagram 40. | +| Computing percentage / Waiting / Failed | `ThreeDControls.tsx:557-586`; `AutoPaintTab.tsx:939-978`. Printable-detail analysis precedes optimization; current computation shown; no manual fallback. | `auto-paint#enhanced-color-matching`; core last section. | +| Performance warning, Build Anyway, cancel | `useBuildWarning.ts:4-6,124-174`: >64 generated runs, >2.5M image pixels, >32 Flat Paint layers, or Flat Paint with dithering. Confirmation applies pending state; cancel does not build. | Root `generating-exporting-output`; `flat-paint#cost-and-detail-tradeoffs`. | +| Pixel Size XY | `PrintSettingsCard.tsx:112-115,151-185`: valid 0.01-10 mm/pixel; text draft permits comma decimal; valid values commit while typing, bounded on blur. | `3d-mode#pixel-size-is-not-nozzle-size`; diagram 10. | +| Model dimensions badge | `ThreeDControls.tsx:366-416`: nontransparent bounds times pixel size; no Auto-paint estimate until current slice data ready; flat depth distinct. | Core XY section; Flat Paint carrier caveat; diagram 10. | +| Layer Height | `PrintSettingsCard.tsx:116-119,194-220`: 0.01-10 mm; `useColorSlicing.ts:54-64` resets heights; later reconciliation makes first minimum valid. | Core layer-boundary section; diagram 11; root 41. | +| First Layer Height | `PrintSettingsCard.tsx:120-128,225-253`: 0-10 input range, physical minimum reconciled against regular height. `useColorSlicing.ts:67-81` resets first color. | Core layer-boundary section and manual example; diagram 11. | +| Smooth Meshing | `PrintSettingsCard.tsx:256-272`; `ThreeDControls.tsx:209-221`: flat active forces effective false; enabling smooth disables flat. `ThreeDView.tsx:1737,1919` selects actual smooth versus greedy geometry. | `3d-mode#smooth-meshing`; diagram 12; Flat Paint comparison. | +| Print settings Reset / disabled state / dirty indicator | `PrintSettingsCard.tsx:133-147`; `ThreeDControls.tsx:296-306`; `printSettingsStorage.ts:7-25`: defaults .1/.12/.2/off, no-op reset disabled when all default; manual thicknesses reset preserving order. | Core settings table and manual reset distinction. | +| Manual / Auto-paint tabs | `ThreeDControls.tsx:615-627`: separate modes; retained tab content; Flat Paint effective only Auto-paint. | Core intro and links to dedicated guides. | +| Manual row drag | `ThreeDColorRow.tsx:45-55`; `useColorSlicing.ts:185-217`: physical sequence, first-row minimum/resnap. | `3d-mode#reorder-colors`; diagram 11. | +| Manual thickness slider | `ThreeDColorRow.tsx:28-35,69-80`: local preview while dragging, commit on release; step regular layer, max 10; first min max(regular,first). | Core adjust/reset section and cumulative example; diagram 11. | +| Thickness readout | `ThreeDColorRow.tsx:85-87`: row thickness, two decimals. `ThreeDView.tsx:1804-1811,1886-1900`: cumulative stack and earlier-layer support. | Core manual explanation; diagram 11 labeled run thickness versus top height. | +| Manual reset | `useColorSlicing.ts:144-162,227-246`: dark-to-light luminance order plus minima; disabled when already matches. | Core manual reset section. | +| Manual >64 colors | `ThreeDControls.tsx:751-763`; `PrintInstructions.tsx:166-172`: rows/instructions replaced with reduce-color warning, Copy disabled. | Core Manual and root export guide. | +| Transparent regions | `useColorSlicing.ts:20-22`; `ThreeDView.tsx:1839-1845`: alpha zero skipped, disconnected opaque regions not automatically connected. | Core manual final paragraph and source-image/XY sections. | + +## Filaments And Profiles + +| Control | Source / availability / side effect | Documentation | +| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------- | +| Add Filament | `AutoPaintTab.tsx:848-860`; `useFilaments.ts:14-25`: adds gray with estimated HD. No implicit printer-slot assignment. | `auto-paint#filament-inputs`. | +| Color swatch, picker, Hex | `FilamentRow.tsx:144-163,87-95`; `filamentUpdates.ts:9-31`: debounced optical color edit; calibration inactive if mismatch, measured scalar restores on matching revert. | Inputs and calibration-edit paragraph; established frontlit diagram 06 linked through calibration. | +| Name / blank / Enter | `FilamentRow.tsx:97-105,168-176`: trim on blur, Enter blurs, blank uses autogenerated name. | Inputs table. | +| HD numeric / bounds | `FilamentRow.tsx:19-20,108-116,178-194`: .01-2, invalid returns previous, clears calibration when committed. | Inputs table and side-effect warning. | +| Convert TD popover / value / Convert / Enter | `FilamentRow.tsx:119-129,199-236`: positive conventional value, x.1 rounded .01 clamped .01-2, clears calibration. | Inputs table. | +| Wand | `FilamentRow.tsx:239-252`: estimate from current color, clears calibration. | Inputs table and warning. | +| Calibration badge and RGB tooltip | `FilamentRow.tsx:42-60,254-271`: only active measured color counts as calibrated; otherwise Estimate. | Inputs table and confidence distinctions. | +| Remove filament | `FilamentRow.tsx:274-283`; `useFilaments.ts:36-38`. | Inputs table. | +| Calibrate | `AutoPaintTab.tsx:862-873`: appears with at least one filament; opens dialog. | Inputs table; calibration-workflows owns detailed tabs. | +| Profile dropdown, Templates | `AutoPaintTab.tsx:588-655`; supplied template IDs read-only. | `auto-paint#filament-profiles` and Templates. | +| Save current | `AutoPaintTab.tsx:660-678`: disabled without active editable dirty profile. | Profiles action table. | +| Save new popover / name / Enter / Save | `AutoPaintTab.tsx:680-712`: nonempty trimmed name required. | Profiles table. | +| Rename popover / name / Enter / Rename | `AutoPaintTab.tsx:716-758`: active non-template only, nonempty name. | Profiles table. | +| Import file | `AutoPaintTab.tsx:761-780`: .kfil/.kapp/.json/.csv/.tsv. `useProfileManager.ts` owns duplicate/storage policy. | Profiles table; root `settings-and-controls` retains import specifics. | +| Export file / disabled empty | `AutoPaintTab.tsx:782-791`: disabled without filaments; file save and dirty-evidence behavior delegated to profile manager. | Profiles table; root import/export page. | +| Delete profile | `AutoPaintTab.tsx:797-810`: selected editable profile only; no template deletion. | Profiles table. | +| Unsaved profile indicator and evidence | `AutoPaintTab.tsx:570-582`; `ThreeDControls.tsx:346-349`: dirty profile appearance omitted from optimizer. | Profiles paragraph explicitly separates individual HD calibration. | + +## Auto-paint Controls And Diagnostics + +| Control | Source and conditions | Documentation / visual | +| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | +| Standard baseline | `autoPaint.ts:3175-3205`: dark-to-light effective luminance. `ThreeDView.tsx:1451-1503`: normalized source luminance maps to heights and snaps; equal-brightness hues may share heights. | `auto-paint#standard-matching`, including distinction from enhanced color-aware assignment. | +| Max Height field / Auto / actual height | `AutoPaintTab.tsx:876-939`: nonempty >0 draft, clamp .5-20 blur, Auto clears; cap lower than auto shows compressed warning. `autoPaint.ts:3225-3249` floor valid grid and reject insufficient foundation. | `auto-paint#max-height`; diagram 15. | +| Effective line width / Reset | `AutoPaintTab.tsx:982-1026`: .1-2, .01 increment, blur/Enter commit; Reset .42. | Printable detail; diagrams 10 and 13. | +| Omit at-risk colors | `AutoPaintTab.tsx:1028-1040`; `usePrintableFeatureSimulation.ts`: supplied to preanalysis and conceal snapshot for build. | Printable detail; diagram 13. | +| Open preview / Close | `PrintableFeaturePreview.tsx:87-123,206-212`: enlarged modal, affected counts. | Printable detail. | +| At risk / Printable views | `PrintableFeaturePreview.tsx:32-69,138-165,181-204`: amber takeover and pink unsupported; latter retained if no replacement; actual passed pixels versus risk only. | Printable detail; diagram 13. | +| Enhanced matching | `AutoPaintTab.tsx:1053-1064`; `ThreeDControls.tsx:187-193`: turning off resets separation and dithering. | Enhanced matching. | +| Total repeat limit | `AutoPaintTab.tsx:1068-1110`: enhanced-only; Off/2/4/6/8/12 extra appearances shared globally. | Repeat section; diagram 14. | +| Preserve color separation | `AutoPaintTab.tsx:1114-1128`; `ThreeDControls.tsx:195-200`: enhanced-only, turning on disables dither. | Separation section; diagram 14. | +| Unique-match limit | `AutoPaintTab.tsx:1133-1170`: visible only enhanced + separation, .1 step, normalized1-100, default6, invalid draft resets. | Separation section; diagram 14. | +| Require unique every color | `AutoPaintTab.tsx:1172-1193`: visible under separation; default true; false permits unmatched source-color merging. | Separation section; diagram 14. | +| Height dithering | `AutoPaintTab.tsx:1197-1211`; `ThreeDControls.tsx:202-207`: enhanced-only, disables separation. `ThreeDView.tsx:1269-1426` block-aware spatial heights, rounded line-width/pixel-size blocks and special edge handling. `autoPaint.ts:2673` and `ThreeDView.tsx:1168-1201` can supply already-discrete cached heights, leaving no fractional-height error to redistribute. | Height Dithering explicitly notes possibly unchanged regions; diagram16 illustrates the mechanism only when fractional heights exist. | +| Flat Paint toggle / face-up child | `AutoPaintTab.tsx:1217-1254`: independent of enhanced; child disabled without flat. `ThreeDControls.tsx:209-221` forces effective smoothing off. | Dedicated Flat Paint guide; diagram17. | +| Algorithm | `AutoPaintTab.tsx:1263-1310`: enhanced-only, Fast/Balanced/Thorough/Deep/Exact base order; exact hint notes subset permutations. | Optimizer section; diagram18 includes ordered search tiers. | +| Region priority | `AutoPaintTab.tsx:1312-1340`; `useAutoPaintWorker.ts:222-249`: weights target counts based on spatial source-color statistics, enhanced UI only. | Optimizer section; diagram18 same image with three weight overlays. | +| Transition detail | `AutoPaintTab.tsx:1343-1374`: enhanced UI only; .8/.9/.95. `autoPaint.ts:489-574`: opacity endpoint capped or earlier perceptual convergence. | Optimizer table; diagram18 potential additional choices;15 compression. | +| Seed | `AutoPaintTab.tsx:1378-1413`: enhanced-only; blank automatic; integer parse, invalid resets; blur/Enter commit. | Optimizer table. | +| Transition count/bar / ranges / compressed badges | `AutoPaintTab.tsx:1421-1533`: result-only and >0zones; real run color, physical start/end/delta, hover ideal compression. | Result table; diagram15. | +| Appearance model and prediction counts | `AutoPaintTab.tsx:101-258`: model level, physical training/local/matrix counts, weighted average/minimum mapping confidence, exact/interpolated/fitted/simulated breakdown. | Result table; detailed evidence model delegated calibration guide. | +| Result Confidence + factors | `AutoPaintTab.tsx:1535-1577`: calibration, coverage, compression plus overall percentage. | Explicitly not measured accuracy. | +| Optimizer metadata | `AutoPaintTab.tsx:1578-1668`: algorithm, score or Partial palette, iterations/cache, exact/best-found, no-removable-run. | Result table and optimizer section. | +| Suggest next filament / Finding / error / none | `AutoPaintTab.tsx:1673-1768`: requires a result and source targets; disabled during request; resets on image/filament edits (`503`). | Complete new Suggest Next Filament section. | +| Suggestion hex, Est ΔE, HD, Captures, Isolation | `AutoPaintTab.tsx:1689-1738`: approximate blend-aware improvement, borrowed nearest HD, percent affected pixels,0-1 gap distinction. | Separate field-by-field table; explicitly hypothetical and not a store result. | +| Add to filaments suggestion | `AutoPaintTab.tsx:1740-1760`: generated suggestion name, add row with estimated HD, clear prior suggestion. | Suggestion section warns to own/measure real filament before print. | + +## Preview And Export Boundary + +| Feature | Source / constraint | Coverage | +| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------ | +| Orbit, pan, zoom | `useThreeScene.ts:62-64`: standard OrbitControls, damping. | Core preview intro. | +| Render mode menu and current state | `PreviewActions.tsx:184-232`: four choices, closes on selection. `ThreeDView.tsx:482-510` modifies presentation only. | Core preview table. | +| Simulated / physical | `PreviewActions.tsx:235-261`: only built Auto-paint; remembered; mesh metadata separates from export. | Core preview table; 19 preview-only diagram. | +| Orthographic / perspective | `PreviewActions.tsx:264-278`; `useThreeScene.ts:117-149`: preserves camera transform and target. | Core preview table. | +| Undo / Redo disabled history | `PreviewActions.tsx:280-299`; `App.tsx:274,969-977`: shared image history; disabled with absent history or active crop. | Core table corrects old inaccurate 3D-settings claim. | +| Layer lower/upper handles | `ThreeDView.tsx:571-614,689-695,2300-2449`: hide outside range, snap boundaries, full export unaffected. | Core layer section; diagram19. | +| Segment hovers / range labels / Flat Paint plain track | `ThreeDView.tsx:616-671,2342-2354`; no one-material-per-layer sequence for flat. | Core and Flat Paint guide. | +| Download STL/3MF and disabled build/export state | `PreviewActions.tsx:374-418`; flat hidesSTL. `useAppHandlers.ts:128-280` generated files from built mesh, save progress. | Root export guide; Flat Paint export steps. | +| Print instructions and Copy | `PrintInstructions.tsx:31-215`; `useSwapPlan.ts:37-192`; uses built settings (`ThreeDControls.tsx:417-447`). | Core snapshots warning, root export detailed layer/Z distinctions. | + +## Files Created Or Reworked + +- `src/docs/3d-mode.md`: retains all legacy section heading anchors with summaries and destination links; core/manual/preview now detailed. +- `src/docs/auto-paint.md`: full non-calibration field/control guide. +- `src/docs/flat-paint.md`: both physical layouts, object assignment, orientation and cost. +- `src/assets/diagrams/10_physical_size.svg` through `19_preview_only.svg`: ten local SVG schematics, including weighting/search/transition diagram18. Alt text, title/desc, explicit schematic captions, consistent colors and >=18px labels. + +## Validation Recorded + +- `npm run test:docs`: passed all3 tests after initial nine diagrams and calibration links corrected. Repeat after diagram18 and other agents' final edits. +- Root visually checked the final diagrams, including the explicit columns/arrows in diagram11, the conditional mechanism in diagram16, and weighting/transition choices in diagram18. Integrated verification is recorded in `feature-documentation.md`. +- No runtime implementation edits, commits, pushes, or user-file changes in this scope. +- Whole-goal completion requires root verification of 2D/calibration/global controls and public/static rendered documentation, not just this source inventory. diff --git a/docs/audits/calibration-feature-coverage.md b/docs/audits/calibration-feature-coverage.md new file mode 100644 index 00000000..6d8130de --- /dev/null +++ b/docs/audits/calibration-feature-coverage.md @@ -0,0 +1,119 @@ +# Calibration And Profile Documentation Coverage + +Audited against the working tree on 2026-09-12. Scope: filament rows and named profiles, the three Calibrate tabs, appearance-evidence compatibility, and confidence interpretation. Other agents audit the surrounding 3D and 2D features. This inventory is evidence for documentation completeness, not proof of physical printing accuracy. + +Primary practical guide: `src/docs/calibration-workflows.md` (slug `calibration-workflows`, order 65). Deep model reference: `src/docs/calibration-theory.md`. Diagram references below are filenames under `src/assets/diagrams/`. + +## Filament Rows And Profile Ownership + +| Feature / action | Authoritative implementation | Practical documentation | Illustration / reason for text | +| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- | +| Swatch picker / Hex | `FilamentRow.tsx:141`; `filamentUpdates.ts:10`; `calibration.ts:366` | Prepare And Protect Your Filament Profile: row table | 06 shows the physical nominal-color/base relationship. Color edits deactivate rather than silently reuse a mismatched wedge record. | +| Editable name | `FilamentRow.tsx:97` | Row table; named-profile dirty-state guidance | Text: identity label only; no optical diagram needed. | +| Manual HD and limits 0.01–2 mm | `FilamentRow.tsx:19`; `FilamentRow.tsx:108` | Row table | 06: greater thickness reduces show-through; states manual entry clears calibration. | +| Conventional TD conversion | `FilamentRow.tsx:119` | Row table; link to file-format guide | 06 distinguishes input scales; multiplying by 0.1 is a Kromacut conversion, not an independent measurement. | +| Wand estimate | `FilamentRow.tsx:240` | Row table | 06 plus explicit estimate/replacement warning. | +| Estimate / measured badge, RGB HD tooltip | `FilamentRow.tsx:42`; `FilamentRow.tsx:255` | Row table and Read Confidence Without Overclaiming Accuracy | 20 separates opacity evidence from recipe evidence. | +| Add / remove filament | `AutoPaintTab.tsx:836`; `AutoPaintTab.tsx:853`; `FilamentRow.tsx:272` | Row table | 23 explains why changing a material set can change empirical compatibility. | +| Select saved profile | `useProfileManager.ts:155` | Profile-toolbar list | Text: replaces the working list, so save edits first. | +| Save selected / overwrite | `useProfileManager.ts:121`; `profileManager.ts:314` | Profile-toolbar list and dirty-state paragraph | 23 for compatibility. Records generally retained, not falsely documented as erased by every overwrite. | +| Save as new, name field | `useProfileManager.ts:95`; `profileManager.ts:279` | Profile-toolbar list | Copies filament rows including wedge calibration, not old appearance history. | +| Rename, name field | `useProfileManager.ts:134` | Profile-toolbar list | Text: label change only. | +| Import/export, dirty export, desktop cancellation | `useProfileManager.ts:195`; `profileManager.ts:292`; `profileManager.ts:667` | Profile-toolbar list and dirty-state paragraph; links to Settings And Controls | Actual current output is `.kfil`, despite older AGENTS wording. Dirty export creates a separate evidence-free appearance profile. | +| Delete profile | `useProfileManager.ts:171` | Profile-toolbar list | Text: backup warning; saved profile and evidence removed. | +| Templates / read-only actions | `AutoPaintTab.tsx:625`; `useProfileManager.ts:157` | Profile introduction, read-only copy guidance | Text: estimated HD, not measured supplier data. | +| Unsaved changes and storage failures | `useProfileManager.ts:84`; `useProfileManager.ts:44`; `StackMatrixCalibrationPanel.tsx:1864`; `PaletteProofPanel.tsx:1147` | Save-before-tracking instructions and matrix storage warning | 23 shows evidence tied to a compatible configuration. | + +## Hiding Distance Wizard + +| Feature / action | Authoritative implementation | Practical documentation | Illustration | +| ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | ---------------------------------------------------------------------------------------- | +| Tab selection / How calibration works | `FilamentCalibrationDialog.tsx:753`; `FilamentCalibrationDialog.tsx:1454` | Guide introduction and theory links | 20 tool comparison. | +| Individual selection, Select all / Deselect all | `FilamentCalibrationDialog.tsx:469`; `FilamentCalibrationDialog.tsx:777` | Hiding Distance step 1 | 20 wedge path; simple selection explained in text. | +| Quick | `FilamentCalibrationDialog.tsx:251`; `FilamentCalibrationDialog.tsx:337`; `FilamentCalibrationDialog.tsx:873` | Hiding Distance step 1 | 06/08 plus explicit one-base/scalar interpretation. | +| Accurate, bases, recommendation reset, max 3 bases | `FilamentCalibrationDialog.tsx:129`; `FilamentCalibrationDialog.tsx:251`; `FilamentCalibrationDialog.tsx:337`; `FilamentCalibrationDialog.tsx:884` | Hiding Distance step 1 | 08 substrate contrast; no claim that 2–3 reads directly measure three spectral channels. | +| Layer height 0.04–0.40 | `FilamentCalibrationDialog.tsx:359`; `FilamentCalibrationDialog.tsx:975` | Wedge print-control table | 07 side view, each rise is one layer. | +| Max layers 4–40 | `FilamentCalibrationDialog.tsx:127`; `FilamentCalibrationDialog.tsx:369`; `FilamentCalibrationDialog.tsx:994` | Wedge print-control table | 07 last patch/Max label. | +| STL / 3MF format | `FilamentCalibrationDialog.tsx:484`; `FilamentCalibrationDialog.tsx:1015` | Wedge print-control table | 07 cross-section over common base; full instructions in prose. | +| Download, copied plan, layer/Z swap instructions | `FilamentCalibrationDialog.tsx:484`; `FilamentCalibrationDialog.tsx:1042`; `generateCalibrationPrint.ts:98` | Wedge step 2 | 07, numbered patches explicitly differ from absolute printer-layer numbers. | +| Next / Back / Close | `FilamentCalibrationDialog.tsx:414`; `FilamentCalibrationDialog.tsx:453`; `FilamentCalibrationDialog.tsx:1094` | Wedge steps and close/reset paragraph | Text: navigation and unsaved-state consequences. | +| Match read | `FilamentCalibrationDialog.tsx:550`; `FilamentCalibrationDialog.tsx:1208` | Wedge step 3 | 07 rail comparison and 08 JND crossing. | +| Optional Merge read and warning | `FilamentCalibrationDialog.tsx:696`; `FilamentCalibrationDialog.tsx:1225`; `calibration.ts:1040` | Wedge step 3 | 07 explicitly distinguishes adjacent-patch comparison from rail comparison. | +| Predicted swatches, reference, HD/channel diagnostic display | `FilamentCalibrationDialog.tsx:1250` | Wedge step 3 | 06/08; outputs not new inputs. | +| Confidence, boundary reads, fitting diagnostics | `calibration.ts:1026`; `calibration.ts:1040`; `FilamentCalibrationDialog.tsx:1290` | Wedge step 3 and confidence section | 08 qualitative curve, no numerical data claim. | +| Session JND pending/save gate | `FilamentCalibrationDialog.tsx:598`; `FilamentCalibrationDialog.tsx:644` | Close/reset and session-fit paragraph | Text; detailed math preserved in theory. | +| Partial entry, Not entered, Won't save, ready/skipped count | `FilamentCalibrationDialog.tsx:542`; `FilamentCalibrationDialog.tsx:664`; `FilamentCalibrationDialog.tsx:683` | Wedge step 3 | Text makes per-filament all-chosen-base requirement explicit. | +| Save replacement semantics | `FilamentCalibrationDialog.tsx:688`; `FilamentCalibrationDialog.tsx:725` | Wedge save paragraph and profile backup guidance | 20 downstream effects. | + +## Palette Proof + +| Feature / action | Authoritative implementation | Practical documentation | Illustration | +| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------- | +| Prerequisite: computed stack, not artwork mesh | `AutoPaintTab.tsx:1784`; `autoPaint.ts:1101`; `PaletteProofPanel.tsx:215` | First proof paragraph | 09 prefix concept. | +| Targets, default 8, max 10 | `paletteProof.ts:16`; `PaletteProofPanel.tsx:925` | Choose Targets And Candidates table | 09 target rows. | +| Candidates 2–5 / available prefixes | `paletteProof.ts:18`; `paletteProof.ts:647`; `PaletteProofPanel.tsx:960` | Choose Targets And Candidates table | 09 candidate columns/physical stopping heights. | +| Choose from image, image clicks and keyboard color toggles | `PaletteProofPanel.tsx:615`; `PaletteProofPanel.tsx:1037` | Target table and selected-region paragraph | 21 explains resulting evidence choices. | +| Original image / Fitted-achievable | `PaletteProofPanel.tsx:553` | Target table | Explicit processed-image versus current prediction distinction; no new fit or physical guarantee. | +| Total proof targets / clear / use smart / use chosen+smart / Back | `PaletteProofPanel.tsx:531`; `PaletteProofPanel.tsx:588`; `PaletteProofPanel.tsx:624` | Target table | Text covers filling unselected slots and dropping surplus priorities. | +| Proof map, IDs, F foundation | `PaletteProofPanel.tsx:1050`; `paletteProof.ts:688` | Print And Identify The Coupon | 09 accessible two-row schematic. | +| Download, saved identity, locking, orientation, exact re-download | `PaletteProofPanel.tsx:308`; `PaletteProofPanel.tsx:821`; `paletteProof.ts:675`; `paletteProofExport.ts:128` | Print And Identify; retain original 3MF | 09 foundation/candidate physical relationship. | +| Results, ties, quality selectors, None | `PaletteProofPanel.tsx:100`; `PaletteProofPanel.tsx:1189`; `PaletteProofPanel.tsx:1366` | Record What You Actually See table | 21 different judgments and next-round branches. | +| Progress, Complete results, Edit results | `PaletteProofPanel.tsx:1170`; `PaletteProofPanel.tsx:1372` | Results paragraph | 21 follow-up after completion. | +| Saved records / target-set grouping | `PaletteProofPanel.tsx:660`; `PaletteProofPanel.tsx:887` | Results paragraph | Text; grouping is not separate physical behavior. | +| Continue targets / same image and process / None exploration | `PaletteProofPanel.tsx:772`; `PaletteProofPanel.tsx:1390`; `paletteProof.ts:402` | Follow-up action list | 21. | +| New targets / history priority | `PaletteProofPanel.tsx:1410`; `paletteProof.ts:245` | Follow-up action list | 21. | +| Reduced candidates / exhausted targets | `PaletteProofPanel.tsx:992`; `paletteProof.ts:667` | Follow-up action list | 21 footer; no unrelated filler promises. | +| Delete proof and confirmation | `PaletteProofPanel.tsx:845`; `PaletteProofPanel.tsx:859` | Follow-up action list | Text: explicit removal of evidence. | +| Global fit gates vs local evidence | `appearanceModel.ts:74`; `appearanceModel.ts:1180`; `calibration-theory.md` | End of proof workflow, confidence section, deep theory | 20 and 21 distinguish evidence strength. | + +## Stack Matrix + +| Feature / action | Authoritative implementation | Practical documentation | Illustration | +| ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | +| Saved dropdown / New matrix / Back to saved | `StackMatrixCalibrationPanel.tsx:1307`; `StackMatrixCalibrationPanel.tsx:1850` | Plan intro and closing action paragraph | Text: record ownership/navigation. | +| Filaments, 2–8, profile order | `StackMatrixCalibrationPanel.tsx:451`; `StackMatrixCalibrationPanel.tsx:458`; `StackMatrixCalibrationPanel.tsx:1877` | Plan controls | 20 grid path. | +| Recipe layers 3–6 | `StackMatrixCalibrationPanel.tsx:1913`; `stackMatrixCalibration.ts:277` | Plan controls / N^L explanation | 23 shows fixed layer counts and physical thickness. | +| Maximum cells exact choices / board footprint | `StackMatrixCalibrationPanel.tsx:116`; `StackMatrixCalibrationPanel.tsx:439`; `stackMatrixCalibration.ts:32` | Plan controls / 170 mm example | 22 grid and marker border. | +| Opaque backing, lightest selected default | `StackMatrixCalibrationPanel.tsx:430`; `StackMatrixCalibrationPanel.tsx:1951` | Plan controls | 23 backing/recipe separation. | +| New-plan regular + first LH live source; saved plan immutable | `FilamentCalibrationDialog.tsx:1396`; `StackMatrixCalibrationPanel.tsx:484`; `StackMatrixCalibrationPanel.tsx:1987` | Plan intro and download paragraph | 23 warns against reinterpretation of old measurements. | +| Exhaustive vs HD-selected gamut / swap estimate | `stackMatrixCalibration.ts:253`; `stackMatrixCalibration.ts:277`; `StackMatrixCalibrationPanel.tsx:2006` | N^L and summary guidance | 20/23 plus prose limitations. | +| Create/download progress / Save As / cancellation / storage errors | `StackMatrixCalibrationPanel.tsx:470`; `StackMatrixCalibrationPanel.tsx:517`; `StackMatrixCalibrationPanel.tsx:2021` | Plan download and persistence paragraphs | Text: no plan inserted merely by cancelling export. | +| Saved Download 3MF / Calibrated indicator | `StackMatrixCalibrationPanel.tsx:1374` | Plan immutable-record guidance | Text clarifies measured-record status, not universal validity. | +| Choose photo / drop zone / image decode | `StackMatrixCalibrationPanel.tsx:653`; `StackMatrixCalibrationPanel.tsx:1396`; `StackMatrixCalibrationPanel.tsx:1485` | Load And Align A Photo | 22. | +| Printed corner orientation key | `StackMatrixCalibrationPanel.tsx:118`; `StackMatrixCalibrationPanel.tsx:1503` | Alignment table | 22 uses 1 TL, 2 TR, 3 BR, 4 BL. | +| Rotate both directions / rerun detection | `StackMatrixCalibrationPanel.tsx:714`; `StackMatrixCalibrationPanel.tsx:1418` | Alignment table | 22 orientation diagram. | +| Zoom ±, 100% reset, scrolling, fit-percent meaning | `StackMatrixCalibrationPanel.tsx:1292`; `StackMatrixCalibrationPanel.tsx:1442` | Alignment table | 22 enlarged-corner illustration. | +| Four handle placement, loupe, drag | `StackMatrixCalibrationPanel.tsx:1141`; `StackMatrixCalibrationPanel.tsx:1551` | Alignment table / placement paragraph | 22 directly distinguishes cell center from physical corner. | +| Show template grid | `StackMatrixCalibrationPanel.tsx:1699` | Alignment table | 22 complete projected grid. | +| Detect again / Reset | `StackMatrixCalibrationPanel.tsx:1206`; `StackMatrixCalibrationPanel.tsx:1210` | Alignment table | Text says resetting alignment is not deleting calibration. | +| Auto detection status / explicit manual or low-confidence review | `StackMatrixCalibrationPanel.tsx:422`; `StackMatrixCalibrationPanel.tsx:1660`; `StackMatrixCalibrationPanel.tsx:1715` | Alignment table | 22 review footer. | +| Perspective-corrected preview | `StackMatrixCalibrationPanel.tsx:1733` | Check-square-cells paragraph | 22 supports exact grid geometry. | +| Reference marker correction off/on | `StackMatrixCalibrationPanel.tsx:1751`; `stackMatrixCalibration.ts:466`; `stackMatrixCalibration.ts:502` | Decide How To Sample | Explicit gains from predicted reference recipes, not independent lighting measurement; cannot repair shadows/glare. | +| Extracted LUT preview / hover RGB | `StackMatrixCalibrationPanel.tsx:1768`; `stackMatrixCalibration.ts:431` | Decide How To Sample | 20 sample-grid motif, practical effect described in prose. | +| Save / Replace / alignment gate | `StackMatrixCalibrationPanel.tsx:1230`; `StackMatrixCalibrationPanel.tsx:1811`; `stackMatrixCalibration.ts:390` | Decide How To Sample | 22 approval gate and 23 physical scope. | +| Photo metadata vs original image persistence | `stackMatrixCalibration.ts:403`; `appearanceProfile.ts:1333` | Source-photo-retention paragraph | Text: profile saves measured colors, not original photo bytes. | +| Delete and combined older/newer evidence | `StackMatrixCalibrationPanel.tsx:1268`; `appearanceProfile.ts:632`; `appearanceModel.ts:195` | Final matrix paragraph | 23 compatibility; no claim that newer sparse boards erase older evidence. | + +## Evidence Scope And Confidence + +| Requirement | Source evidence | Documentation / illustration | +| --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | +| Ordered ID/color/HD/calibration fingerprint, names excluded | `appearanceProfile.ts:594`; `profileManager.ts:360` | Compatibility table; distinction between dirty UI state and optical fingerprint. | +| Proof local/global process: profile+LH+firstLH+transitionOpacity | `appearanceModel.ts:154` | Compatibility table. | +| Exact proof anchors omit transitionOpacity equality | `appearanceModel.ts:163` | Compatibility table with realizable suffix requirement. | +| Matrix eligibility: complete, not explicitly unverified, compatible profile, regular LH | `appearanceModel.ts:171`; `appearanceModel.ts:195` | Compatibility table and 23. Does not falsely add unconditional first-LH equality. | +| Matrix backing equivalence, limited continuation, local coverage | `appearanceModel.ts:1446`; `appearanceModel.ts:2995`; existing `calibration-theory.md` Prediction Uncertainty | Practical warning with deep theory link. | +| HD scalar remains a thickness model at new LH, not physical validation | `calibration.ts:858`; `appearanceModel.ts:171` | 23 and 0.08→0.04 example. | +| Reference correction is predicted-corner RGB gain, not illumination measurement | `stackMatrixCalibration.ts:492` | On/off consequences paragraph. | +| Estimate vs measured/interpolated/fitted/simulated and confidence separation | `AutoPaintTab.tsx:183`; `calibration.ts:1331`; `types/appearance.ts` | Read Confidence Without Overclaiming Accuracy; avoids treating Result Confidence as physical match percentage. | +| Wedge aging and interval uncertainty | `calibration.ts:1026`; `calibration.ts:1331` | Confidence section and existing deep theory retained. | + +## Gaps Closed And Verification + +- Prior 3D documentation described these workflows in long, dense paragraphs. The new guide makes every audited input/action independently findable in short steps, tables, and outcome warnings. +- Added four purpose-specific diagrams: `20_calibration_choices.svg`, `21_proof_rounds.svg`, `22_matrix_alignment.svg`, and `23_calibration_scope.svg`. +- Replaced the hard-to-read original diagrams `06_frontlit_hiding_distance.svg`, `07_calibration_wedge.svg`, `08_opacity_solve.svg`, and `09_palette_proof.svg` with readable, accessible same-style schematics. The old proof cross-section visually resembled independently colored columns; the replacement now uses the same physical material along each horizontal layer. +- All eight use 960×540 viewBoxes, 18 px minimum labels, 26 px titles, explicit title/description accessibility, and a disclaimer where colors or graphs are schematic. +- Rendered all eight with headless Playwright to `tmp/docs-calibration-qa/`. Checked every SVG text bounding box against the full viewport and inspected all eight raster previews. No text overflow was found. The opacity graph's threshold annotation and numeric patch spacing were refined after visual review. +- Confirmed that Palette Proof consumes `autoPaintResult.finalStack`, so documentation does not require building a separate artwork mesh first. +- No app algorithms, profile files, printer settings, or user evidence were changed. Root agent owns integrated docs registration, navigation, changelog, links, build, and rendered in-app verification. diff --git a/docs/audits/feature-documentation.md b/docs/audits/feature-documentation.md new file mode 100644 index 00000000..be14ae70 --- /dev/null +++ b/docs/audits/feature-documentation.md @@ -0,0 +1,72 @@ +# Illustrated documentation coverage audit + +Scope: nontrivial 3D and 2D features on `develop`, with 3D first. The implementation and its handlers are the authority, not older prose or screenshots. This inventory is for maintaining the guide; user-facing pages live in `src/docs`. + +## Coverage inventories + +- [3D controls](3d-feature-coverage.md): print dimensions, layer snapping, manual stacks, filaments, Auto-paint, geometry options, confidence, inspection. +- [Calibration](calibration-feature-coverage.md): HD wedge, Palette Proof, Stack Matrix, profile ownership, compatibility and evidence. +- [2D controls](2d-feature-coverage.md): loading, cropping, resizing, touch-up, adjustments, quantization, palettes, swatches and dedithering. + +## Cross-workflow and export controls + +| Feature / control | Authoritative implementation | User-facing coverage | Illustration / demonstration | +| ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------ | +| Build, progress, Build Anyway / cancel | `src/components/ThreeDControls.tsx`, `src/App.tsx`, build handler | `3d-mode`, `generating-exporting-output` | `40_build_export_snapshot.svg` | +| Built snapshot vs current settings; instructions attached to build | `ThreeDControls.tsx` builtState instruction fields; `useAppHandlers.ts` last mesh export | `generating-exporting-output` | `40_build_export_snapshot.svg` | +| PNG download vs live adjustments | `useAppHandlers.ts` onDownloadImage; `CanvasPreview.tsx` exportImageBlob | `loading-images`, `image-adjustments`, `faq` | 2D pipeline illustration | +| STL / 3MF and physical materials | `useAppHandlers.ts`, `exportStl.ts`, `export3mf.ts` | `generating-exporting-output`, `flat-paint` | Built stack and flat orientation diagrams | +| Start color, swaps, Copy, no-swaps / too-many-colors state | `PrintInstructions.tsx`, `useSwapPlan.ts` | `generating-exporting-output`, `troubleshooting` | `41_swap_layers.svg` | +| New-layer number vs boundary Z vs top Z | `useSwapPlan.ts` Auto-paint and Manual formulas | `generating-exporting-output#print-instructions` | Exact 0.10 / 0.04 mm example in `41_swap_layers.svg` | +| Layer Preview, shaded/color/physical choices not export edits | Preview controls and last mesh export | `3d-mode`, `generating-exporting-output` | Preview diagram plus `40_build_export_snapshot.svg` | +| Desktop Save As, browser download, cancellation | `src/hooks/saveBlobToFile.ts` as called by export handlers | `generating-exporting-output`, `settings-and-controls`, calibration guide | Control table and written consequence; no invented geometry effect | +| Collapse, reset, splitter, 2D/3D navigation | `CollapsibleCard.tsx`, `App.tsx`, `PrintSettingsCard.tsx` | `settings-and-controls`, relevant control guides | Relevant before/after diagrams; state vs geometry explained | +| Shared Undo/Redo image history, not printer-setting history | `App.tsx` useImageHistory and preview callbacks | `3d-mode`, `loading-images`, `settings-and-controls` | Explicit scope and rebuild warning | +| Remembered settings vs profile backups | `printSettingsStorage.ts`, profile manager, Auto-paint storage | `settings-and-controls`, `calibration-workflows` | Evidence context diagram | +| Experimental multi-plate has no print effect | `Header.tsx` experimental toggle and `App.tsx` animation-only branch | `settings-and-controls#experimental-multi-plate-mode` | Explicitly documented as no geometry effect | +| Theme / resources / update / diagnostics | `Header.tsx` | `settings-and-controls` | Readable control reference, no claimed print effect | + +## Accuracy corrections identified by the code audit + +- Algorithm Weight controls an intermediate quantization palette size, not generic effect strength. +- Source and adjusted preview are distinct; bake adjustments before workflows that consume the source. +- Deleting a swatch remaps the palette; erasure/zero alpha removes pixels. +- Resizing pixels can simplify geometry; changing mm/pixel alone cannot reduce mesh complexity. +- The 3D toolbar's Undo/Redo callbacks operate on image history. +- Preview trimming and display styles do not change the exported mesh. +- Auto-paint output being calculated is separate from building that output. +- A Max Height cap on appearance stacks is not an unconditional guarantee about the carrier-inclusive Flat Paint slab. +- Changing regular layer height affects empirical calibration eligibility. Matrix backing transfer and first-layer behavior must not be reduced to a blanket all-settings-equal rule. +- Confidence summaries, exact search labels and color-accurate rendering do not certify measured physical accuracy. +- Standard Auto-paint maps normalized image luminance to height; equal-brightness hues can share a height. Enhanced mapping considers image color. +- Height dithering redistributes fractional-height error when present. Already-discrete mappings may remain unchanged, so the illustration is explicitly conditional. +- Profile duplicate detection includes appearance evidence. Same-ID files without usable evidence do not erase an existing profile's measurements. +- HD is a frontlit model parameter; 10% modeled show-through at one HD is not an unconditional visual match threshold. +- A diagnostic trace records a new Auto-paint calculation, not a mesh build from an already-computed result. + +## Verification gates + +Completion requires source/control coverage review, actual rendered illustration inspection, docs navigation and image integrity tests, production build/static pages, responsive browser checks and lint. Passing structural checks alone is not evidence that prose or illustrations describe the implementation correctly. + +- `npm run test:docs`: metadata, sidebar membership, cross-page anchors, local image existence and accessibility metadata. +- `node scripts/verify-doc-illustrations.mjs`: readable SVG labels, bounds, native-size renders and contact sheets in `test-results/docs-illustrations` for human/agent visual inspection. +- `npm run build`: TypeScript, bundled app and statically generated docs with image-file verification. +- `npm run test:e2e:docs`: every documentation route at desktop and mobile widths, loaded image counts, full-size links, direct anchor and keyboard navigation, mobile navigation collapse, and the static pages without JavaScript. +- `npm run lint`: project lint gate. + +## Completion evidence, 2026-09-12 + +| Requirement | Current evidence | +| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Inventory nontrivial 3D features first | `3d-feature-coverage.md` and `calibration-feature-coverage.md` map the current controls, handler side effects, availability, output meaning, guide sections, and diagrams. Source cross-review corrected standard mapping, dithering, profile imports, and calibration scope. | +| Inventory and document nontrivial 2D features | `2d-feature-coverage.md` maps loading, pixel tools, all twelve adjustments, quantizers, palettes, alpha editing, dedithering, and their downstream print effects. | +| Complete missing practical guides in `src/docs` | Four new guides: Auto-paint Controls, Flat Paint, Calibration Workflows, and Image Adjustments. Core 3D and 2D pages were rewritten; overview, quick start, export, settings, troubleshooting, and FAQ agree with them. The collection has 15 pages. | +| Explain effects, dependencies, and limits | Tables and examples distinguish source edits, physical geometry, optical prediction, display-only controls, reset/persistence consequences, and slicer alignment. Existing 3D section anchors still resolve after the split. | +| Provide useful, readable illustrations | 27 local SVG schematics: 23 new and four redesigned calibration figures. Every SVG has accessible title/description metadata, at least 18px text at native size, and no text outside its viewBox. All four contact sheets and focused native/in-page renders were visually reviewed; spacing and misleading diagrams were corrected. | +| Make the guides usable in the app and on the web | 3D-first sidebar groups, full-size illustration links, and collapsible mobile navigation. Desktop and mobile page screenshots were inspected, including the final mobile layout and the Flat Paint/height-dithering figures. | +| Verify current implementation | `npm run test:docs`: 3/3 pass. `npm run lint`: pass. `npm run test:e2e:docs`: 5/5 pass, including its fresh production build and static-page verification. `node scripts/verify-doc-illustrations.mjs`: all 27 pass. `git diff --check`: pass. | +| Stay on develop and preserve unrelated work | Branch is `develop`. Existing candidate-print assets and unrelated `tmp` contents were not removed. No commit or push was performed. | + +Browser coverage visits every guide at 1440px and 390px, loads every documented image, checks layout bounds and full-size links, follows an anchor and keyboard navigation, exercises both mobile navigation panels, and visits every generated static page with JavaScript disabled. The production build retains the existing large-chunk warning; it completes successfully. + +The source/control inventories are semantic evidence; structural tests do not independently prove the physical explanations. No printer settings, optical algorithms, or model/export geometry are changed by this documentation work. Generated QA captures are under ignored `test-results`, not published assets. diff --git a/package.json b/package.json index 90368d2b..37990339 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,8 @@ "profile:calibrated": "node scripts/profile-calibrated.mjs", "profile:compare": "node scripts/compare-calibrated-profiles.mjs", "test:e2e": "playwright test --grep @smoke", + "test:docs": "node --no-warnings --experimental-strip-types --test tests/docsContent.test.ts", + "test:e2e:docs": "playwright test --config playwright.docs.config.ts", "test:e2e:matrix": "playwright test --grep @matrix", "test:e2e:stress": "playwright test --grep @stress", "test:e2e:full": "playwright test --grep @full", diff --git a/playwright.docs.config.ts b/playwright.docs.config.ts new file mode 100644 index 00000000..ee20305c --- /dev/null +++ b/playwright.docs.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from '@playwright/test'; +import base from './playwright.config'; + +// Isolate documentation QA from a user's running dev app and its saved data. +export default defineConfig({ + ...base, + testMatch: 'docs.spec.ts', + use: { ...base.use, baseURL: 'http://127.0.0.1:5182' }, + webServer: { + command: 'npm run build && npm run preview -- --host 127.0.0.1 --port 5182 --strictPort', + url: 'http://127.0.0.1:5182', + reuseExistingServer: false, + timeout: 180_000, + }, +}); diff --git a/scripts/generate-docs-seo-pages.mjs b/scripts/generate-docs-seo-pages.mjs index 850a06d0..405b94b5 100644 --- a/scripts/generate-docs-seo-pages.mjs +++ b/scripts/generate-docs-seo-pages.mjs @@ -110,15 +110,12 @@ function resolveDocImage(src) { if (clean.includes('kromacut-logo.png')) { return findBuiltAsset('logo-') ?? clean; } - const diagramPrefixes = { - '06_frontlit_hiding_distance.svg': '06_frontlit_hiding_distance-', - '07_calibration_wedge.svg': '07_calibration_wedge-', - '08_opacity_solve.svg': '08_opacity_solve-', - '09_palette_proof.svg': '09_palette_proof-', - }; - const diagramName = Object.keys(diagramPrefixes).find((name) => clean.includes(name)); - if (diagramName) { - return findBuiltAsset(diagramPrefixes[diagramName]) ?? clean; + const diagramName = path.basename(clean); + if ( + diagramName.endsWith('.svg') && + existsSync(path.join(rootDir, 'src/assets/diagrams', diagramName)) + ) { + return findBuiltAsset(`${diagramName.slice(0, -4)}-`) ?? clean; } return clean; } @@ -159,7 +156,10 @@ function renderInline(markdown, currentDocSlug, docsBySlug) { const [srcPart, titlePart] = rawSrc.trim().split(/\s+["']/); const title = titlePart ? titlePart.replace(/["']$/, '') : ''; const titleAttr = title ? ` title="${escapeHtml(title)}"` : ''; - return protect(`${escapeHtml(alt)}`); + const imageUrl = escapeHtml(resolveDocImage(srcPart)); + return protect( + `${escapeHtml(alt)}` + ); }); html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_match, label, href) => { @@ -167,7 +167,9 @@ function renderInline(markdown, currentDocSlug, docsBySlug) { const externalAttrs = /^(https?:|mailto:)/i.test(resolved) ? ' target="_blank" rel="noopener noreferrer"' : ''; - return protect(`${renderInline(label, currentDocSlug, docsBySlug)}`); + return protect( + `${renderInline(label, currentDocSlug, docsBySlug)}` + ); }); html = html.replace(/\*\*([^*]+)\*\*/g, '$1'); @@ -250,7 +252,9 @@ function renderMarkdown(doc, docsBySlug) { parts.push(lines[index].replace(/^\s*>\s?/, '')); index++; } - html.push(`
${renderMarkdown({ ...doc, body: parts.join('\n') }, docsBySlug)}
`); + html.push( + `
${renderMarkdown({ ...doc, body: parts.join('\n') }, docsBySlug)}
` + ); continue; } @@ -273,7 +277,9 @@ function renderMarkdown(doc, docsBySlug) { .map( (row) => `${row - .map((cell) => `${renderInline(cell, doc.slug, docsBySlug)}`) + .map( + (cell) => `${renderInline(cell, doc.slug, docsBySlug)}` + ) .join('')}` ) .join('')}` @@ -316,7 +322,11 @@ function replaceOrInsertHeadTag(html, selector, replacement) { function updateMeta(html, attribute, key, content) { const escaped = escapeHtml(content); const pattern = new RegExp(`]*${attribute}="${key}"[^>]*>`, 's'); - return replaceOrInsertHeadTag(html, pattern, ``); + return replaceOrInsertHeadTag( + html, + pattern, + `` + ); } function updateDocHead(template, doc) { @@ -451,16 +461,40 @@ function verifyGeneratedOutput(docs) { const manifest = JSON.parse(readFileSync(path.join(distDir, 'site.webmanifest'), 'utf8')); const version = JSON.parse(readFileSync(path.join(distDir, 'version.json'), 'utf8')); - assertGenerated(rootHtml.includes('https://kromacut.com/'), 'root is missing from sitemap'); - assertGenerated(!sitemap.includes('https://kromacut.com/app'), '/app must not appear in sitemap'); - assertGenerated(robots.includes('Sitemap: https://kromacut.com/sitemap.xml'), 'robots.txt sitemap reference is missing'); + assertGenerated( + rootHtml.includes('https://kromacut.com/'), + 'root is missing from sitemap' + ); + assertGenerated( + !sitemap.includes('https://kromacut.com/app'), + '/app must not appear in sitemap' + ); + assertGenerated( + robots.includes('Sitemap: https://kromacut.com/sitemap.xml'), + 'robots.txt sitemap reference is missing' + ); assertGenerated(manifest.start_url === '/app', 'manifest start_url must be /app'); assertGenerated(manifest.id === '/', 'manifest id must remain stable at /'); - assertGenerated(typeof version.version === 'string' && version.version.length > 0, 'version.json is invalid'); + assertGenerated( + typeof version.version === 'string' && version.version.length > 0, + 'version.json is invalid' + ); docs.forEach((doc) => { const relativePage = path.join('docs', doc.slug, 'index.html'); @@ -475,9 +509,18 @@ function verifyGeneratedOutput(docs) { for (const match of html.matchAll(/]*src="([^"]+)"/g)) { const src = match[1]; if (/^(https?:|data:)/i.test(src)) continue; - assertGenerated(!src.includes('<') && !src.includes('>'), `malformed image URL in ${doc.slug}: ${src}`); - assertGenerated(src.startsWith('/'), `image URL is not root-relative in ${doc.slug}: ${src}`); - assertGenerated(existsSync(path.join(distDir, src.slice(1))), `missing image used by ${doc.slug}: ${src}`); + assertGenerated( + !src.includes('<') && !src.includes('>'), + `malformed image URL in ${doc.slug}: ${src}` + ); + assertGenerated( + src.startsWith('/'), + `image URL is not root-relative in ${doc.slug}: ${src}` + ); + assertGenerated( + existsSync(path.join(distDir, src.slice(1))), + `missing image used by ${doc.slug}: ${src}` + ); } }); } diff --git a/scripts/verify-doc-illustrations.mjs b/scripts/verify-doc-illustrations.mjs new file mode 100644 index 00000000..671b4d3f --- /dev/null +++ b/scripts/verify-doc-illustrations.mjs @@ -0,0 +1,73 @@ +import { chromium } from '@playwright/test'; +import { readdirSync, readFileSync, mkdirSync } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const root = fileURLToPath(new URL('..', import.meta.url)); +const directory = path.join(root, 'src/assets/diagrams'); +const output = path.join(root, 'test-results/docs-illustrations'); +const files = readdirSync(directory).filter((file) => /^\d{2}_.*\.svg$/.test(file)); +mkdirSync(output, { recursive: true }); +const browser = await chromium.launch(); +const page = await browser.newPage({ viewport: { width: 960, height: 540 }, deviceScaleFactor: 1 }); +const failures = []; +try { + for (const file of files) { + const svg = readFileSync(path.join(directory, file), 'utf8'); + await page.setContent( + `${svg}` + ); + await page.evaluate(() => document.fonts.ready); + const issues = await page.evaluate(() => { + const svg = document.querySelector('svg'); + const { width, height } = svg.viewBox.baseVal; + return [...svg.querySelectorAll('text')].flatMap((text) => { + const box = text.getBBox(); + const size = parseFloat(getComputedStyle(text).fontSize); + const errors = []; + if (size < 18) errors.push(`small label (${size}px)`); + if ( + box.x < 0 || + box.y < 0 || + box.x + box.width > width || + box.y + box.height > height + ) { + errors.push('text outside viewBox'); + } + return errors.map((error) => `${error}: ${text.textContent}`); + }); + }); + failures.push(...issues.map((issue) => `${file}: ${issue}`)); + await page + .locator('svg') + .screenshot({ path: path.join(output, file.replace(/\.svg$/, '.png')) }); + } + // Contact sheets supplement the per-image readability and clipping checks. + for (let start = 0; start < files.length; start += 8) { + const cards = files.slice(start, start + 8).map((file) => { + const encoded = Buffer.from(readFileSync(path.join(directory, file))).toString( + 'base64' + ); + return `

${file}

`; + }); + await page.setViewportSize({ width: 1280, height: 900 }); + await page.setContent( + `${cards.join('')}` + ); + await page + .locator('img') + .evaluateAll((images) => Promise.all(images.map((img) => img.decode()))); + await page.screenshot({ + path: path.join(output, `contact-${start / 8 + 1}.png`), + fullPage: true, + }); + } +} finally { + await browser.close(); +} +if (failures.length) { + console.error(failures.join('\n')); + process.exitCode = 1; +} else { + console.log(`Verified ${files.length} SVG illustrations. Renders: ${output}`); +} diff --git a/src/assets/diagrams/06_frontlit_hiding_distance.svg b/src/assets/diagrams/06_frontlit_hiding_distance.svg index 6e409e26..4f60617f 100644 --- a/src/assets/diagrams/06_frontlit_hiding_distance.svg +++ b/src/assets/diagrams/06_frontlit_hiding_distance.svg @@ -1,62 +1,28 @@ - - - -Hiding Distance — Thin Layers Only Partly Hide the Base -Frontlit viewing: light passes through the filament, reflects off what is beneath, and passes back out. -Transmission T = 10^(−thickness / HD) — every added layer multiplies the show-through. - -what you see - - - - - - -1 layer · T ≈ 50% - - - - - - - -2 layers · T ≈ 25% - - - - - - - - - -4 layers · T ≈ 6% - - - - - - - - - - - - - -8 layers · T < 1% - -black base - - - -opaque filament color -(the wedge's reference rail) -T = 10^(−thickness / HD) -HD (hiding distance): the depth at -which a filament visually hides -what's beneath it. -Conventional backlit TD ≈ 10 × HD. - -Kromacut · frontlit calibration + +More filament thickness hides more of the base +Three schematic stacks have progressively more orange layers over a dark base. Their visible swatches approach the opaque filament color as thickness increases. Frontlit light enters and returns after reflection underneath. Colors are illustrative, not predictions for a particular spool. + + +More thickness hides more of the base +Frontlit viewing: light enters the surface, reflects underneath, and returns. + + + + +ThinThickerNearly opaque + +Visible colorVisible colorVisible color + + + + + + +More base shows throughLess base shows throughNear the filament's color + +Modeled show-through: T = 10^(−thickness / HD) +At thickness = HD, 10% remains in this model. Visual opacity needs a comparison. +Higher HD → more thickness to hide the same base. Backlit TD is a different input scale. +Schematic colors and layers, not measurements + diff --git a/src/assets/diagrams/07_calibration_wedge.svg b/src/assets/diagrams/07_calibration_wedge.svg index f2919390..22ab8350 100644 --- a/src/assets/diagrams/07_calibration_wedge.svg +++ b/src/assets/diagrams/07_calibration_wedge.svg @@ -1,64 +1,29 @@ - - -Reading the Calibration Wedge -Each tile prints patches of 1..N filament layers over a base, beside a rail of fully opaque filament. -You report one number per tile: the first patch that looks identical to the rail. - - - -reference rail -(fully opaque) - - - -foot - - - - - - - - - - - - - - -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -first patch identical to the rail → report 8 - - -side view (single-filament STL workflow) - - - - - - - - - - - - - -base filament - -single swap: -base → color - -Kromacut · frontlit calibration + +Read the first wedge patch that matches the reference rail +An illustrative eight-patch wedge has a tab at its one-layer end and an opaque rail beside all patches. Patch six is the first shown matching the rail. Max layers sets the last patch; layer height sets each thickness increment. A side view shows increasing thickness over a common base. The optional Merge read compares neighboring patches rather than the reference rail. + + + +Match compares a patch with the rail beside it +Example only: 8 patches printed; the first rail match is patch 6. + +Opaque reference rail, made from the filament being measured + + + + + + + +12345678 + +Tab = startMatch = 6Max = 8 + +Side view: one more layer per step + +Base below; layer height sets each rise. + +Merge is optional, and differentCompare neighboring patches.Enter the last patch still differentfrom the patch immediately before it.It checks the curve, not the rail match. +Illustrative reads, colors, and exaggerated heights + diff --git a/src/assets/diagrams/08_opacity_solve.svg b/src/assets/diagrams/08_opacity_solve.svg index ca555d5e..f6f12471 100644 --- a/src/assets/diagrams/08_opacity_solve.svg +++ b/src/assets/diagrams/08_opacity_solve.svg @@ -1,48 +1,23 @@ - - -From One Read to a Hiding Distance -The difference between each patch and the opaque rail shrinks as layers stack. -Your read pins where that difference crosses one just-noticeable difference (JND). - - - - - - - - - -0 -2 -4 -8 -12 -0 -2 -4 -6 -8 -10 -12 -ΔE00 difference from the opaque rail -wedge patch — layers of filament over the base - - - - - - -one JND (ΔE00 ≈ 2) — “looks identical” - - - - -your read: patch 8 → d* = 8 × layer height - - -HD = −d* / log₁₀(T*) -T* = the show-through that sits exactly one JND -from opaque — solved from the colors alone - -Kromacut · frontlit calibration + +A wedge read locates the visible opacity threshold +A schematic curve of patch-to-rail color difference falls as filament layers increase. The example first matching patch is six, where the difference reaches a just-noticeable threshold. Patch count times layer height gives thickness; the model combines thickness with filament and base colors to infer hiding distance. The graph is explanatory, not measured data. + + +Your read locates a visible threshold +The difference from the opaque rail falls as filament thickness increases. +Color difference from the rail (ΔE00) + + +JND: looks identical + +1368 +Patch number / added layers + +Read → thickness → HDExample Match: 6Thickness d* = 6 × height +HD = −d* / log₁₀(T*) +T* depends on the filament,base, and visible threshold. +No visible base contrast?There is no useful crossingto measure with that base. +The default JND is about 2 ΔE00. More informative base reads can refine the model. +Schematic curve and example read, not measurement data + diff --git a/src/assets/diagrams/09_palette_proof.svg b/src/assets/diagrams/09_palette_proof.svg index d1cab9b1..f3c222ba 100644 --- a/src/assets/diagrams/09_palette_proof.svg +++ b/src/assets/diagrams/09_palette_proof.svg @@ -1,68 +1,31 @@ - - - -Palette Proof Layout -Each target is one printed row; its A-E candidates run left to right in both app views. - -Patch map -T = target shown in Kromacut, A-E = physical candidates - - -ABCDE + +Palette Proof candidates are stopping heights on one stack +An illustrative proof map has two target rows and three candidates A through C. An F-marked candidate is the shared foundation margin, not an extra printed color. A side view of one target's candidates shows the same material order, with each candidate stopping at a different layer prefix. Horizontal layers use the same filament wherever they continue. Colors and heights are schematic. + + +Candidates stop at different heights of the same stack +A prefix includes the foundation and every preceding layer, in physical print order. +Proof map: two example targetsTarget +ABC + + + + - - - - - - - + + +12A1B1C1 +A2 FB2C2 - -1234 -5678 +Numbers = target rowsLetters = candidate columnsF = compare the foundation margin +Side view of one candidate row + + - - - - - - - - - +ABC + +One filament per horizontal layer.Later prefixes keep every layer below. +Touching patches share a continuous foundation. Targets are not additional printed colors. +Schematic layout, layers, and appearance; not to scale - -A1 FB1C1D1E1 -A2B2C2D2E2 -A3B3C3D3E3 -A4B4C4D4E4 -A5B5C5D5E5 -A6B6C6D6E6 -A7B7C7D7E7 -A8B8C8D8E8 - - -44 mm wide x 68 mm high at the default layout -notch - -Cross-section -Candidates stay exact while touching neighbors share layer regions - - - - - - - - - - -prefix 2prefix 3prefix 4prefix 5prefix 6 - -continuous first layer; touching active cells union on each later layer -One physical filament is assigned to each horizontal layer. -No arbitrary color combinations are fabricated. - -Kromacut - camera-free appearance proof diff --git a/src/assets/diagrams/10_physical_size.svg b/src/assets/diagrams/10_physical_size.svg new file mode 100644 index 00000000..28c49bea --- /dev/null +++ b/src/assets/diagrams/10_physical_size.svg @@ -0,0 +1 @@ +Three different kinds of detailSame four-pixel grid at two physical scales, compared with twice as many pixels at the original scale.Three different kinds of detailA. Original size4 pixels × 0.1 mm0.4 mm wideB. Larger pixel size4 pixels × 0.2 mm0.8 mm wideC. More pixels8 pixels × 0.05 mmStill 0.4 mm wideSchematic zoom. A nozzle's extrusion width remains a separate physical limit. diff --git a/src/assets/diagrams/11_manual_layers.svg b/src/assets/diagrams/11_manual_layers.svg new file mode 100644 index 00000000..a6d951fb --- /dev/null +++ b/src/assets/diagrams/11_manual_layers.svg @@ -0,0 +1 @@ +A row is a thickness, not a top heightThree columns stop at the black, red, and white surfaces; their heights add upward from a common plate.A row is a thickness, not a top heightSide view: cumulative stackBlackRedWhitePlate → black → red → whiteExample at 0.08 mm layersRun thicknessTop heightBlack: 0.20 mm→0.20 mmRed: 0.16 mm→0.36 mmWhite: 0.08 mm→0.44 mmFirst layer: 0.20 mmLater surfaces include earlier runs.Schematic. Increasing a lower run lifts later surfaces and moves later swaps. diff --git a/src/assets/diagrams/12_smooth_boundaries.svg b/src/assets/diagrams/12_smooth_boundaries.svg new file mode 100644 index 00000000..d674e43a --- /dev/null +++ b/src/assets/diagrams/12_smooth_boundaries.svg @@ -0,0 +1 @@ +Smooth contours, same source detailA stair-stepped diagonal becomes a connected smoother boundary. Pixel size and layer height do not change.Smooth contours, same source detailSmooth Meshing offSmooth Meshing onSquare pixel steps remain.Connected boundaries are smoothed.Schematic outline only. Both choices alter exported contours; neither adds source pixels. diff --git a/src/assets/diagrams/13_printable_detail.svg b/src/assets/diagrams/13_printable_detail.svg new file mode 100644 index 00000000..82dc7980 --- /dev/null +++ b/src/assets/diagrams/13_printable_detail.svg @@ -0,0 +1,58 @@ + + A thin stripe: compare its width, then choose whether to keep it + At 0.10 mm per pixel, a two-pixel purple stripe is 0.20 mm wide, narrower than the planned 0.40 mm extrusion width. The preview marks it amber as a warning, not as a new filament color. With Omit at-risk colors from matching off, the stripe remains a target in Auto-paint's input. With it on, this stripe is replaced by its suitable blue neighbor, leaving a blue region rather than a hole. These are input colors, not guaranteed print colors. The original 2D image is unchanged. + + + Why a thin detail may disappear + Example: Pixel Size = 0.10 mm/pixel. Stripe = 2 pixels = 0.20 mm. + + + 1. Compare the widths + Purple stripe + + 0.20 mm + Planned extrusion line + + 0.40 mm + The planned line is twice as wide as the stripe. + + + 2. Inspect the warning + + + Amber = warning + Not a yellow filament. + This stripe is at risk + in the slicer. + The overlay only highlights the problem. + + 3. Choose: “Omit at-risk colors from matching” + Below: input to Auto-paint, not a prediction of the finished print. + + OFF: keep the stripe + + + Purple stays as an + image-color target. + The slicer may still lose it. + + + ON: use the nearby blue + + The stripe is replaced + with nearby blue. + A blue region, + not a hole. + + Your 2D image stays unchanged. Schematic analysis, not exact slicer toolpaths. + If no suitable printable neighbor exists, Kromacut keeps the detail. + diff --git a/src/assets/diagrams/14_repeats_separation.svg b/src/assets/diagrams/14_repeats_separation.svg new file mode 100644 index 00000000..4d2e628b --- /dev/null +++ b/src/assets/diagrams/14_repeats_separation.svg @@ -0,0 +1 @@ +Repeats and separation solve different problemsA repeated material expands possible stack sequences. Separation assigns distinct outputs; partial mode can merge an unmatched target.Repeats and separation solve different problemsShared repeat budgetBlackYellowBlack1 extra appearanceDistinct outputsPartial paletteTarget A → Output 1Target B → Output 2Target C → Output 3Target A → Output 1Target B → Output 2Target C → Output 2 (merged)Conceptual examples. Strict mode rejects an incomplete distinct-color assignment. diff --git a/src/assets/diagrams/15_transition_height.svg b/src/assets/diagrams/15_transition_height.svg new file mode 100644 index 00000000..ba4664ef --- /dev/null +++ b/src/assets/diagrams/15_transition_height.svg @@ -0,0 +1 @@ +A height cap squeezes transitions, not the foundationThe foundation stays opaque while upper runs are compressed to fit a lower printable cap.A height cap squeezes transitions, not the foundationAuto heightLower Max HeightPrintable capOpaque foundationOpaque foundationMore transition thickness.Fewer intermediate height choices.Schematic. An impossibly low cap fails instead of shrinking the opaque foundation. diff --git a/src/assets/diagrams/16_height_dithering.svg b/src/assets/diagrams/16_height_dithering.svg new file mode 100644 index 00000000..6bbcb9b7 --- /dev/null +++ b/src/assets/diagrams/16_height_dithering.svg @@ -0,0 +1 @@ +When fractional heights are presentConditional mechanism: fractional-height rounding error can be distributed among neighboring low and high printable heights. Already-discrete input regions may remain unchanged.When fractional heights are presentDirect height snappingDistribute rounding errorOne snapped surface height.Fractional height rounds to one layer.Nearby low / high height blocks.Possible intermediate tone at a distance.Schematic mechanism only. Already-snapped regions may remain unchanged. diff --git a/src/assets/diagrams/17_flat_paint_orientation.svg b/src/assets/diagrams/17_flat_paint_orientation.svg new file mode 100644 index 00000000..a707c924 --- /dev/null +++ b/src/assets/diagrams/17_flat_paint_orientation.svg @@ -0,0 +1 @@ +Same artwork, three physical arrangementsEach three-column cross-section uses black foundation, orange middle, and yellow upper materials. Face-down reverses columns and adds a carrier; face-up raises shorter columns.Same artwork, three physical arrangementsNormal reliefFace-down + carrierFace-up, no carrierView from aboveFoundation behindView from aboveColumns stop at their color.View through clear bottom.Foundation fills underneath.Schematic cross-sections. Flat Paint needs multi-material 3MF; never mirror it again. diff --git a/src/assets/diagrams/18_optimizer_choices.svg b/src/assets/diagrams/18_optimizer_choices.svg new file mode 100644 index 00000000..087f181f --- /dev/null +++ b/src/assets/diagrams/18_optimizer_choices.svg @@ -0,0 +1 @@ +Choose where the optimizer spends its effortThe same image is weighted equally, toward its center, or toward edges. Separate transition-detail examples show increasing potential height choices, not exact layer counts.Choose where matching effort goesUniformAll pixels count equally.Center-weightedMiddle colors matter more.Edge-weightedOuter colors matter more.Transition detail: more potential thickness choicesCompact · 80%Detailed · 90%Maximum · 95%Fast → Balanced → Thorough → Deep: more search work, not guaranteed print accuracy.Schematic weighting and choices. Early convergence and Max Height can limit transitions. diff --git a/src/assets/diagrams/19_preview_only.svg b/src/assets/diagrams/19_preview_only.svg new file mode 100644 index 00000000..2745910a --- /dev/null +++ b/src/assets/diagrams/19_preview_only.svg @@ -0,0 +1 @@ +Inspecting a range does not crop the printLower and upper layers are hidden in the preview but all four layers remain in the export.Inspecting a range does not crop the printLayer Preview: selected rangeExport: complete modelOutside the range: hidden.All layers and materials remain.Schematic. Camera, shading, wireframe, and preview colors are inspection-only too. diff --git a/src/assets/diagrams/20_calibration_choices.svg b/src/assets/diagrams/20_calibration_choices.svg new file mode 100644 index 00000000..1e049cfc --- /dev/null +++ b/src/assets/diagrams/20_calibration_choices.svg @@ -0,0 +1,52 @@ + + Choose the calibration evidence you need + A wedge measures one filament's opacity. A Palette Proof compares artwork targets with printed candidates. A Stack Matrix photographs many known recipes. All inform predicted colors and stack choices, not printer extrusion settings. Drawings are schematic, not measured color predictions. + + + + + + Three tools, three different questions + Combine evidence where it helps. None of these tunes the printer. + + + + Hiding Distance + Palette Proof + Stack Matrix + + + + + + When does the base hide? + Read a patch beside its rail. + Output: measured HD. + + + + + + + + + + + + Which patch is closest? + Judge selected image colors. + Output: local evidence. + + + + + + What do recipes look like? + Photograph a known grid. + Output: measured colors. + + + Predicted colors → stack choice → heights and swap plan + Schematic colors, not measured predictions + + diff --git a/src/assets/diagrams/21_proof_rounds.svg b/src/assets/diagrams/21_proof_rounds.svg new file mode 100644 index 00000000..fb471103 --- /dev/null +++ b/src/assets/diagrams/21_proof_rounds.svg @@ -0,0 +1,37 @@ + + How Palette Proof judgments guide another round + Best available supports a winner without claiming a color match. Close adds a soft correction and Dead on adds a strong anchor. Continue targets keeps winners and explores challengers. None supplies no winner and leads to untried alternatives. New targets gathers evidence about another part of the image. Example colors are schematic. + + + + A proof is a comparison, not a pass/fail test + Judge the physical patches first. Then choose what to test next. + + A patch is the closest + + + + B1 + Best available: preference only + Close: soft local color correction + Dead on: strongest local anchor + + Continue targets + Keep a previous best. + Test nearby untried challengers. + Allow an exploratory alternative. + Ties can keep multiple winners. + + + None: every candidate is poor + No winner and no invented correct color. + + Continue with exploration + Try untested physical candidates. + + + New targets + Test different artwork colors. Fewer useful candidates can mean a smaller next coupon. + Schematic comparison, not a predicted print result + + diff --git a/src/assets/diagrams/22_matrix_alignment.svg b/src/assets/diagrams/22_matrix_alignment.svg new file mode 100644 index 00000000..aa7136a5 --- /dev/null +++ b/src/assets/diagrams/22_matrix_alignment.svg @@ -0,0 +1,58 @@ + + Place Stack Matrix handles at marker centers + A six-by-six schematic board has a four-by-four recipe grid surrounded by a one-cell border. Markers 1, 2, 3, and 4 sit in the corner border cells. Handles belong in the centers of those cells, half a cell from the physical outside edge. The enlarged corner highlights the wrong outside corner and the correct marker center. Review every projected line before confirming alignment. + + + + + + + The handle is a cell center, not the board corner + Use this record's printed corner key. Marker colors vary between boards. + + Top edge + + + + + + + + + + + + + + + + + + + 12 + 34 + + + + Top-left corner, enlarged + + + + + + + + + + Not here + + Center + + Recipe grid + Outer edge sits half a cell beyond the center. + + Review the whole grid, not just the corners. + Then confirm adjusted / low-confidence alignment before saving the sampled colors. + Schematic board with an illustrative 4 × 4 recipe grid + + diff --git a/src/assets/diagrams/23_calibration_scope.svg b/src/assets/diagrams/23_calibration_scope.svg new file mode 100644 index 00000000..f1aedab0 --- /dev/null +++ b/src/assets/diagrams/23_calibration_scope.svg @@ -0,0 +1,42 @@ + + A measured layer recipe belongs to its physical thickness + Three 0.08 millimeter layers make 0.24 millimeters of color material. Three 0.04 millimeter layers make 0.12 millimeters. A matrix measurement of the first is not reused as the second. Wedge hiding distance can still estimate behavior by thickness, while exact appearance evidence needs compatible layers, filaments, and backing. Layer thicknesses are schematic and colors are not measurements. + + + Same layer count does not mean the same color recipe + A finer layer grid changes the material thickness represented by each step. + + + Measured matrix: 0.08 mm layers + New model: 0.04 mm layers + + + + + + + + + + + + 0.24 mm + of color + + 0.12 mm + of color + 3 recipe layers + opaque backing + 3 thinner layers + backing + Photographed recipe color + Not the same measured recipe + + + HD can still estimate by thickness + That does not certify the new setup. + Check a small physical test. + Matrix evidence has a scope + Match regular layer height and profile. + Recipe and backing still matter. + Schematic thicknesses and material colors, not optical predictions + + diff --git a/src/assets/diagrams/30_crop_resize_scale.svg b/src/assets/diagrams/30_crop_resize_scale.svg new file mode 100644 index 00000000..685c073c --- /dev/null +++ b/src/assets/diagrams/30_crop_resize_scale.svg @@ -0,0 +1,5 @@ + +Pixels, framing, and physical sizeThree schematic examples distinguish cropping a region, resampling to fewer pixels, and changing millimeters per pixel. + + +Pixels, framing, and physical sizeStarting example: 1000 × 800 opaque pixels at 0.1 mm/px = 100 × 80 mmCropResize to 50%Change Pixel SizeKeep a 600 × 600 region0.1 mm/px → 60 × 60 mmDiscard outside the box500 × 400 pixels0.1 mm/px → 50 × 40 mmFewer source pixelsSame 500 × 400 pixels0.2 mm/px → 100 × 80 mmSame pixels, larger printZoom changes none of these. It only changes your view.Transparent outer margins are excluded from the printed footprint. Schematic, not to scale. diff --git a/src/assets/diagrams/31_pixel_tools.svg b/src/assets/diagrams/31_pixel_tools.svg new file mode 100644 index 00000000..9348a891 --- /dev/null +++ b/src/assets/diagrams/31_pixel_tools.svg @@ -0,0 +1,5 @@ + +Small pixel edits become physical featuresBrush paints opaque pixels, eraser creates transparent holes, fill changes an edge-connected region, and text is rasterized without antialiasing. + + +Small pixel edits become physical featuresExact colors, hard edges, and image-pixel sizesBrushAdd or join pixels1–64 px diameterEraserTransparent cutoutCan create holesFillOne connected areaNo diagonal joinsTextBecomes pixelsSize: 6–128 pxAt 0.1 mm/px, a one-pixel stroke is only 0.1 mm wide.Picker samples a source color; custom colors may add targets. Enlarging the view adds no detail. diff --git a/src/assets/diagrams/32_adjustment_controls.svg b/src/assets/diagrams/32_adjustment_controls.svg new file mode 100644 index 00000000..ab8d708d --- /dev/null +++ b/src/assets/diagrams/32_adjustment_controls.svg @@ -0,0 +1,5 @@ + +Twelve controls for the target imageEach control has schematic negative, zero, and positive color samples. Tone controls affect different brightness ranges, color controls shift hue or saturation, and clarity affects local edges. + + +Twelve controls for the target imageEach row of swatches: negative / zero / positive. Directional examples, not measured output.ExposureContrastHighlightsShadowsWhitesBlacksSaturationVibranceHueTemperatureTintClarityTone-range overlap and other active sliders affect the result. Alpha is unchanged. diff --git a/src/assets/diagrams/33_adjustment_bake.svg b/src/assets/diagrams/33_adjustment_bake.svg new file mode 100644 index 00000000..95439b67 --- /dev/null +++ b/src/assets/diagrams/33_adjustment_bake.svg @@ -0,0 +1,5 @@ + +Preview first, then bake the imageAdjustments create a non-destructive preview. Apply writes adjusted pixels into the working image and resets sliders. Downstream quantization, image download, and 3D use the working image. + + +Preview first, then bake the imageA visible adjustment is not yet a change to the source pixels.Working imageOriginal or last saved editLive previewSliders change the lookNew working imageAppearance is baked inSliders reset to zeroApplyQuantizationPNG download3D generationWithout Apply, these steps still use the underlying image, not the live preview. diff --git a/src/assets/diagrams/34_quantization_pipeline.svg b/src/assets/diagrams/34_quantization_pipeline.svg new file mode 100644 index 00000000..246a27c2 --- /dev/null +++ b/src/assets/diagrams/34_quantization_pipeline.svg @@ -0,0 +1,5 @@ + +Two limits, two different jobsAlgorithm Weight sets an intermediate palette budget. Auto's Number of Colors limits the final result, or a fixed palette provides the permitted final colors. None skips the first stage only. + + +Two limits, two different jobsExample: Weight 128 → Auto target 16. The result may contain fewer colors.Source imageMany colorsBaked adjustmentsStage 1: AlgorithmWeight: up to 128 colorsPosterize · Median-cutK-means · Wu · OctreeNone skips this stageWeight is not a percentageStage 2: AutoNumber of Colors: 16Final result ≤16 colorsOR: fixed paletteOnly enabled colorsNot every color is usedApply changes the image. Undo before testing another setting from the same source.Transparent pixels stay transparent; partially transparent pixels become opaque. diff --git a/src/assets/diagrams/35_swatch_operations.svg b/src/assets/diagrams/35_swatch_operations.svg new file mode 100644 index 00000000..4b00a6e1 --- /dev/null +++ b/src/assets/diagrams/35_swatch_operations.svg @@ -0,0 +1,5 @@ + +Recolor, remove, or remap?Three schematic images compare applying a new color, applying zero alpha, and deleting a swatch. Delete maps to the remaining palette rather than making transparent holes. + + +Recolor, remove, or remap?Starting image: amber background and two disconnected pink regions.Apply a new colorAll exact matches recoloredDisconnected regions tooApply alpha = 0Matching pixels disappearCheckerboard = no materialDelete the swatchMap to remaining colorsNo transparent holesDelete reruns the selected quantizer, so other image colors may change as well.Choose None for direct remapping; use Eraser or alpha = 0 to remove a background. diff --git a/src/assets/diagrams/36_dedither_neighbors.svg b/src/assets/diagrams/36_dedither_neighbors.svg new file mode 100644 index 00000000..1b021af7 --- /dev/null +++ b/src/assets/diagrams/36_dedither_neighbors.svg @@ -0,0 +1,5 @@ + +Neighbor support, not a blur radiusIn the example the pink center has three same-color neighbors and five cyan alternatives. It remains pink at Weight 3 and becomes cyan at Weight 4. More passes repeat cleanup, potentially removing thin features. + + +Neighbor support, not a blur radiusA pixel checks eight neighbors, including diagonals. Exact RGB and alpha must match.Three matching neighborsPink center: 3 pink, 5 cyanWeight 33 ≥ 3: keep the centerSame-color support is enoughWeight 43 < 4: choose cyanMost common differentneighborPass 1 → new image → Pass 2 → new image. More passes can erase small features.Weight 1–9 (default 4)Passes 1–10 (default 1)Tied choices can vary. diff --git a/src/assets/diagrams/40_build_export_snapshot.svg b/src/assets/diagrams/40_build_export_snapshot.svg new file mode 100644 index 00000000..4d2bebb1 --- /dev/null +++ b/src/assets/diagrams/40_build_export_snapshot.svg @@ -0,0 +1,22 @@ + +Build captures the model you will exportChanged print settings need another build. Viewing only part of a built stack does not crop the export. + + +Build captures the model you will export +1. Prepare +Image + print settingsFilaments + calibrationManual or Auto-paint +Build 3D Model + +2. Inspect the build + + +Trim the view to inspectNot an export crop + +3. Export + slice + +Complete built geometryConfirm real spools + +Settings changed? Build again. +Camera, shading and Simulated / Physical colors only change the view. +Schematic layers, not a calibrated color prediction. + diff --git a/src/assets/diagrams/41_swap_layers.svg b/src/assets/diagrams/41_swap_layers.svg new file mode 100644 index 00000000..1042ff80 --- /dev/null +++ b/src/assets/diagrams/41_swap_layers.svg @@ -0,0 +1,17 @@ + +A swap layer is the first layer of the next filamentA stack with a 0.10 millimeter first layer and 0.04 millimeter regular layers switches to yellow before layer four. Layer tops and the material-change boundary have different Z heights. + + +A swap layer is the first layer of the next filament +Side view • 0.10 first / 0.04 regular + +Z 0.22 • layer 4Z 0.18 • layer 3Z 0.14 • layer 2Z 0.10 • layer 1Z 0.00 • plate +First layer + + +Read the layer number first +Start with purple.Print layers 1, 2 and 3.Swap before printing layer 4. +Boundary below yellow: 0.18 mmTop of yellow layer: 0.22 mmBoth heights describe the same swap. +Check where your slicer inserts the change. Do not scale the model in Z. +Illustrative stack. Your actual instructions come from the built model. + diff --git a/src/components/docs/DocsPage.tsx b/src/components/docs/DocsPage.tsx index b9fa6e8f..c98b421e 100644 --- a/src/components/docs/DocsPage.tsx +++ b/src/components/docs/DocsPage.tsx @@ -1,4 +1,5 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { ChevronDown } from 'lucide-react'; import { docs, defaultDocSlug } from '@/docs'; import type { DocLinkTarget, DocRecord, TocEntry } from '@/types/docs'; import { applyDocSeo } from '@/lib/seo'; @@ -30,18 +31,24 @@ const DOC_NAV_GROUPS = [ slugs: ['overview', 'quick-start'], }, { - id: 'workflow', - label: 'Workflow', + id: '3d-workflow', + label: '3D And Printing', nested: true, slugs: [ - 'loading-images', - 'reducing-colors', - 'dedithering-cleanup', '3d-mode', + 'auto-paint', + 'flat-paint', + 'calibration-workflows', 'calibration-theory', 'generating-exporting-output', ], }, + { + id: '2d-workflow', + label: '2D Image Preparation', + nested: true, + slugs: ['loading-images', 'image-adjustments', 'reducing-colors', 'dedithering-cleanup'], + }, { id: 'reference', label: 'Reference', @@ -55,6 +62,8 @@ export default function DocsPage() { const [activeDocSlug, setActiveDocSlug] = useState(initialTarget.docSlug); const [pendingHeading, setPendingHeading] = useState(initialTarget.headingSlug); const [activeHeading, setActiveHeading] = useState(initialTarget.headingSlug); + const [contentsOpen, setContentsOpen] = useState(false); + const [headingsOpen, setHeadingsOpen] = useState(false); const scrollRef = useRef(null); const activeDoc = findDoc(activeDocSlug); @@ -64,6 +73,8 @@ export default function DocsPage() { setActiveDocSlug(nextDoc.meta.slug); setPendingHeading(target.headingSlug); setActiveHeading(target.headingSlug); + setContentsOpen(false); + setHeadingsOpen(false); window.history.pushState(null, '', buildDocsPath(nextDoc.meta.slug, target.headingSlug)); }, []); @@ -75,6 +86,8 @@ export default function DocsPage() { setActiveDocSlug(nextDoc.meta.slug); setPendingHeading(target.headingSlug); setActiveHeading(target.headingSlug); + setContentsOpen(false); + setHeadingsOpen(false); }; window.addEventListener('hashchange', onLocationChange); window.addEventListener('popstate', onLocationChange); @@ -137,79 +150,99 @@ export default function DocsPage() {
@@ -224,39 +257,59 @@ export default function DocsPage() {
-