@litfamily/lithermes 1.0.29 → 1.0.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/README.md +12 -9
  2. package/README_Ko-KR.md +12 -9
  3. package/assets/lithermes-plugin/README.md +15 -2
  4. package/assets/lithermes-plugin/__init__.py +49 -10
  5. package/assets/lithermes-plugin/adhd_stack.py +228 -0
  6. package/assets/lithermes-plugin/core.py +30 -4
  7. package/assets/lithermes-plugin/core_commands.py +99 -0
  8. package/assets/lithermes-plugin/core_contexts.py +54 -4
  9. package/assets/lithermes-plugin/core_contract.py +2 -2
  10. package/assets/lithermes-plugin/core_routing.py +126 -0
  11. package/assets/lithermes-plugin/diagnostics.py +3 -2
  12. package/assets/lithermes-plugin/lit_mark.py +75 -0
  13. package/assets/lithermes-plugin/payload-version.json +470 -58
  14. package/assets/lithermes-plugin/plugin.yaml +1 -1
  15. package/assets/lithermes-plugin/scientific_visualization.py +23 -0
  16. package/assets/lithermes-plugin/skills/frontend-ui-ux/SKILL.md +7 -7
  17. package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/components.css +414 -0
  18. package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/fonts.json +42 -0
  19. package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/layouts/landing.html +164 -0
  20. package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/layouts/settings.html +114 -0
  21. package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/layouts/workspace.html +115 -0
  22. package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/styles/computational-brutalism.json +227 -0
  23. package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/styles/field-notes.json +205 -0
  24. package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/styles/graphite.json +200 -0
  25. package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/styles/meadow.json +199 -0
  26. package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/styles/neo-brutalism.json +222 -0
  27. package/assets/lithermes-plugin/skills/frontend-ui-ux/kit/ui.js +226 -0
  28. package/assets/lithermes-plugin/skills/frontend-ui-ux/references/README.md +2 -4
  29. package/assets/lithermes-plugin/skills/frontend-ui-ux/references/complete-contract.md +4 -4
  30. package/assets/lithermes-plugin/skills/frontend-ui-ux/references/craft-floor.md +10 -0
  31. package/assets/lithermes-plugin/skills/frontend-ui-ux/scripts/design-lock.mjs +400 -0
  32. package/assets/lithermes-plugin/skills/frontend-ui-ux/scripts/probe-rules.json +6 -1
  33. package/assets/lithermes-plugin/skills/frontend-ui-ux/scripts/probe.mjs +76 -4
  34. package/assets/lithermes-plugin/skills/lit-adhd/SKILL.md +194 -0
  35. package/assets/lithermes-plugin/skills/lit-adhd/references/brief-contract.md +55 -0
  36. package/assets/lithermes-plugin/skills/lit-adhd/references/card-examples.md +86 -0
  37. package/assets/lithermes-plugin/skills/lit-adhd/references/status-taxonomy.md +40 -0
  38. package/assets/lithermes-plugin/skills/lit-adhd/scripts/adhd.mjs +11 -0
  39. package/assets/lithermes-plugin/skills/lit-adhd/scripts/lib/collect.mjs +554 -0
  40. package/assets/lithermes-plugin/skills/lit-adhd/scripts/lib/gauge.mjs +89 -0
  41. package/assets/lithermes-plugin/skills/lit-adhd/scripts/lib/hermes-sessions.mjs +219 -0
  42. package/assets/lithermes-plugin/skills/lit-adhd/scripts/lib/next-step.mjs +101 -0
  43. package/assets/lithermes-plugin/skills/lit-adhd/scripts/lib/plan-task-rows.mjs +32 -0
  44. package/assets/lithermes-plugin/skills/lit-adhd/scripts/lib/redact.mjs +42 -0
  45. package/assets/lithermes-plugin/skills/lit-adhd/scripts/lib/secret-shapes.mjs +59 -0
  46. package/assets/lithermes-plugin/skills/lit-diagram-drawer/SKILL.md +7 -4
  47. package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/style-guide.md +20 -11
  48. package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-architecture.md +3 -3
  49. package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-dependency.md +1 -1
  50. package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-tree.md +3 -3
  51. package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-wardley.md +1 -1
  52. package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/verifier-guide.md +5 -0
  53. package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/diagram_quality.py +4 -4
  54. package/assets/lithermes-plugin/skills/lit-docx/SKILL.md +1 -1
  55. package/assets/lithermes-plugin/skills/lit-hijack/SKILL.md +239 -0
  56. package/assets/lithermes-plugin/skills/lit-hijack/references/capture-and-provenance.md +123 -0
  57. package/assets/lithermes-plugin/skills/lit-hijack/references/clean-room-build.md +128 -0
  58. package/assets/lithermes-plugin/skills/lit-hijack/references/distil-and-licence.md +128 -0
  59. package/assets/lithermes-plugin/skills/lit-hijack/references/gap-and-port-design.md +152 -0
  60. package/assets/lithermes-plugin/skills/lit-hijack/references/parity-and-report.md +131 -0
  61. package/assets/lithermes-plugin/skills/lit-hijack/scripts/hijack.mjs +995 -0
  62. package/assets/lithermes-plugin/skills/lit-plan/SKILL.md +1 -0
  63. package/assets/lithermes-plugin/skills/lit-pptx/SKILL.md +11 -6
  64. package/assets/lithermes-plugin/skills/lit-pptx/fonts/jetbrains-mono/JetBrainsMono-Bold.ttf +0 -0
  65. package/assets/lithermes-plugin/skills/lit-pptx/fonts/jetbrains-mono/JetBrainsMono-Regular.ttf +0 -0
  66. package/assets/lithermes-plugin/skills/lit-pptx/fonts/jetbrains-mono/OFL.txt +93 -0
  67. package/assets/lithermes-plugin/skills/lit-pptx/fonts/provenance.json +1 -0
  68. package/assets/lithermes-plugin/skills/lit-pptx/references/anti-slop-checklist.md +3 -0
  69. package/assets/lithermes-plugin/skills/lit-pptx/references/authoring-guide.md +1 -1
  70. package/assets/lithermes-plugin/skills/lit-pptx/references/consensus-protocol.md +1 -1
  71. package/assets/lithermes-plugin/skills/lit-pptx/references/direction-step.md +8 -2
  72. package/assets/lithermes-plugin/skills/lit-pptx/references/examples/13-engineering-review-computational-brutalism-ko.md +175 -0
  73. package/assets/lithermes-plugin/skills/lit-pptx/references/examples/14-launch-pitch-neo-brutalism-ko.md +156 -0
  74. package/assets/lithermes-plugin/skills/lit-pptx/references/examples/15-design-lecture-bauhaus-ko.md +141 -0
  75. package/assets/lithermes-plugin/skills/lit-pptx/references/examples/16-community-programme-riso-ko.md +160 -0
  76. package/assets/lithermes-plugin/skills/lit-pptx/references/examples/17-public-data-briefing-newsroom-ko.md +183 -0
  77. package/assets/lithermes-plugin/skills/lit-pptx/references/layout-families.md +1 -1
  78. package/assets/lithermes-plugin/skills/lit-pptx/references/tonalities/bauhaus.md +105 -0
  79. package/assets/lithermes-plugin/skills/lit-pptx/references/tonalities/computational-brutalism.md +111 -0
  80. package/assets/lithermes-plugin/skills/lit-pptx/references/tonalities/neo-brutalism.md +114 -0
  81. package/assets/lithermes-plugin/skills/lit-pptx/references/tonalities/newsroom.md +106 -0
  82. package/assets/lithermes-plugin/skills/lit-pptx/references/tonalities/riso.md +101 -0
  83. package/assets/lithermes-plugin/skills/lit-pptx/scripts/craft_extras.py +49 -0
  84. package/assets/lithermes-plugin/skills/lit-pptx/scripts/deck_output.py +4 -2
  85. package/assets/lithermes-plugin/skills/lit-pptx/scripts/lib/render-pack.js +96 -10
  86. package/assets/lithermes-plugin/skills/lit-pptx/scripts/lib/template-registry.js +50 -6
  87. package/assets/lithermes-plugin/skills/lit-pptx/templates/tonalities/bauhaus/pack.yaml +103 -0
  88. package/assets/lithermes-plugin/skills/lit-pptx/templates/tonalities/computational-brutalism/pack.yaml +99 -0
  89. package/assets/lithermes-plugin/skills/lit-pptx/templates/tonalities/neo-brutalism/pack.yaml +107 -0
  90. package/assets/lithermes-plugin/skills/lit-pptx/templates/tonalities/newsroom/pack.yaml +99 -0
  91. package/assets/lithermes-plugin/skills/lit-pptx/templates/tonalities/riso/pack.yaml +99 -0
  92. package/assets/lithermes-plugin/skills/lit-recap/SKILL.md +1 -1
  93. package/assets/lithermes-plugin/skills/lit-schematic/SKILL.md +144 -0
  94. package/assets/lithermes-plugin/skills/lit-schematic/examples/iso-heat-exchanger/build.mjs +38 -0
  95. package/assets/lithermes-plugin/skills/lit-schematic/examples/iso-heat-exchanger/scene.mjs +133 -0
  96. package/assets/lithermes-plugin/skills/lit-schematic/examples/journal-adsorption-rig/build.mjs +87 -0
  97. package/assets/lithermes-plugin/skills/lit-schematic/examples/pid-dosing-skid/build.mjs +85 -0
  98. package/assets/lithermes-plugin/skills/lit-schematic/references/cutaway-outputs.md +70 -0
  99. package/assets/lithermes-plugin/skills/lit-schematic/references/isometric-craft.md +101 -0
  100. package/assets/lithermes-plugin/skills/lit-schematic/references/journal-figures.md +72 -0
  101. package/assets/lithermes-plugin/skills/lit-schematic/references/kit-api.md +134 -0
  102. package/assets/lithermes-plugin/skills/lit-schematic/references/pfd-and-layout.md +53 -0
  103. package/assets/lithermes-plugin/skills/lit-schematic/references/pid-drafting.md +103 -0
  104. package/assets/lithermes-plugin/skills/lit-schematic/references/pid-symbols.md +163 -0
  105. package/assets/lithermes-plugin/skills/lit-schematic/references/verification.md +100 -0
  106. package/assets/lithermes-plugin/skills/lit-schematic/scripts/doctor.mjs +57 -0
  107. package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/figure.mjs +81 -0
  108. package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/fonts.mjs +27 -0
  109. package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/geom.mjs +113 -0
  110. package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/interactive.mjs +292 -0
  111. package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/isa.mjs +115 -0
  112. package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/iso.mjs +719 -0
  113. package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/legend-sheet.mjs +162 -0
  114. package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/pid.mjs +937 -0
  115. package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/png.mjs +132 -0
  116. package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/qa-core.mjs +658 -0
  117. package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/route.mjs +218 -0
  118. package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/sheet.mjs +890 -0
  119. package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/svg.mjs +82 -0
  120. package/assets/lithermes-plugin/skills/lit-schematic/scripts/lib/theme.mjs +115 -0
  121. package/assets/lithermes-plugin/skills/lit-schematic/scripts/motion.mjs +129 -0
  122. package/assets/lithermes-plugin/skills/lit-schematic/scripts/qa.mjs +92 -0
  123. package/assets/lithermes-plugin/skills/lit-schematic/scripts/render.mjs +233 -0
  124. package/assets/lithermes-plugin/skills/lit-schematic/scripts/scaffold.mjs +60 -0
  125. package/assets/lithermes-plugin/skills/lit-scientific-visualization/SKILL.md +19 -1
  126. package/assets/lithermes-plugin/skills/lit-typographic-motion/SKILL.md +12 -11
  127. package/assets/lithermes-plugin/skills/lit-typographic-motion/bin/motion.mjs +56 -2
  128. package/assets/lithermes-plugin/skills/lit-typographic-motion/bin/runtime.mjs +129 -4
  129. package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/THIRD_PARTY_NOTICES +9 -0
  130. package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/blender/runner.py +218 -0
  131. package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/blender.mjs +154 -0
  132. package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/board.mjs +132 -0
  133. package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/completion.mjs +48 -5
  134. package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/gate.mjs +13 -0
  135. package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/house.mjs +44 -0
  136. package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/scaffold.mjs +238 -0
  137. package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/score.mjs +643 -0
  138. package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/sound-dsp.mjs +21 -0
  139. package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/sound.mjs +171 -0
  140. package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/stage-qa.mjs +23 -3
  141. package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/stage.mjs +124 -17
  142. package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/styles.mjs +240 -0
  143. package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/treatment.mjs +152 -10
  144. package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/vendor/three/LICENSE +21 -0
  145. package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/vendor/three/addons/environments/RoomEnvironment.js +144 -0
  146. package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/vendor/three/addons/geometries/RoundedBoxGeometry.js +155 -0
  147. package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/vendor/three/three.module.js +54571 -0
  148. package/assets/lithermes-plugin/skills/lit-typographic-motion/recipes/hero-3d/expected.json +67 -0
  149. package/assets/lithermes-plugin/skills/lit-typographic-motion/recipes/hero-3d/index.html +139 -0
  150. package/assets/lithermes-plugin/skills/lit-typographic-motion/references/depth.md +74 -0
  151. package/assets/lithermes-plugin/skills/lit-typographic-motion/references/studio.md +87 -0
  152. package/assets/lithermes-plugin/skills/lit-typographic-motion/references/style-bibles.md +9 -2
  153. package/assets/lithermes-plugin/skills/lit-typographic-motion/references/treatment.md +24 -8
  154. package/assets/lithermes-plugin/skills/lit-typographic-motion/styles/paper.json +41 -0
  155. package/assets/lithermes-plugin/skills/lit-typographic-motion/styles/swiss-signal.json +41 -0
  156. package/assets/lithermes-plugin/skills/lit-typographic-motion/styles/terminalcore.json +42 -0
  157. package/assets/lithermes-plugin/skills/lit-typographic-motion/styles/tidal.json +41 -0
  158. package/assets/lithermes-plugin/skills/litresearch/SKILL.md +4 -0
  159. package/assets/lithermes-plugin/skills/readme-studio/SKILL.md +1 -1
  160. package/assets/lithermes-plugin/skills/review-work/SKILL.md +2 -0
  161. package/assets/lithermes-plugin/skills/start-work/SKILL.md +2 -1
  162. package/assets/lithermes-plugin/skills/visual-qa/references/complete-contract.md +3 -3
  163. package/package.json +1 -1
  164. package/readme-assets/badge-version.svg +1 -1
  165. package/src/lib/skillPayload.js +1 -1
@@ -0,0 +1,67 @@
1
+ {
2
+ "aspect": "2:1",
3
+ "beat": "The lid opens, the core rises and settles, and the lid closes.",
4
+ "brandWord": "LITHERMES",
5
+ "encode": {
6
+ "edgeFrames": 15,
7
+ "edgeQ": 97,
8
+ "q": 94
9
+ },
10
+ "fps": 20,
11
+ "hero": "A rounded case with a hinged lid and a lit core.",
12
+ "idea": "A case turns once and opens on its beat to show the lit core inside, beside a still name.",
13
+ "layers": {
14
+ "beat": "The lid opens on the core and a ring runs out across the floor.",
15
+ "mid": "The camera breathes twice per loop.",
16
+ "slow": "The case turns exactly once per loop."
17
+ },
18
+ "loopSec": 8,
19
+ "mode": "cover",
20
+ "motto": {
21
+ "from": "the motto painted on the repository artwork",
22
+ "source": "project",
23
+ "text": "KEEP THE WORK LIT."
24
+ },
25
+ "note": "PORT_UNMEASURED: the row below is the ancestor's GPU-rung measurement (Apple M5 Pro, three.js r170, libwebp); re-render through this renderer and replace the row before adding hero-3d to qa/cover-recipes.js.",
26
+ "recipe": "hero-3d",
27
+ "recipeReason": "One object acting once per loop says what the project holds better than a type pattern.",
28
+ "request": "A README motion cover for LitHermes with a product object that opens.",
29
+ "row": {
30
+ "bytes": 1060856,
31
+ "longestStillSec": 0.05,
32
+ "medianD": 0.002485,
33
+ "movingFrac": 1,
34
+ "seamLocal": 1.199,
35
+ "spike": 3.684
36
+ },
37
+ "schema": "lithermes.cover-recipe/v1",
38
+ "settings": {
39
+ "encode": {
40
+ "edgeFrames": 15,
41
+ "edgeQ": 97,
42
+ "method": 4,
43
+ "q": 94
44
+ },
45
+ "fps": 20,
46
+ "frames": 160,
47
+ "size": [
48
+ 1000,
49
+ 500
50
+ ]
51
+ },
52
+ "system": {
53
+ "copies": "One case, one core, one ring.",
54
+ "offset": "The ring trails the lid by a tenth of the loop.",
55
+ "rule": "One hinge rule and one turn rule on one object."
56
+ },
57
+ "title": {
58
+ "box": [
59
+ 0.05,
60
+ 0.36,
61
+ 0.43,
62
+ 0.14
63
+ ],
64
+ "kind": "live"
65
+ },
66
+ "verdict": "PORT_UNMEASURED"
67
+ }
@@ -0,0 +1,139 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <!-- Recipe D, hero 3D: one product object, lit in a small studio, acting its beat once per loop. A
6
+ worked example: a rounded case turns exactly once per loop (slow layer), the camera breathes twice
7
+ (mid layer), and once per loop the lid opens, a lit core rises and settles back and the lid closes,
8
+ while a ring runs out across the floor (the beat). The word sits still on the left. Drawn with the
9
+ pinned three.js build on the GPU rung (software when the GPU is missing). Replace the word, the
10
+ motto and the HERO block with the project's own object. -->
11
+ <link rel="stylesheet" href="/lit/fonts.css">
12
+ <script src="/lit/loop-kit.js"></script>
13
+ <script type="importmap">{ "imports": { "three": "/lit/three/three.module.js", "three/addons/": "/lit/three/addons/" } }</script>
14
+ <style>
15
+ html, body { margin: 0; width: 1200px; height: 600px; overflow: hidden; background: #0b0f16; }
16
+ canvas { position: absolute; left: 0; top: 0; width: 1200px; height: 600px; display: block; }
17
+ </style>
18
+ </head>
19
+ <body>
20
+ <canvas id="world"></canvas>
21
+ <canvas id="type" width="2400" height="1200"></canvas>
22
+ <script type="module">
23
+ import * as THREE from "three";
24
+ import { RoomEnvironment } from "three/addons/environments/RoomEnvironment.js";
25
+ import { RoundedBoxGeometry } from "three/addons/geometries/RoundedBoxGeometry.js";
26
+
27
+ const { TAU, clamp, fract, ease } = LitLoop;
28
+ const span = (a, b, t) => clamp((t - a) / (b - a));
29
+ const C = { bg: "#0b0f16", ivory: "#f2efdf", dim: "#8b8f8f", orange: "#ff6337", shell: "#d9d4c4", inner: "#1a2230" };
30
+ const W = 1200, H = 600;
31
+ const AIM = { x: 860, y: 318 };
32
+
33
+ // ---- the world: renderer, studio light, floor ----
34
+ const glCanvas = document.getElementById("world");
35
+ const renderer = new THREE.WebGLRenderer({ canvas: glCanvas, antialias: true, alpha: true, preserveDrawingBuffer: true });
36
+ renderer.setPixelRatio(window.devicePixelRatio);
37
+ renderer.setSize(W, H, false);
38
+ renderer.setClearColor(0x000000, 0);
39
+ renderer.outputColorSpace = THREE.SRGBColorSpace;
40
+ renderer.toneMapping = THREE.ACESFilmicToneMapping;
41
+ renderer.shadowMap.enabled = true;
42
+ renderer.shadowMap.type = THREE.PCFSoftShadowMap;
43
+ const scene = new THREE.Scene();
44
+ scene.environment = new THREE.PMREMGenerator(renderer).fromScene(new RoomEnvironment(), 0.04).texture;
45
+ scene.environmentIntensity = 0.55;
46
+ const cam = new THREE.PerspectiveCamera(30, W / H, 0.1, 60);
47
+ cam.setViewOffset(W, H, W / 2 - AIM.x, H / 2 - AIM.y, W, H);
48
+ const key = new THREE.DirectionalLight(0xffffff, 2.4);
49
+ key.position.set(-3, 6, 4);
50
+ key.castShadow = true;
51
+ key.shadow.mapSize.set(2048, 2048);
52
+ key.shadow.radius = 5;
53
+ key.shadow.bias = -0.0004;
54
+ key.shadow.normalBias = 0.03;
55
+ key.shadow.camera.left = -4; key.shadow.camera.right = 4; key.shadow.camera.top = 4; key.shadow.camera.bottom = -4;
56
+ const rim = new THREE.DirectionalLight(0xffb08f, 1.1);
57
+ rim.position.set(4, 2.5, -5);
58
+ scene.add(key, rim);
59
+ const floor = new THREE.Mesh(new THREE.PlaneGeometry(30, 30), new THREE.ShadowMaterial({ opacity: 0.35 }));
60
+ floor.rotation.x = -Math.PI / 2;
61
+ floor.receiveShadow = true;
62
+ scene.add(floor);
63
+ const ring = new THREE.Mesh(new THREE.RingGeometry(0.98, 1, 128), new THREE.MeshBasicMaterial({ color: C.orange, transparent: true, opacity: 0 }));
64
+ ring.rotation.x = -Math.PI / 2;
65
+ ring.position.y = 0.002;
66
+ scene.add(ring);
67
+
68
+ // ---- HERO: the product object (a case with a hinged lid and a lit core) ----
69
+ const shell = new THREE.MeshPhysicalMaterial({ color: C.shell, roughness: 0.32, metalness: 0.05, clearcoat: 0.6, clearcoatRoughness: 0.2 });
70
+ const inner = new THREE.MeshStandardMaterial({ color: C.inner, roughness: 0.8 });
71
+ const HERO = new THREE.Group();
72
+ const base = new THREE.Mesh(new RoundedBoxGeometry(1.6, 0.62, 1.1, 6, 0.12), shell);
73
+ base.position.y = 0.31;
74
+ const well = new THREE.Mesh(new RoundedBoxGeometry(1.38, 0.5, 0.88, 4, 0.08), inner);
75
+ well.position.y = 0.4;
76
+ const hinge = new THREE.Group();
77
+ hinge.position.set(0, 0.64, -0.55);
78
+ const lid = new THREE.Mesh(new RoundedBoxGeometry(1.6, 0.16, 1.1, 6, 0.07), shell);
79
+ lid.position.set(0, 0.08, 0.55);
80
+ hinge.add(lid);
81
+ const coreMat = new THREE.MeshStandardMaterial({ color: C.orange, emissive: C.orange, emissiveIntensity: 0, roughness: 0.35 });
82
+ const core = new THREE.Mesh(new THREE.IcosahedronGeometry(0.24, 3), coreMat);
83
+ const glow = new THREE.PointLight(C.orange, 0, 4, 2);
84
+ core.add(glow);
85
+ for (const m of [base, lid, core]) m.castShadow = true;
86
+ base.receiveShadow = true;
87
+ HERO.add(base, well, hinge, core);
88
+ scene.add(HERO);
89
+
90
+ // The beat: open 0.28-0.44, hold, close 0.62-0.78; zero at both ends, so the loop closes.
91
+ const openAt = (t) => ease.smooth(span(0.28, 0.44, t)) * (1 - ease.smooth(span(0.62, 0.78, t)));
92
+
93
+ function drawWorld(t) {
94
+ HERO.rotation.y = -0.5 + TAU * t;
95
+ const open = openAt(t);
96
+ hinge.rotation.x = -1.45 * open;
97
+ const rise = ease.outBack(span(0.36, 0.5, t)) * (1 - ease.smooth(span(0.58, 0.7, t)));
98
+ core.position.y = 0.42 + 0.6 * rise;
99
+ core.rotation.y = TAU * 2 * t;
100
+ coreMat.emissiveIntensity = 1.1 * open;
101
+ glow.intensity = 3 * open;
102
+ const wave = ease.outCubic(span(0.38, 0.72, t));
103
+ ring.scale.setScalar(0.9 + 1.3 * wave);
104
+ ring.material.opacity = 0.55 * open * (1 - wave);
105
+ const breathe = Math.sin(TAU * 2 * t);
106
+ cam.position.set(5.8 * Math.sin(0.35), 2.3 + 0.12 * breathe, 5.8 * Math.cos(0.35));
107
+ cam.lookAt(0, 0.62 + 0.04 * breathe, 0);
108
+ renderer.render(scene, cam);
109
+ }
110
+
111
+ // ---- the word, set once ----
112
+ const ctx = document.getElementById("type").getContext("2d");
113
+ ctx.scale(2, 2);
114
+ function drawType(mask) {
115
+ ctx.clearRect(0, 0, W, H);
116
+ if (mask) { ctx.fillStyle = "#000"; ctx.fillRect(0, 0, W, H); }
117
+ ctx.textBaseline = "alphabetic";
118
+ ctx.fillStyle = mask ? "#fff" : C.ivory;
119
+ ctx.font = '800 84px "JetBrains Mono"';
120
+ ctx.fillText("LITHERMES", 70, 292);
121
+ if (mask) return;
122
+ ctx.font = '500 18px "JetBrains Mono"';
123
+ ctx.fillStyle = C.dim;
124
+ let mx = 74;
125
+ for (const ch of "KEEP THE WORK ") { ctx.fillText(ch, mx, 338); mx += 19.6; }
126
+ ctx.fillStyle = C.orange;
127
+ ctx.font = '700 18px "JetBrains Mono"';
128
+ for (const ch of "LIT.") { ctx.fillText(ch, mx, 338); mx += 19.6; }
129
+ }
130
+
131
+ window.renderFrame = (t, o = {}) => {
132
+ glCanvas.style.visibility = o.mask ? "hidden" : "visible";
133
+ if (!o.mask) drawWorld(fract(t));
134
+ drawType(Boolean(o.mask));
135
+ };
136
+ document.fonts.load('800 84px "JetBrains Mono"').then(() => document.fonts.load('500 18px "JetBrains Mono"')).then(() => { window.renderFrame(0); window.ready = true; });
137
+ </script>
138
+ </body>
139
+ </html>
@@ -0,0 +1,74 @@
1
+ # Depth and story
2
+
3
+ Motion films read like stories because shots have protagonists, turns and
4
+ pay-offs, and depth answers how far the eye travels. This reference condenses
5
+ the story file format and the depth rules; the renderer and QA enforce them.
6
+
7
+ ## Story and protagonist
8
+
9
+ The treatment carries the narrative contract: a **story** (`expect` what the
10
+ viewer expects, `turn` what happens instead, `beat` the shot where the turn
11
+ lands, `payoff` what the ending gives) and, on the stage path, a
12
+ **protagonist** (one character or hero object the eye follows: a name, a
13
+ look, and one act per shot, the acts covering at least half the film
14
+ including the turn shot). The board's per-shot captions carry the turns so
15
+ the read of the board is the read of the story.
16
+
17
+ ## The four depths
18
+
19
+ Each shot is staged at one of four depths, declared in the treatment:
20
+
21
+ | Depth | Eye travel | Camera | Layers |
22
+ |---|---|---|---|
23
+ | `flat` | none: the page is a poster | locked | type + ground only |
24
+ | `near` | small parallax on the hero | dolly ≤ 6 % | hero lifts off ground |
25
+ | `deep` | the hero travels through the world | dolly + focus pull | foreground, hero, ground |
26
+ | `fold` | the world turns its page | one rotation, one axis | double-sided panel |
27
+
28
+ A film uses at most two depths, and the pay-off shot is never `flat`. Depth
29
+ changes only on a `match` or `morph` hand-off, so the eye never teleports.
30
+
31
+ ## GPU ladder
32
+
33
+ A film declares the cheapest rung that can stage it honestly: a 2D film takes
34
+ the software rung (SwiftShader, CPU raster); a `depth: 3d` film takes the
35
+ platform's GPU rung first (ANGLE/Metal/GL/D3D11), and falls back to software
36
+ only with a warning, rendering the same frames. Only when neither rung has
37
+ WebGL is it exit 11. The rung is chosen from the treatment (`depth`), never
38
+ by the page. `paper` stays 2D: hand-drawn calm never reaches for a GPU.
39
+ `terminalcore` stays 2D too: phosphor has no third dimension.
40
+
41
+ ## The Blender rung
42
+
43
+ A `depth: 3d` film whose treatment says `render3d: "blender"` renders its
44
+ world offline in Blender and shows the path-traced plate under its HTML type.
45
+ The scene is `stage/scene.py`, written against the `lit` helpers the runner
46
+ puts in scope; `motion.mjs blender --out DIR` renders one still at every beat
47
+ midpoint into `stage/plate-preview/`, `--final` renders the plate sequence
48
+ into `stage/plate/` plus `plate.json`, and the stage refuses to render without
49
+ a plate that matches its frames (exit 17). Preview first, open the stills,
50
+ compare them with any reference frames the user gave and with what the GPU
51
+ rung built, then render the final plate. A film that shows its plate shares
52
+ its run with a 3-D-of-any-kind page: the same scene, receipt and frames
53
+ render exactly the same plate again. Without Blender installed the command
54
+ falls back to the GPU rung instead of rendering; without `scene.py` it is
55
+ exit 17.
56
+
57
+ ## Painted light and replay identity
58
+
59
+ Light is painted, never computed live: the scaffold bakes one key light, one
60
+ hemisphere light in the style's colours and one shadow-only floor into the
61
+ page, with the shadow bias that keeps a turning object's self-shadow from
62
+ flickering (`-0.0004` / `0.03`; without them the acne reads as flashes and
63
+ fails the gate). A Blender plate shows path-traced light under the same type;
64
+ the GPU rung renders the same baked page, so both agree to the eye.
65
+
66
+ For WebGL the page creates its context with `preserveDrawingBuffer: true`; a
67
+ page that asks for WebGL and gets none on any rung exits 11. A replay is
68
+ frame-identical: the same treatment on the same rung in a fresh browser must
69
+ reproduce the sampled frames pixel for pixel, or the render stops with exit
70
+ 18. Chrome rasterizes every tile in full on the CPU, so blurs, shadows and
71
+ shaders replay pixel for pixel; one quirk remains, and the replay paints and
72
+ captures every frame exactly like the master because of it. Seeds are never
73
+ time-based. The rung is chosen from the treatment (`depth`) or the cover
74
+ recipe, never by the page.
@@ -0,0 +1,87 @@
1
+ # House styles
2
+
3
+ Four house styles ship as data in `styles/<id>.json` (schema
4
+ `litfamily.motion-style/v1`, validated by `engine/styles.mjs` and refused with
5
+ the bad field named). A film's treatment names exactly one; the validator checks
6
+ it against the pick rules below, the renderer serves it as `/lit/style.css`
7
+ and `/lit/style.js`, and the text QA judges copy against it. The style bibles in
8
+ `references/style-bibles.md` carry the look of each; this file carries the
9
+ rules. `node <skill>/bin/motion.mjs styles [--out DIR]` prints the table and,
10
+ with `--out`, writes the machine-readable `styles.json` catalog.
11
+
12
+ | Style | Type preset | Best for |
13
+ |---|---|---|
14
+ | `swiss-signal` | swiss-signal | the default: precise, hard cuts, teal signal |
15
+ | `tidal` | tidal | brand moods: slow flow, coral moment |
16
+ | `terminalcore` | terminalcore | terminal briefs: phosphor type, no ease |
17
+ | `paper` | none (stage only) | warm explainers; the type path refuses it |
18
+
19
+ ## Picking
20
+
21
+ A style named in the request wins (`paper style`, `tidal`, `터미널코어`…).
22
+ Otherwise the project's house style (`motion-house.json` beside the output
23
+ folder, written by a render that passes its gate) holds while it exists.
24
+ Otherwise the keyword table in `style-bibles.md` auto-picks (`terminal` /
25
+ `hacker`, `gradient` / `wave`, `warm` / `paper`…). Otherwise an `explainer`
26
+ takes `paper` and a `brand-mood` takes `tidal`. Otherwise the default
27
+ `swiss-signal`. The manifest records `{ style, source, reason }`.
28
+
29
+ ## Register
30
+
31
+ Rich is the default: every layer the treatment's world describes is drawn,
32
+ labelled, lit and moved. Minimal is only for a calm, quiet or minimal ask
33
+ (`minimal`, `calm`, `잔잔한`, `차분한`…): the core palette, two layers, one
34
+ camera move at most, no accents. A minimal film that reaches for a role
35
+ accent, or a rich film the request asked calm, fails validation.
36
+
37
+ ## Palette, type, motion
38
+
39
+ Every colour on a stage page comes from the style's palette plus, on a rich
40
+ film, the style's role accents (`style.accents`, each with a role and a
41
+ `3:1`-on-ground colour). Copy uses the text roles (`style.textRoles`); display
42
+ and headline type uses ink. Ink on ground needs `7:1`, muted `4.5:1`. Type
43
+ uses the style's faces (Hangul falls back to Pretendard) on the style's
44
+ descending scale steps, with `keep-all` word breaking. Entrances, moves and
45
+ hand-offs use the style's ease curves and durations; an exit is never longer
46
+ than the hero move. Nothing eases on `terminalcore`. The banned list in each
47
+ style file is closed: the page never uses what its style bans.
48
+
49
+ ## Layouts per shot
50
+
51
+ One grid per layout, named per shot, mapped per format (`LAYOUTS` in
52
+ `engine/styles.mjs`): `title`, `split`, `split-alt`, `stage`, `hero`, `full`
53
+ (a full shot is subject only and shows no copy). Every type zone sits inside
54
+ the central 90 % title-safe area. Adjacent shots never share a layout; a film
55
+ of four or more shots uses at least three. A hand-off (`cut`, `match`,
56
+ `wipe`, `push`, `iris`, `dissolve`, `morph`) comes from the style's list; the
57
+ last shot's transition is `end`. Every shot names its hero: the one move the
58
+ eye follows.
59
+
60
+ ## The board
61
+
62
+ Round 1 ends with a board, not a preview: `stills/board.png`, one keyframe
63
+ per shot with number, time, layout and hand-off under it, the shot's type
64
+ zone dashed on the frame, the house style (name, palette, type) plus format,
65
+ length and sound in the header, and the layout check in the footer. The check
66
+ runs the text and style rules on the board frames (`stills/check.json`);
67
+ a FAIL ends the round with exit 13 (`BOARD_CHECK_FAIL`, the QA-fail exit with
68
+ the board named). Read the board with `read_file`, record the round with
69
+ `look`, make the change, then render.
70
+
71
+ ## The gate rule names
72
+
73
+ Older notes name six text rules that have no runtime of their own. They are
74
+ contracts on the page, enforced by the QA checks and look rounds below; the
75
+ mapping is fixed and every row has a RED test:
76
+
77
+ | Doc name | Enforced by |
78
+ |---|---|
79
+ | `TEXT-OVERLAP` | no two settled copy lines overlap (`text-title-safe` overlap row at the settled frames) |
80
+ | `TEXT-ON-STYLE` | copy uses the style's faces, roles and scale steps (`fonts`, `text-title-safe` family row, type scale) |
81
+ | `TEXT-ZONE` | settled copy sits in the shot's type zone (`text-title-safe` zone row + board zone guide) |
82
+ | `FLAT-FRAME` | no empty dark run past twice the scene hold floor (`MO-D-03` in `gate.mjs`) |
83
+ | `DEAD-AIR` | every beat's midpoint shows a non-text image (`non-text-presence` in `stage-qa.mjs`, WARN at 1.5x) |
84
+ | `RICH-FILL` | rich films use the style's regions: copy roles plus at least one accent (`stage-qa` role coverage on rich treatments) |
85
+
86
+ `MO-D-03`'s floor is a calibration constant: it changes only with a new
87
+ calibration table, never to let a film pass.
@@ -36,11 +36,18 @@ merely ends. An explicit `"style"` in the brief always wins over this table.
36
36
  The report labels a style you chose as `agent default`; it says
37
37
  `user-specified` only when the user's own request named that style.
38
38
 
39
- | Brief mentions | Preset |
39
+ | Brief mentions | Style |
40
40
  |---|---|
41
41
  | 터미널, 해커 / terminal, hacker, CRT | `terminalcore` |
42
42
  | 물결, 파도, 잔잔한, 흐름 / gradient, wave, tide, calm | `tidal` |
43
- | anything else | `swiss-signal` |
43
+ | 따뜻한, 밝은, 종이, 손그림, 포근한, 아기자기 / warm, cozy, bright, paper, handmade, hand-drawn | `paper` (stage only) |
44
+ | anything else | the default `swiss-signal` |
45
+
46
+ A style named in the request wins; then the project's house style
47
+ (`motion-house.json` beside the output folder, written by a passed render),
48
+ then the keyword table above, then the genre (`explainer` takes `paper`,
49
+ `brand-mood` takes `tidal`), then the default. The manifest records the pick
50
+ and the reason.
44
51
 
45
52
  `system`, `status` and a bare `flow` are deliberately not keywords: they appear
46
53
  in payment-system, design-system and workflow briefs that have nothing to do
@@ -57,7 +57,11 @@ span is removed from it.
57
57
  | `audience`, `channel` | Who watches, and where it plays. |
58
58
  | `format`, `formatReason` | `16:9` (1920×1080) or `9:16` (1080×1920), with a reason tied to `channel`. |
59
59
  | `durationSec` | 4 to 90. Unless the user asked for a length, `announcement`, `event`, `explainer` and `motion-graphics` run at least 10 s. |
60
- | `beats[]` | `{t0, t1, purpose, onScreen, motion, sound}` each. They cover 0 to `durationSec` with no gap over 0.25 s, every beat lasts at least 1.2 s, and there are at least as many beats as the genre's arc has stages. |
60
+ | `beats[]` | `{t0, t1, purpose, onScreen, motion, sound}` each, plus `layout`, `hero` and `transition` on the stage path. They cover 0 to `durationSec` with no gap over 0.25 s, every beat lasts at least 1.2 s, and there are at least as many beats as the genre's arc has stages. |
61
+ | `story` | `{expect, turn, payoff}` (one or two sentences each; the turn differs from the expectation) and `beat` (the shot where the turn lands: after the opening, before the end). A genre arc alone is an information order, not a story. |
62
+ | `protagonist` | Stage path only: `{name, kind: character or object, look, acts[]}`. One drawn character or hero object that acts across the film: one act per shot, acts covering at least half the film, including the turn shot. |
63
+ | `depth`, `render3d` | `depth` is `2d` or `3d` (a stage-path route). A `depth3d` subject device needs `depth: 3d`, and `3d` needs the subject. `render3d` is `three` (the GPU rung, the default) or `blender` (the offline Cycles rung) and needs `depth: 3d`. |
64
+ | `world` | Stage path, rich register only: `{layers[], labels[], camera[]}`. At least 3 depth layers back to front, at least 6 labelled parts the viewer reads (4 words each at most), and camera moves covering at least half the shots. |
61
65
  | `subject` | `{name, source: user or invented, specifics[]}`. When the request names no specific subject, invent one: a name plus at least 2 concrete specifics (what it is or does, for whom, one distinctive detail). |
62
66
  | `visualDevices[]` | `{kind, role: subject, support or texture, beats[]}`, where `beats` lists beat indexes from 0. Kinds: `illustration`, `diagram`, `chart`, `icon`, `shape`, `path`, `mask`, `depth3d`, `particles`, `grid`, `gradient`, `photo-texture`. |
63
67
  | `typePlan` | `{faces[], hierarchy, maxWordsOnScreen}`. Faces come from this product's verified set: Pretendard, Archivo, Galmuri9, VT323, Silkscreen, MesloLGS NF. |
@@ -89,13 +93,21 @@ span is removed from it.
89
93
 
90
94
  ### Sound rules
91
95
 
92
- - `generated` is the default under bare `lit`, on both paths. The `sound`
93
- subcommand builds a deterministic bed from the treatment: tempo, pulse and a
94
- pad chord progression, plus accents only where a beat's `sound` field asks
95
- (a hit on a cut, a rise into a change, a closing cadence). `sound.palette` is
96
- one of `soft-mallet`, `warm-keys`, `glass-pulse` or `low-strings`; key and
97
- tempo follow from the treatment, so two films rarely share a bed. The reply
98
- labels the bed as generated.
96
+ - `score` is the default for rich films, built per film from the film itself:
97
+ the words seed its key, mode, tempo, progression, motif and percussion, the
98
+ beats arrange it (intro, build, the drop on the turn, break, outro), and the
99
+ `sound` subcommand writes `sound/score.wav`, one stem per part in
100
+ `sound/stems/` and the cue plan in `sound-cues.json`. The reply labels the
101
+ score as generated. `generated` is the bed for minimal films only: tempo,
102
+ pulse and a pad chord progression, plus accents only where a beat's `sound`
103
+ field asks (a hit on a cut, a rise into a change, a closing cadence).
104
+ `sound.palette` is one of `soft-mallet`, `warm-keys`, `glass-pulse` or
105
+ `low-strings`; key and tempo follow from the treatment, so two films rarely
106
+ share a bed.
107
+ - On the stage path a `score` or `generated` film lists at least 2 on-screen
108
+ events that make a sound (`sound.events`: `{t, on, kind}`, `kind` one of
109
+ `tap`, `hit`, `whoosh`, `chime`), at least half of them away from the cuts.
110
+ The score plays them on screen; the bed accents them where a beat asks.
99
111
  - `supplied`: the user's WAV, named in `sound.file`, relative to the output dir.
100
112
  - `authored`: a WAV you wrote into the stage dir (`stage/*.wav`).
101
113
  - `none` only when the user asked for silence, or when the channel plays muted
@@ -143,6 +155,10 @@ mostly equal this example's (`copiedExample`). Do not copy it; write your own.
143
155
  "beats": [
144
156
  { "t0": "<start s>", "t1": "<end s>", "purpose": "<arc stage>", "onScreen": "<what is drawn>", "motion": "<how it moves>", "sound": "<what the sound does here>" }
145
157
  ],
158
+ "story": { "expect": "<what the viewer expects>", "turn": "<what happens instead>", "beat": "<shot index of the turn>", "payoff": "<what the ending gives>" },
159
+ "protagonist": { "name": "<the character or hero object>", "kind": "<character or object>", "look": "<shape, material, colour role, scale>", "acts": [{ "beat": "<beat index>", "action": "<what it does in this shot>" }] },
160
+ "depth": "<2d or 3d>",
161
+ "world": { "layers": ["<depth layer, back to front>"], "labels": ["<part the viewer reads>"], "camera": [{ "beat": "<beat index>", "move": "<push-in, truck, crane, orbit, rack focus>" }] },
146
162
  "subject": { "name": "<a specific name>", "source": "<user or invented>", "specifics": ["<what it is or does>", "<for whom>", "<one distinctive detail>"] },
147
163
  "visualDevices": [
148
164
  { "kind": "<device kind>", "role": "<subject, support or texture>", "beats": ["<beat index>"] }
@@ -0,0 +1,41 @@
1
+ {
2
+ "schema": "litfamily.motion-style/v1",
3
+ "id": "paper",
4
+ "name": "Paper",
5
+ "summary": "A warm paper ground, near-black ink, one terracotta signal and one blue moment; soft springs, hand-drawn calm.",
6
+ "light": true,
7
+ "typePreset": null,
8
+ "palette": { "ground": "#F3EEE5", "surface": "#E6DED0", "ink": "#1D1B18", "muted": "#5B564E", "signal": "#B0452A", "accent": "#2B5D8E", "line": "#C9BFAE" },
9
+ "accents": [{ "role": "growth and done", "color": "#3F7D3A" }, { "role": "a second data series", "color": "#7A3E7A" }, { "role": "a warning or a date", "color": "#8A6418" }, { "role": "a third data series", "color": "#1F6F6B" }],
10
+ "textRoles": ["ink", "muted", "signal", "accent", "ground"],
11
+ "faces": {
12
+ "display": { "family": "Pretendard", "weight": 700 },
13
+ "headline": { "family": "Pretendard", "weight": 700 },
14
+ "body": { "family": "Pretendard", "weight": 400 },
15
+ "label": { "family": "MesloLGS NF", "weight": 400 }
16
+ },
17
+ "scale": {
18
+ "16:9": { "display": 112, "headline": 68, "body": 40, "label": 26 },
19
+ "9:16": { "display": 108, "headline": 74, "body": 46, "label": 32 }
20
+ },
21
+ "leading": { "display": 1.15, "headline": 1.25, "body": 1.6, "label": 1.4 },
22
+ "motion": {
23
+ "ease": { "enter": [0.22, 1, 0.36, 1], "move": [0.65, 0, 0.35, 1], "exit": [0.55, 0, 1, 0.45] },
24
+ "dur": { "micro": 0.18, "move": 0.55, "hero": 0.8, "exit": 0.32 },
25
+ "stagger": { "letter": 0.03, "word": 0.09, "item": 0.1 },
26
+ "spring": { "micro": { "zeta": 0.85, "hz": 3.5 }, "panel": { "zeta": 0.8, "hz": 2 }, "headline": { "zeta": 0.95, "hz": 2.2 }, "subject": { "zeta": 0.6, "hz": 1.8 }, "camera": { "zeta": 1, "hz": 0.5 } },
27
+ "secondary": { "delay": 0.15, "travel": 0.6 },
28
+ "ambient": { "travel": 0.04 },
29
+ "push": 0.02
30
+ },
31
+ "transitions": ["cut", "match", "wipe", "iris", "push"],
32
+ "ground": { "kind": "flat" },
33
+ "sound": { "timbre": "soft-keys", "key": "F", "mode": "major", "tempo": 96 },
34
+ "score": { "genre": "garage" },
35
+ "beds": [
36
+ { "timbre": "soft-keys", "key": "F", "mode": "major", "tempo": 96 },
37
+ { "timbre": "felt-strings", "key": "G", "mode": "major", "tempo": 88 },
38
+ { "timbre": "glass", "key": "C", "mode": "major", "tempo": 108 }
39
+ ],
40
+ "bans": ["drop shadows that float type", "neon or glow", "gradients on type", "a saturated colour with no role", "bouncy type"]
41
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "schema": "litfamily.motion-style/v1",
3
+ "id": "swiss-signal",
4
+ "name": "Swiss signal",
5
+ "summary": "Ink ground, bone type, one teal signal and one amber moment; type lands precisely and cuts hard.",
6
+ "light": false,
7
+ "typePreset": "swiss-signal",
8
+ "palette": { "ground": "#0C0E13", "surface": "#171B24", "ink": "#E9EBE4", "muted": "#A4A9AF", "signal": "#0F7A82", "accent": "#D9A441", "line": "#4B5058" },
9
+ "accents": [{ "role": "state under review", "color": "#E2725B" }, { "role": "state planned", "color": "#9B8CFF" }, { "role": "state done", "color": "#8FC25A" }, { "role": "state in progress", "color": "#5BA8E0" }],
10
+ "textRoles": ["ink", "muted", "signal", "accent", "ground"],
11
+ "faces": {
12
+ "display": { "family": "Archivo", "weight": 900, "stretch": "100%" },
13
+ "headline": { "family": "Archivo", "weight": 700, "stretch": "100%" },
14
+ "body": { "family": "Pretendard", "weight": 400 },
15
+ "label": { "family": "MesloLGS NF", "weight": 400 }
16
+ },
17
+ "scale": {
18
+ "16:9": { "display": 128, "headline": 76, "body": 40, "label": 26 },
19
+ "9:16": { "display": 120, "headline": 80, "body": 46, "label": 32 }
20
+ },
21
+ "leading": { "display": 1.1, "headline": 1.2, "body": 1.55, "label": 1.4 },
22
+ "motion": {
23
+ "ease": { "enter": [0.16, 1, 0.3, 1], "move": [0.65, 0, 0.35, 1], "exit": [0.7, 0, 0.84, 0] },
24
+ "dur": { "micro": 0.15, "move": 0.45, "hero": 0.6, "exit": 0.28 },
25
+ "stagger": { "letter": 0.025, "word": 0.07, "item": 0.08 },
26
+ "spring": { "micro": { "zeta": 1, "hz": 4 }, "panel": { "zeta": 0.9, "hz": 2.2 }, "headline": { "zeta": 1, "hz": 2.6 }, "subject": { "zeta": 0.8, "hz": 1.8 }, "camera": { "zeta": 1, "hz": 0.5 } },
27
+ "secondary": { "delay": 0.15, "travel": 0.6 },
28
+ "ambient": { "travel": 0.03 },
29
+ "push": 0.02
30
+ },
31
+ "transitions": ["cut", "wipe", "match", "push"],
32
+ "ground": { "kind": "flat", "grid": true },
33
+ "sound": { "timbre": "glass", "key": "A", "mode": "minor", "tempo": 104 },
34
+ "score": { "genre": "house" },
35
+ "beds": [
36
+ { "timbre": "glass", "key": "A", "mode": "minor", "tempo": 104 },
37
+ { "timbre": "pulse-synth", "key": "D", "mode": "minor", "tempo": 112 },
38
+ { "timbre": "soft-keys", "key": "C", "mode": "major", "tempo": 96 }
39
+ ],
40
+ "bans": ["glow or bloom on type", "an accent colour with no role", "centred fade-in as the only move", "overshoot or bounce on type", "particles as decoration", "gradients behind type"]
41
+ }
@@ -0,0 +1,42 @@
1
+ {
2
+ "schema": "litfamily.motion-style/v1",
3
+ "id": "terminalcore",
4
+ "name": "Terminalcore",
5
+ "summary": "A navy terminal: phosphor type that appears at typing speed, one signal hue, hard cuts, nothing eases.",
6
+ "light": false,
7
+ "typePreset": "terminalcore",
8
+ "palette": { "ground": "#05070A", "surface": "#0C1116", "ink": "#39FF6A", "muted": "#7C8B93", "signal": "#39FF6A", "line": "#1E2A33" },
9
+ "accents": [{ "role": "a warning line", "color": "#FFB23F" }, { "role": "an error line", "color": "#FF6B6B" }, { "role": "a path or a link", "color": "#6CA8FF" }],
10
+ "textRoles": ["ink", "muted", "signal", "ground"],
11
+ "faces": {
12
+ "display": { "family": "VT323", "weight": 400 },
13
+ "headline": { "family": "VT323", "weight": 400 },
14
+ "body": { "family": "VT323", "weight": 400 },
15
+ "label": { "family": "MesloLGS NF", "weight": 400 }
16
+ },
17
+ "hangul": { "family": "Galmuri9", "weight": 400 },
18
+ "scale": {
19
+ "16:9": { "display": 126, "headline": 81, "body": 45, "label": 36 },
20
+ "9:16": { "display": 117, "headline": 81, "body": 54, "label": 36 }
21
+ },
22
+ "leading": { "display": 1.1, "headline": 1.2, "body": 1.5, "label": 1.4 },
23
+ "motion": {
24
+ "ease": { "enter": [0, 0, 1, 1], "move": [0, 0, 1, 1], "exit": [0, 0, 1, 1] },
25
+ "dur": { "micro": 0.1, "move": 0.3, "hero": 0.5, "exit": 0.1 },
26
+ "stagger": { "letter": 0.0455, "word": 0.18, "item": 0.25 },
27
+ "spring": { "micro": { "zeta": 1, "hz": 6 }, "panel": { "zeta": 1, "hz": 4 }, "headline": { "zeta": 1, "hz": 4 }, "subject": { "zeta": 1, "hz": 3 }, "camera": { "zeta": 1, "hz": 1 } },
28
+ "secondary": { "delay": 0.1, "travel": 0.6 },
29
+ "ambient": { "travel": 0.02 },
30
+ "push": 0
31
+ },
32
+ "transitions": ["cut", "wipe"],
33
+ "ground": { "kind": "flat", "panel": "surface" },
34
+ "sound": { "timbre": "pulse-synth", "key": "E", "mode": "minor", "tempo": 120 },
35
+ "score": { "genre": "tech-house" },
36
+ "beds": [
37
+ { "timbre": "pulse-synth", "key": "E", "mode": "minor", "tempo": 120 },
38
+ { "timbre": "glass", "key": "B", "mode": "minor", "tempo": 132 },
39
+ { "timbre": "pulse-synth", "key": "A", "mode": "minor", "tempo": 100 }
40
+ ],
41
+ "bans": ["falling code rain", "purple-cyan neon haze", "glitch running continuously", "an accent hue with no role", "pixel type too small to read", "eased type"]
42
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "schema": "litfamily.motion-style/v1",
3
+ "id": "tidal",
4
+ "name": "Tidal",
5
+ "summary": "Indigo ground with a slow teal-to-violet flow, off-white type that drifts with it, one coral moment.",
6
+ "light": false,
7
+ "typePreset": "tidal",
8
+ "palette": { "ground": "#0E1420", "surface": "#18223A", "ink": "#E8ECEF", "muted": "#A9B3C1", "signal": "#5FB3C4", "accent": "#E07856", "line": "#3A4660", "stopA": "#124559", "stopB": "#4C3B6E" },
9
+ "accents": [{ "role": "a warm highlight", "color": "#E8C07A" }, { "role": "a second current", "color": "#7FD6B0" }, { "role": "a far layer", "color": "#B9A3E3" }],
10
+ "textRoles": ["ink", "muted", "signal", "accent", "ground"],
11
+ "faces": {
12
+ "display": { "family": "Archivo", "weight": 700, "stretch": "100%" },
13
+ "headline": { "family": "Archivo", "weight": 700, "stretch": "100%" },
14
+ "body": { "family": "Pretendard", "weight": 400 },
15
+ "label": { "family": "MesloLGS NF", "weight": 400 }
16
+ },
17
+ "scale": {
18
+ "16:9": { "display": 116, "headline": 72, "body": 40, "label": 26 },
19
+ "9:16": { "display": 112, "headline": 76, "body": 46, "label": 32 }
20
+ },
21
+ "leading": { "display": 1.12, "headline": 1.22, "body": 1.6, "label": 1.4 },
22
+ "motion": {
23
+ "ease": { "enter": [0.37, 0, 0.63, 1], "move": [0.45, 0, 0.55, 1], "exit": [0.5, 0, 0.75, 0] },
24
+ "dur": { "micro": 0.25, "move": 0.9, "hero": 1.2, "exit": 0.6 },
25
+ "stagger": { "letter": 0.04, "word": 0.12, "item": 0.14 },
26
+ "spring": { "micro": { "zeta": 1, "hz": 2.5 }, "panel": { "zeta": 1, "hz": 1.2 }, "headline": { "zeta": 1, "hz": 1.4 }, "subject": { "zeta": 0.9, "hz": 1 }, "camera": { "zeta": 1, "hz": 0.35 } },
27
+ "secondary": { "delay": 0.2, "travel": 0.6 },
28
+ "ambient": { "travel": 0.05 },
29
+ "push": 0.025
30
+ },
31
+ "transitions": ["dissolve", "match", "wipe"],
32
+ "ground": { "kind": "flow", "stops": ["stopA", "stopB"] },
33
+ "sound": { "timbre": "felt-strings", "key": "D", "mode": "major", "tempo": 84 },
34
+ "score": { "genre": "deep-house" },
35
+ "beds": [
36
+ { "timbre": "felt-strings", "key": "D", "mode": "major", "tempo": 84 },
37
+ { "timbre": "glass", "key": "F#", "mode": "minor", "tempo": 76 },
38
+ { "timbre": "soft-keys", "key": "Bb", "mode": "major", "tempo": 72 }
39
+ ],
40
+ "bans": ["a rainbow or hue-cycling ramp", "bloom on the flow", "hard snaps on type", "glitch as texture", "flow so fast that held type smears"]
41
+ }
@@ -578,6 +578,10 @@ Stop when:
578
578
 
579
579
  On resume (after compaction, cancel, or restart): reread the on-disk `SESSION_DIR` — `expansion-log.md` for the lead ledger, every `wave-*.md` for merged findings, and the live plain-text tracker — before launching any new wave. The on-disk ledger, not session memory, is the source of truth for what is open and closed.
580
580
 
581
+ ## Port handoff
582
+
583
+ When the user wants a found mechanism ported into their own skill, hand the ranked sources to `lit-hijack` (`lit hijack <source> into <target>`): it captures with provenance, applies the licence gate and builds a source-free spec the target can be built from.
584
+
581
585
  ## Anti-patterns
582
586
 
583
587
  - Self-activating on a question one read would answer.