@things-factory/figure-ui 10.1.27 โ†’ 10.1.29

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 (91) hide show
  1. package/client/graphql/index.ts +23 -0
  2. package/client/modeller/angle-dial.ts +70 -0
  3. package/client/modeller/base-box.ts +104 -0
  4. package/client/modeller/figure-animations.ts +90 -17
  5. package/client/modeller/figure-canvas.ts +24 -6
  6. package/client/modeller/figure-inspector.ts +169 -5
  7. package/client/modeller/figure-preview.ts +110 -3
  8. package/client/modeller/figure-report.ts +20 -32
  9. package/client/modeller/figure-side.ts +10 -1
  10. package/client/modeller/figure-source.ts +8 -0
  11. package/client/modeller/joint-edits.ts +66 -5
  12. package/client/modeller/joint-gizmo.ts +180 -0
  13. package/client/modeller/part-edits.ts +75 -9
  14. package/client/modeller/pose-defaults.ts +67 -0
  15. package/client/modeller/proposal.ts +9 -3
  16. package/client/modeller/scene-budget.ts +31 -40
  17. package/client/pages/figure-list-page.ts +4 -9
  18. package/client/pages/figure-modeller-page.ts +144 -43
  19. package/client/types.ts +2 -0
  20. package/dist-client/graphql/index.d.ts +7 -0
  21. package/dist-client/graphql/index.js +21 -0
  22. package/dist-client/graphql/index.js.map +1 -1
  23. package/dist-client/modeller/angle-dial.d.ts +32 -0
  24. package/dist-client/modeller/angle-dial.js +41 -0
  25. package/dist-client/modeller/angle-dial.js.map +1 -0
  26. package/dist-client/modeller/base-box.d.ts +47 -0
  27. package/dist-client/modeller/base-box.js +52 -0
  28. package/dist-client/modeller/base-box.js.map +1 -0
  29. package/dist-client/modeller/figure-animations.d.ts +19 -4
  30. package/dist-client/modeller/figure-animations.js +86 -17
  31. package/dist-client/modeller/figure-animations.js.map +1 -1
  32. package/dist-client/modeller/figure-canvas.d.ts +9 -0
  33. package/dist-client/modeller/figure-canvas.js +20 -6
  34. package/dist-client/modeller/figure-canvas.js.map +1 -1
  35. package/dist-client/modeller/figure-inspector.d.ts +37 -0
  36. package/dist-client/modeller/figure-inspector.js +159 -5
  37. package/dist-client/modeller/figure-inspector.js.map +1 -1
  38. package/dist-client/modeller/figure-preview.d.ts +26 -0
  39. package/dist-client/modeller/figure-preview.js +99 -3
  40. package/dist-client/modeller/figure-preview.js.map +1 -1
  41. package/dist-client/modeller/figure-report.d.ts +11 -6
  42. package/dist-client/modeller/figure-report.js +20 -35
  43. package/dist-client/modeller/figure-report.js.map +1 -1
  44. package/dist-client/modeller/figure-side.d.ts +5 -1
  45. package/dist-client/modeller/figure-side.js +13 -0
  46. package/dist-client/modeller/figure-side.js.map +1 -1
  47. package/dist-client/modeller/figure-source.d.ts +7 -0
  48. package/dist-client/modeller/figure-source.js.map +1 -1
  49. package/dist-client/modeller/joint-edits.d.ts +23 -3
  50. package/dist-client/modeller/joint-edits.js +53 -5
  51. package/dist-client/modeller/joint-edits.js.map +1 -1
  52. package/dist-client/modeller/joint-gizmo.d.ts +34 -0
  53. package/dist-client/modeller/joint-gizmo.js +158 -0
  54. package/dist-client/modeller/joint-gizmo.js.map +1 -0
  55. package/dist-client/modeller/part-edits.d.ts +29 -4
  56. package/dist-client/modeller/part-edits.js +61 -9
  57. package/dist-client/modeller/part-edits.js.map +1 -1
  58. package/dist-client/modeller/pose-defaults.d.ts +9 -0
  59. package/dist-client/modeller/pose-defaults.js +35 -0
  60. package/dist-client/modeller/pose-defaults.js.map +1 -0
  61. package/dist-client/modeller/proposal.d.ts +1 -1
  62. package/dist-client/modeller/proposal.js +8 -3
  63. package/dist-client/modeller/proposal.js.map +1 -1
  64. package/dist-client/modeller/scene-budget.d.ts +31 -34
  65. package/dist-client/modeller/scene-budget.js +28 -37
  66. package/dist-client/modeller/scene-budget.js.map +1 -1
  67. package/dist-client/pages/figure-list-page.js +4 -9
  68. package/dist-client/pages/figure-list-page.js.map +1 -1
  69. package/dist-client/pages/figure-modeller-page.d.ts +50 -0
  70. package/dist-client/pages/figure-modeller-page.js +141 -42
  71. package/dist-client/pages/figure-modeller-page.js.map +1 -1
  72. package/dist-client/tsconfig.tsbuildinfo +1 -1
  73. package/dist-client/types.d.ts +2 -0
  74. package/dist-client/types.js.map +1 -1
  75. package/package.json +5 -5
  76. package/test/ai-proposal-contract.test.ts +16 -11
  77. package/test/angle-dial.test.ts +78 -0
  78. package/test/base-box.test.ts +165 -0
  79. package/test/expect.ts +2 -0
  80. package/test/i18n-prefix-guard.test.ts +17 -0
  81. package/test/joint-edits.test.ts +37 -2
  82. package/test/joint-gizmo.test.ts +174 -0
  83. package/test/joint-needle.test.ts +162 -0
  84. package/test/part-edits.test.ts +100 -0
  85. package/test/pose-defaults.test.ts +71 -0
  86. package/test/scene-budget.test.ts +82 -0
  87. package/translations/en.json +16 -9
  88. package/translations/ja.json +16 -9
  89. package/translations/ko.json +16 -9
  90. package/translations/ms.json +16 -9
  91. package/translations/zh.json +16 -9
@@ -1 +1 @@
1
- {"version":3,"file":"figure-inspector.js","sourceRoot":"","sources":["../../client/modeller/figure-inspector.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { css, html, LitElement, nothing, svg } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { live } from 'lit/directives/live.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\nimport {\n EXTRUDE_PRIMITIVES,\n MATERIAL_PRESETS,\n PRIMITIVE_KINDS,\n SEGMENTED_PRIMITIVES,\n SEGMENT_PRESETS,\n SIZING_RULES,\n FIGURE_PLACEMENTS,\n trianglesOf\n} from '@hatiolab/figure-model'\nimport { ANCHOR_RULES, JOINT_TYPES, PART_ROLES, REPEAT_LIMIT, anchorOfPart, repeatPlanOfPart } from '@hatiolab/figure-model'\nimport type {\n AnchorRule,\n Axis,\n FigurePart,\n FigurePlacement,\n JointType,\n MaterialPreset,\n PartRole,\n PrimitiveKind,\n Vec3\n} from '@hatiolab/figure-model'\nimport { activePalette } from '@hatiolab/things-scene'\n\nimport { partToFigure, partFromFigure } from './figure-source.js'\nimport type { FigureDraft, PartModel } from './figure-source.js'\nimport { canMirror } from './part-edits.js'\nimport { jointOf, parentChoices, patchJoint, setJointType } from './joint-edits.js'\n\n/** Axis choices for a joint. Written as a direction the author reads, stored as a vector. */\nconst JOINT_AXES: readonly { key: string; axis: Vec3 }[] = [\n { key: '+x', axis: { x: 1, y: 0, z: 0 } },\n { key: '-x', axis: { x: -1, y: 0, z: 0 } },\n { key: '+y', axis: { x: 0, y: 1, z: 0 } },\n { key: '-y', axis: { x: 0, y: -1, z: 0 } },\n { key: '+z', axis: { x: 0, y: 0, z: 1 } },\n { key: '-z', axis: { x: 0, y: 0, z: -1 } }\n]\n\nfunction axisKeyOf(axis: Vec3): string | undefined {\n return JOINT_AXES.find(one => one.axis.x === axis.x && one.axis.y === axis.y && one.axis.z === axis.z)?.key\n}\n\n/**\n * ๊ณ ๋ฅธ ๋ถ€ํ’ˆ์˜ ์†์„ฑ.\n *\n * ## ์—ฌ๊ธฐ๊ฐ€ ์‚ฌ์šฉ์ž ์šฉ์–ด๋กœ ๋ณด์—ฌ ์ฃผ๋Š” ์ž๋ฆฌ๋‹ค\n *\n * ๋ชจ๋ธ๋Ÿฌ ํŽ˜์ด์ง€๊ฐ€ ๊ฐ–๊ณ  ์žˆ๋Š” ๊ฒƒ์€ **์”ฌ ๋ชจ๋ธ**์ด๋‹ค โ€” ๊ธฐ์ค€ ์ƒ์ž ์œ„์— ๋ถ€ํ’ˆ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋†“์ธ ์ƒํƒœ.\n * ๊ทธ๋Ÿฐ๋ฐ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์”ฌ ์†์„ฑ ์ด๋ฆ„(`left`ยท`top`ยท`zPos`)์ด ์•„๋‹ˆ๋ผ\n * **XยทYยทZ** ๋‹ค. ๋‹ค๋ฅธ 3D ๋„๊ตฌ๊ฐ€ ๋ชจ๋‘ ๊ทธ๋ ‡๊ฒŒ ๋ถ€๋ฅด๊ณ , ์œ„์น˜๋„ ๋ถ€ํ’ˆ์˜ **์ค‘์‹ฌ**์œผ๋กœ ์ฝ๋Š”๋‹ค.\n *\n * ๊ทธ๋ž˜์„œ ์ด ํŒจ๋„์€ ๋ฐ›์€ ๋ถ€ํ’ˆ์„ FigureSource ํ˜•ํƒœ๋กœ **๋ณ€ํ™˜ํ•ด์„œ ๋ณด์—ฌ ์ฃผ๊ณ , ์ˆ˜์ •ํ•œ ๊ฒƒ์„\n * ๋‹ค์‹œ ์”ฌ ๋ชจ๋ธ๋กœ ๋˜๋Œ๋ ค ์•Œ๋ฆฐ๋‹ค.** ๋ณ€ํ™˜์€ `figure-source.ts` ๊ฐ€ ํ•œ๋‹ค โ€” ์—ฌ๊ธฐ์„œ ์ถ•์„ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜์ง€\n * ์•Š๋Š”๋‹ค.\n *\n * ## ์žˆ๋Š” ๊ฒƒ๋งŒ ๋ณด์—ฌ ์ค€๋‹ค\n *\n * ๋ถ„ํ•  ์ˆ˜๋Š” ๊ณก๋ฉด์ด ์žˆ๋Š” ๋„ํ˜•์—๋งŒ, ๋ชจ์„œ๋ฆฌ ๊ตด๋ฆผ์€ ๋‹จ๋ฉด์„ ๋ฝ‘๋Š” ๋„ํ˜•์—๋งŒ ๋œป์ด ์žˆ๋‹ค.\n * ๋œป ์—†๋Š” ์นธ์„ ํšŒ์ƒ‰์œผ๋กœ ๋Š˜์–ด๋†“์œผ๋ฉด ์ €์ž‘์ž๊ฐ€ ใ€Œ์™œ ์•ˆ ๋จน์ง€ใ€๋ฅผ ๊ณ ๋ฏผํ•˜๊ฒŒ ๋œ๋‹ค โ€”\n * ์•„์˜ˆ ๋‚ด์ง€ ์•Š๋Š”๋‹ค.\n *\n * ## ์ด๋ฆ„์€ ์ €์žฅ๋˜๋Š” ์‹๋ณ„์ž๋‹ค\n *\n * `FigurePart.name` ์€ ๋ฐ”์ธ๋”ฉยท์• ๋‹ˆ๋ฉ”์ด์…˜ยท์Šฌ๋กฏ์ด ๊ฐ€๋ฆฌํ‚ค๋Š” ์ด๋ฆ„์ด๋‹ค. ๊ณ ์น˜๋ฉด ๋ฐฐ์น˜๋œ\n * ์ธ์Šคํ„ด์Šค์˜ ๋ฐ”์ธ๋”ฉ์ด **์กฐ์šฉํžˆ** ๋Š๊ธด๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋ฆ„ ์นธ์—๋งŒ ๊ฒฝ๊ณ ๋ฅผ ๋ถ™์ธ๋‹ค.\n *\n * ## ใ€Œ์ƒํƒœ ์ƒ‰์ด ๋ถ™๋Š” ์ž๋ฆฌใ€๋ฅผ ๊ฑท์—ˆ๋‹ค\n *\n * `FigurePart.materialSlot`(๋‹น์‹œ ์ด๋ฆ„์€ `slot`) ์„ ๊ณ ๋ฅด๋Š” ์นธ์ด ์žˆ์—ˆ๋Š”๋ฐ **์•„๋ฌด ์ผ๋„ ํ•˜์ง€ ์•Š์•˜๋‹ค.** things-scene ์˜\n * figure ๋Ÿฐํƒ€์ž„์ด `slot` ์„ ์ฝ์ง€ ์•Š๋Š”๋‹ค โ€” ์„ ์–ธ ํ•œ ์ค„์ด ์ „๋ถ€๋‹ค. ๋˜๋Š” ์ค„ ์•Œ๊ณ  ๋งŒ๋“ค์—ˆ๊ณ ,\n * ํ™•์ธํ•˜์ง€ ์•Š์€ ๊ฒƒ์ด ์ž˜๋ชป์ด๋‹ค.\n *\n * ๊ทธ๋ฆฌ๊ณ  ๋˜๊ฒŒ ๋งŒ๋“ค๋”๋ผ๋„ ์ด ๋ชจ์–‘์ด ์•„๋‹ˆ๋‹ค. ์ƒํƒœ ์ƒ‰์€ ํŠน๋ณ„ํ•œ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ **์†์„ฑ ํ•˜๋‚˜**์ด๊ณ ,\n * ํˆดํŒยท๋ผ๋ฒจยทํ‘œ์‹œ ์—ฌ๋ถ€์™€ ๊ฐ™์€ ์ž๋ฆฌ์—์„œ ๋‹ค๋ค„์ ธ์•ผ ํ•œ๋‹ค. ๊ทธ ์„ค๊ณ„๊ฐ€ ์ •ํ•ด์ง€๋ฉด(figure-model#2)\n * ์ด ์ž๋ฆฌ์— **์†์„ฑ ์„ ์–ธ๊ณผ ๋ถ€ํ’ˆ ๋ฐ”์ธ๋”ฉ** ํŽธ์ง‘๊ธฐ๊ฐ€ ๋“ค์–ด์˜จ๋‹ค.\n *\n * ๊ทธ๋•Œ๊นŒ์ง€ ๋นˆ ์•ฝ์†์„ ๋‘์ง€ ์•Š๋Š”๋‹ค. ์•„๋ฌด ์ผ๋„ ์•ˆ ํ•˜๋Š” ์นธ์€ ์—†๋А๋‹ˆ๋งŒ ๋ชปํ•˜๋‹ค.\n *\n * ## ๊ณ ์น˜์ง€ ์•Š๋Š”๋‹ค\n *\n * ์ •๋ณธ ํ•œ ๋ฒŒ์€ ์ €์ž‘๋ฉด์ด ๊ฐ–๋Š”๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ๋ฐ”๋€ ๋ถ€ํ’ˆ์„ ์•Œ๋ฆด ๋ฟ์ด๋‹ค.\n */\n@customElement('figure-inspector')\nexport class FigureInspector extends localize(i18next)(LitElement) {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n min-height: 0;\n --figure-control-height: 30px;\n overflow-y: auto;\n background-color: var(--md-sys-color-surface-container-lowest);\n color: var(--md-sys-color-on-surface);\n font: var(--label-font, inherit);\n /*\n ์ด ํŒจ๋„์˜ ๋ณธ๋ฌธ ํฌ๊ธฐ๋ฅผ ์—ฌ๊ธฐ์„œ ํ•œ ๋ฒˆ ์ •ํ•œ๋‹ค.\n\n ์ „์—๋Š” ๊ทœ์น™๋งˆ๋‹ค ๋”ฐ๋กœ ์ ์—ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋น ๋œจ๋ฆฐ ๊ทœ์น™์ด ๋ณธ๋ฌธ ๊ธฐ๋ณธ ํฌ๊ธฐ(1rem)๋ฅผ\n ๋ฌผ๋ ค๋ฐ›์•„ ๊ทธ ์ค„๋งŒ ์ œ๋ชฉ์ฒ˜๋Ÿผ ์ปค์ง„๋‹ค. ์˜ค๋ฅ˜๊ฐ€ ์•„๋‹ˆ๋ผ์„œ ํ™”๋ฉด์„ ๋„์›Œ ๋ด์•ผ ์•ˆ๋‹ค.\n ์ด ํŒŒ์ผ์—์„œ๋งŒ ๋‘ ๋ฒˆ ๋‚ฌ๋‹ค.\n\n form ์š”์†Œ(input ยท select ยท button)๋Š” ๊ธ€๊ผด์„ ๋ฌผ๋ ค๋ฐ›์ง€ ์•Š์œผ๋ฏ€๋กœ ๊ฐ์ž ์ ์–ด์•ผ ํ•œ๋‹ค.\n ๊ทธ๊ฒƒ ๋ง๊ณ ๋Š” ์—ฌ๊ธฐ ๊ฐ’์„ ๋”ฐ๋ฅธ๋‹ค.\n */\n font-size: 0.76rem;\n }\n\n /*\n โ”€โ”€ ์ž๋ฆฌ๋ฅผ ์•„๋ผ๋Š” ํŒ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n ์†์„ฑ์€ ์•ž์œผ๋กœ ๋” ๋Š˜์–ด๋‚œ๋‹ค(๋Šฅ๋ ฅ ยท ํฌํŠธ ยท ์• ๋‹ˆ๋ฉ”์ด์…˜ ยท ๊ธฐ์ค€์ •๋ณด). ์ง€๊ธˆ ์—ฌ๋ฐฑ์„ ๊ทธ๋Œ€๋กœ ๋‘๋ฉด\n ๊ทธ๊ฒƒ๋“ค์ด ๋“ค์–ด์˜ฌ ์ž๋ฆฌ๊ฐ€ ์—†๋‹ค. ์ ˆ ์—ฌ๋ฐฑ์„ 6/10 ์œผ๋กœ, ์ œ๋ชฉ ์•„๋ž˜๋ฅผ 4px ๋กœ ์ค„์˜€๋‹ค โ€” ๊ธ€์ž ํฌ๊ธฐ์™€\n ์นธ ๋†’์ด๋Š” ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค(์ž‘๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ **๋นˆ ๊ณณ์„ ์ค„์ด๋Š” ๊ฒƒ**์ด๋‹ค).\n */\n section {\n padding: 8px 10px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n /* ์ž…๋ ฅ ํ–‰์€ ์ด˜์ด˜ํ•˜๊ฒŒ, ์„œ๋กœ ๋‹ค๋ฅธ ํŽธ์ง‘ ์˜๋„ ์‚ฌ์ด์—๋Š” ํ˜ธํก์„ ๋‘”๋‹ค. */\n section + section {\n margin-top: 6px;\n }\n section[collapsible] {\n padding: 0;\n }\n details[group] > summary {\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 34px;\n padding: 0 10px;\n cursor: pointer;\n list-style: none;\n }\n details[group] > summary::-webkit-details-marker {\n display: none;\n }\n details[group] > summary h3 {\n margin: 0;\n }\n details[group] > summary md-icon {\n --md-icon-size: 16px;\n color: var(--md-sys-color-on-surface-variant);\n }\n details[group] > div[group-content] {\n padding: 4px 10px 8px;\n border-top: 1px solid var(--md-sys-color-outline-variant);\n }\n h3 {\n display: flex;\n align-items: center;\n gap: 4px;\n margin: 0 0 4px 0;\n font-size: var(--ui-t-micro, 11px);\n font-weight: 700;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /* ์ž์‚ฐ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋Š” ๋ถ€ํ’ˆ์„ ๊ณ ์นœ๋‹ค๋Š” ํ˜„์žฌ ๋ฌธ๋งฅ์—์„œ๋Š” ์š”์•ฝ์œผ๋กœ๋งŒ ๋‘”๋‹ค. */\n details[asset] {\n margin: -1px 0;\n }\n details[asset] summary {\n display: flex;\n align-items: center;\n gap: 6px;\n min-height: 26px;\n cursor: pointer;\n list-style: none;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n details[asset] summary::-webkit-details-marker {\n display: none;\n }\n details[asset] summary::before {\n content: 'โ€บ';\n font-size: 1.1rem;\n line-height: 1;\n transition: transform 120ms ease;\n }\n details[asset][open] summary::before {\n transform: rotate(90deg);\n }\n details[asset] summary b {\n font-size: var(--ui-t-micro, 11px);\n letter-spacing: 0.04em;\n }\n details[asset] summary small {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 0.7rem;\n }\n\n label {\n display: flex;\n align-items: center;\n gap: 3px;\n margin-bottom: 2px;\n font-size: 0.68rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /*\n ๋„์›€๋ง ๋ฌผ์Œํ‘œ. **๊ธ€์ž ์ค„์„ ํ•˜๋‚˜ ๋จน์ง€ ์•Š๋Š”๋‹ค** โ€” ๋ผ๋ฒจยท์ œ๋ชฉ ์ค„์˜ ๋‚จ๋Š” ํญ์— ์–นํžŒ๋‹ค.\n ์•„์ด์ฝ˜๋งŒ ๋‘๊ณ  ํ…Œ๋‘๋ฆฌ๋ฅผ ์•ˆ ๋‘๋Š” ์ด์œ ๋Š” ์ด๊ฒƒ์ด ๋ˆ„๋ฅผ ๊ฒƒ์ด๋ผ๊ธฐ๋ณด๋‹ค ใ€Œ๋” ์žˆ๋‹คใ€๋Š” ํ‘œ์‹œ๋ผ์„œ๋‹ค.\n */\n button[help] {\n display: inline-flex;\n align-items: center;\n padding: 0;\n margin: 0;\n color: var(--md-sys-color-outline);\n background: none;\n border: none;\n cursor: pointer;\n }\n button[help] md-icon {\n --md-icon-size: 13px;\n font-size: 13px;\n }\n button[help]:hover,\n button[help][aria-expanded='true'] {\n color: var(--md-sys-color-primary);\n }\n\n /* ํŽธ ๋„์›€๋ง. ๋ผ๋ฒจ ์•„๋ž˜ ํ•œ ์นธ ๋“ค์—ฌ ๋ถ™์ธ๋‹ค โ€” ๋ฌด์—‡์— ๋”ธ๋ฆฐ ๋ง์ธ์ง€ ๋ณด์ด๊ฒŒ. */\n p[hint] {\n margin: 2px 0 4px 0;\n padding-left: 6px;\n font-size: 0.68rem;\n line-height: 1.5;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n border-left: 2px solid var(--md-sys-color-outline-variant);\n }\n\n input,\n select {\n width: 100%;\n min-height: var(--figure-control-height);\n box-sizing: border-box;\n padding: 4px 7px;\n font: var(--input-field-font, inherit);\n font-size: 0.76rem;\n color: var(--md-sys-color-on-surface);\n background-color: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n }\n input:focus,\n select:focus {\n outline: 2px solid var(--md-sys-color-primary);\n outline-offset: -1px;\n }\n\n /*\n ์ˆซ์ž ์นธ โ€” ๋ผ๋ฒจ์„ ์นธ **์•ˆ** ์™ผ์ชฝ์— ๋‘”๋‹ค.\n\n ๋ฒกํ„ฐ ์ €์ž‘๋„๊ตฌ(SketchยทFigma)๊ฐ€ XยทYยทWยทH ๋ฅผ ์ด๋ ‡๊ฒŒ ๋‘”๋‹ค. ๋ผ๋ฒจ์„ ์œ„์— ์–น์œผ๋ฉด ์ค„๋งˆ๋‹ค\n ๋‘ ์ค„์„ ๋จน์–ด์„œ, ์ž๋ฆฌยทํฌ๊ธฐยทํšŒ์ „ ์•„ํ™‰ ์นธ์ด ํ™”๋ฉด ์ ˆ๋ฐ˜์„ ์ฐจ์ง€ํ•œ๋‹ค. ์•ˆ์— ๋‘๋ฉด ํ•œ ์ค„์—\n ์…‹์ด ๋“ค์–ด๊ฐ€๊ณ  ๋ฌด์—‡์ด ๋ฌด์—‡์ธ์ง€๋„ ๋ถ™์–ด ์ฝํžŒ๋‹ค.\n */\n div[cell] {\n display: flex;\n box-sizing: border-box;\n height: var(--figure-control-height);\n min-height: var(--figure-control-height);\n align-items: center;\n gap: 2px;\n padding-left: 6px;\n background-color: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n }\n div[cell]:focus-within {\n outline: 2px solid var(--md-sys-color-primary);\n outline-offset: -1px;\n border-color: transparent;\n }\n div[cell] span[axis] {\n flex: none;\n font-size: 0.64rem;\n letter-spacing: 0.02em;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n div[cell] input {\n min-width: 0;\n min-height: 0;\n height: calc(var(--figure-control-height) - 2px);\n padding: 4px 6px 4px 2px;\n font-family: var(--mono-font, monospace);\n text-align: right;\n background: none;\n border: none;\n border-radius: 0;\n }\n div[cell] input:focus {\n outline: none;\n }\n\n /* ์ถ• ์…‹์„ ํ•œ ์ค„์— โ€” ์ขŒํ‘œ๋Š” ์…‹์ด ๊ฐ™์ด ์ฝํ˜€์•ผ ํ•œ๋‹ค */\n div[triple] {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 4px;\n }\n div[field] + div[field],\n div[triple] + div[field],\n div[field] + div[triple],\n div[inline-field] + div[inline-field],\n div[inline-field] + div[field],\n div[field] + div[inline-field],\n div[vector-row] + div[vector-row],\n div[vector-row] + div[field],\n div[field] + div[vector-row] {\n /* ์นธ ์‚ฌ์ด 7 โ†’ 5. ์นธ ์ž์ฒด๋Š” ๊ทธ๋Œ€๋กœ ๋‘๊ณ  ์‚ฌ์ด๋งŒ ์ขํžŒ๋‹ค. */\n margin-top: 5px;\n }\n\n /* ์งง์€ ๋ผ๋ฒจ๊ณผ ๋‹จ์ผ ๊ฐ’์€ ๊ฐ™์€ ์ค„์—์„œ ์ฝ๋Š”๋‹ค. ๋ณต์žกํ•œ ์„ ํƒ๊ธฐ์—๋Š” ์“ฐ์ง€ ์•Š๋Š”๋‹ค. */\n div[inline-field] {\n display: grid;\n /* ๊ฐ™์€ ํŽธ์ง‘ ๋ฐ€๋„ ์•ˆ์—์„œ๋Š” ์ž…๋ ฅ ์‹œ์ž‘์„ ์„ ๋งž์ถ˜๋‹ค. ๋ผ๋ฒจ ๊ธธ์ด๊ฐ€ ์นธ ํญ์„ ํ”๋“ค๋ฉด ์•ˆ ๋œ๋‹ค. */\n grid-template-columns: 64px minmax(0, 1fr);\n align-items: center;\n gap: 7px;\n }\n div[inline-field] > label {\n margin: 0;\n white-space: nowrap;\n }\n /* ํ•œ ์ค„ ์ž…๋ ฅ์˜ ์„ค๋ช…์€ ์ž…๋ ฅ์นธ์„ ๋ฐ€์–ด๋‚ด์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ์•„๋ž˜ ์ „ํญ์—์„œ ์ฝ๋Š”๋‹ค. */\n div[inline-field] > p[hint] {\n grid-column: 1 / -1;\n margin: -2px 0 1px;\n }\n div[inline-field] > code[fixed] {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n /* XยทYยทZ๋Š” ํ•จ๊ป˜ ๋น„๊ตํ•˜๋Š” ๊ฐ’์ด๋ฏ€๋กœ, ๋ฌถ์Œ ์ œ๋ชฉ๋งŒ ์™ผ์ชฝ์— ๋‘๊ณ  ์ž…๋ ฅ์€ ํ•œ ํ–‰์— ๋‘”๋‹ค. */\n div[vector-row] {\n display: grid;\n grid-template-columns: 64px minmax(0, 1fr);\n align-items: center;\n gap: 7px;\n }\n div[vector-row] > label {\n margin: 0;\n white-space: nowrap;\n }\n div[vector-row] > p[hint] {\n grid-column: 1 / -1;\n margin: -2px 0 1px;\n }\n div[sizing-choices] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 5px;\n }\n button[sizing-choice] {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 2px;\n min-height: 52px;\n padding: 7px 8px;\n color: var(--md-sys-color-on-surface);\n background: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 7px;\n text-align: left;\n cursor: pointer;\n }\n button[sizing-choice][on] {\n color: var(--md-sys-color-on-primary-container);\n background: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n button[sizing-choice] b {\n font-size: 0.74rem;\n }\n button[sizing-choice] small {\n font-size: 0.64rem;\n line-height: 1.35;\n opacity: 0.8;\n }\n div[anchor-rows] {\n display: grid;\n gap: 6px;\n }\n div[anchor-row] {\n display: grid;\n grid-template-columns: 46px minmax(0, 1fr);\n align-items: start;\n gap: 8px;\n padding: 6px 7px;\n background: var(--md-sys-color-surface-container);\n border-radius: 7px;\n }\n div[anchor-row] label {\n margin: 0;\n font-size: 0.7rem;\n font-weight: 700;\n }\n div[anchor-options] {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 4px;\n }\n button[anchor-choice] {\n min-width: 0;\n height: var(--figure-control-height);\n box-sizing: border-box;\n padding: 4px 3px;\n overflow: hidden;\n color: var(--md-sys-color-on-surface);\n font: var(--label-font, inherit);\n font-size: 0.63rem;\n line-height: 1.2;\n text-overflow: ellipsis;\n white-space: nowrap;\n background: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 5px;\n cursor: pointer;\n }\n button[anchor-choice][on] {\n color: var(--md-sys-color-on-primary-container);\n background: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n details[anchor-advanced] {\n grid-column: 2;\n margin-top: 4px;\n }\n details[anchor-advanced] summary {\n cursor: pointer;\n font-size: 0.62rem;\n color: var(--md-sys-color-on-surface-variant);\n }\n details[anchor-advanced] div[anchor-options] {\n margin-top: 4px;\n }\n div[palette-meaning] {\n display: grid;\n gap: 2px;\n margin-top: 7px;\n padding: 6px 8px;\n color: var(--md-sys-color-on-surface);\n background: var(--md-sys-color-surface-container);\n border-radius: 7px;\n }\n div[palette-meaning] b {\n font-size: 0.72rem;\n }\n div[palette-meaning] small {\n color: var(--md-sys-color-on-surface-variant);\n font-size: 0.64rem;\n line-height: 1.35;\n }\n\n /*\n ์ •๋ฐ€ ์ œ์ž‘ ๋„๊ตฌ.\n\n ๋„๋ฉด ํŽธ์ง‘๊ธฐ๋Š” ์ž์‚ฐ์„ ๋ฐฐ์น˜ํ•˜๋Š” ๊ณณ์ด๋ผ ๋Œ€์ถฉ ๋†“์•„๋„ ๋˜์ง€๋งŒ, ์—ฌ๊ธฐ๋Š” ์ž์‚ฐ์„ ๋งŒ๋“œ๋Š”\n ๊ณณ์ด๋‹ค. ใ€Œ๋ชธํ†ต ํ•œ๊ฐ€์šด๋ฐใ€ยทใ€Œ๋ฐ”๋‹ฅ์— ๋ถ™์ด๊ธฐใ€ยทใ€Œ๋ฐ˜๋Œ€์ชฝ์—๋„ ํ•˜๋‚˜ใ€๋ฅผ ์†์œผ๋กœ ๊ณ„์‚ฐํ•˜๋ฉด\n ๋Š˜ ์กฐ๊ธˆ์”ฉ ์–ด๊ธ‹๋‚˜๊ณ , ๊ธฐ์ค€ ์น˜์ˆ˜๋ฅผ ๋ฐ”๊พธ๋ฉด ์ „๋ถ€ ๋‹ค์‹œ ํ•ด์•ผ ํ•œ๋‹ค.\n */\n div[tools] {\n display: grid;\n grid-template-columns: repeat(6, minmax(0, 1fr));\n gap: 4px;\n }\n div[tools] button {\n display: grid;\n place-items: center;\n min-width: 0;\n height: var(--figure-control-height);\n box-sizing: border-box;\n padding: 0;\n font: var(--label-font, inherit);\n font-size: 0.7rem;\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n div[tools] button md-icon {\n font-size: 17px;\n }\n div[tools] button[disabled] {\n opacity: 0.35;\n cursor: default;\n }\n div[tools] button:hover:not([disabled]) {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n\n /* ์ง€๊ธˆ ์–ด๋А ์ถ•์ด ๋Š˜์–ด๋‚˜๋‚˜ โ€” ํฌ๊ธฐ๋ฅผ ๊ณ ์น˜๋ฉด ๋ฐ”๋€” ์ˆ˜ ์žˆ์–ด์„œ ๊ฐ’์œผ๋กœ ์ ๋Š”๋‹ค */\n p[axis-now] {\n margin: 4px 0 0 0;\n font-size: 0.7rem;\n color: var(--md-sys-color-primary);\n }\n /* ์ด ์„ ํƒ์ด ๋ฌด์—‡์„ ๋ฌด๋Š”์ง€ โ€” ์„ฑ์ˆ™๋„์˜ ๋ฌถ์Œ ์ˆ˜์— ๊ทธ๋Œ€๋กœ ์žกํžŒ๋‹ค */\n p[cost] {\n margin: 4px 0 0 0;\n font-size: 0.68rem;\n line-height: 1.5;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /* ์ด๋ฆ„์„ ๋ฐ”๊พธ๋ฉด ๋ฌด์—‡์ด ๋Š๊ธฐ๋Š”์ง€ ๋งํ•œ๋‹ค */\n p[warn] {\n margin: 4px 0 0 0;\n font-size: 0.68rem;\n line-height: 1.5;\n color: var(--md-sys-color-tertiary);\n }\n\n /* ๋ถ„ํ•  ์ˆ˜ ํ”„๋ฆฌ์…‹ โ€” ์ž์œ  ์ž…๋ ฅ๋ณด๋‹ค ์ด ์…‹์„ ๊ถŒํ•œ๋‹ค */\n div[presets] {\n display: flex;\n gap: 4px;\n margin-top: 4px;\n }\n div[presets] button {\n flex: 1;\n padding: 3px 0;\n font: var(--label-font, inherit);\n font-size: 0.72rem;\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n div[presets] button[on] {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n\n /*\n ๋ถ„ํ•  ์ˆ˜ ์„ ํƒ โ€” ๋ชจ์–‘๊ณผ ์‚ผ๊ฐํ˜• ์ˆ˜๋ฅผ **ํ•จ๊ป˜** ๋ณด์—ฌ ์ค€๋‹ค.\n\n ์ˆซ์ž๋งŒ ๋Š˜์–ด๋†“์œผ๋ฉด 8 ๊ณผ 16 ์ด ๋ฌด์—‡์ด ๋‹ค๋ฅธ์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค. ๋กœ์šฐํด๋ฆฌ์—์„œ ์ด ์„ ํƒ์ด\n ๊ณง ใ€Œ๋ช‡ ๊ฐœ๊นŒ์ง€ ํŽธํ•˜๊ฒŒ ๋†“์„ ์ˆ˜ ์žˆ๋‚˜ใ€๋ฅผ ์ •ํ•˜๋ฏ€๋กœ, ๊ฐ์ง€๋Š” ์ •๋„์™€ ๊ทธ ๊ฐ’์ด ๋ฌด๋Š”\n ์‚ผ๊ฐํ˜• ์ˆ˜๋ฅผ ํ•œ์ž๋ฆฌ์—์„œ ๋ณด์•„์•ผ ํ•œ๋‹ค.\n\n ์‹ค๋ฃจ์—ฃ์€ ์ง€์–ด๋‚ธ ๊ทธ๋ฆผ์ด ์•„๋‹ˆ๋‹ค โ€” ๊ณก๋ฉด ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ๋ฅผ ์œ„์—์„œ ๋ณธ ์œค๊ณฝ์ด ์ •ํ™•ํžˆ\n ์ •n๊ฐํ˜•์ด๋‹ค. ์‚ผ๊ฐํ˜• ์ˆ˜๋Š” ํ™”๋ฉด์ด ์…ˆํ•˜์ง€ ์•Š๊ณ  figure-model ์˜ trianglesOf ๊ฐ€ ๋‚ธ๋‹ค.\n */\n div[segments] {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 4px;\n }\n /* ์› ์œ ์ง€ ยท ๋„๊ธฐ โ€” ๊ณ ๋ฅด๋Š” ๊ฐ’์ด๋ผ ๋ถ„ํ•  ์ˆ˜์™€ ๊ฐ™์€ ๋ชจ์–‘์œผ๋กœ ๋‘”๋‹ค */\n div[choices] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 4px;\n }\n button[choice] {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 1px;\n padding: 6px 8px;\n text-align: left;\n font: var(--label-font, inherit);\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n button[choice]:hover:not([on]) {\n background-color: var(--md-sys-color-surface-container);\n }\n button[choice][on] {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n button[choice] small {\n opacity: 0.75;\n }\n button[seg] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1px;\n padding: 6px 2px 4px 2px;\n font: var(--label-font, inherit);\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n button[seg]:hover:not([on]) {\n background-color: var(--md-sys-color-surface-container);\n }\n button[seg][on] {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n button[seg] svg {\n display: block;\n /* ์ž‘์œผ๋ฉด 12 ์™€ 16 ์ด ๋‘˜ ๋‹ค ๋™๊ทธ๋ผ๋ฏธ๋กœ ๋ณด์ธ๋‹ค โ€” ๊ฐ์ด ์ฝํž ๋งŒํผ์€ ํ‚ค์šด๋‹ค */\n width: 32px;\n height: 32px;\n }\n button[seg] svg polygon {\n fill: var(--md-sys-color-surface-container-highest);\n stroke: currentColor;\n stroke-width: 1.1;\n stroke-linejoin: miter;\n }\n button[seg][on] svg polygon {\n fill: var(--md-sys-color-surface-container-lowest);\n }\n button[seg] b {\n font-size: 0.8rem;\n font-weight: 700;\n line-height: 1.1;\n }\n button[seg] small {\n font-size: 0.62rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n button[seg][on] small {\n color: inherit;\n }\n /* ์„ฑ๋Šฅยท์‹ค๋ฃจ์—ฃ ๊ฒ€์ฆ์„ ๋งˆ์นœ ํ”„๋ฆฌ์…‹๋งŒ ๊ณ ๋ฅธ๋‹ค. */\n details[free] {\n margin-top: 6px;\n }\n details[free] summary {\n font-size: 0.68rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n cursor: pointer;\n }\n details[free] div[cell] {\n margin-top: 4px;\n }\n\n /*\n ์ƒ‰ ๊ฒฌ๋ณธ.\n\n ํ† ํฐ์„ ๊ธ€์ž๋กœ ๋ฐ›์ง€ ์•Š๋Š”๋‹ค. things-scene ์˜ ํŒ”๋ ˆํŠธ ์„ ์–ธ์ด ใ€Œ์—ฌ๊ธฐ ๋“  ์ด๋ฆ„์ด ์ €์ž‘์—์„œ\n ๊ณ ๋ฅผ ์ˆ˜ ์žˆ๋Š” ์ „๋ถ€์ด๊ณ , ์ž์œ ์ƒ‰์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ๊ฐ๊ฐ์ ์ธ ๋กœ์šฐํด๋ฆฌ์˜ ์ฒซ ๊ทœ์น™ใ€\n ์ด๋ผ๊ณ  ๋ชป๋ฐ•๊ณ  ์žˆ๋‹ค. ๊ธ€์ž ์นธ์œผ๋กœ ๋‘๋ฉด ๊ทธ ๊ทœ์น™์ด ํ™”๋ฉด์—์„œ ์‚ฌ๋ผ์ง€๊ณ , ์˜คํƒ€ ํ•˜๋‚˜๋กœ\n resolveToken ์ด ๋˜์ง„๋‹ค.\n */\n div[swatches] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n /*\n ๋‘ ๋ฌด๋ฆฌ์˜ ๊ฒฝ๊ณ„. ใ€Œ์น ํ•œ ์ƒ‰ใ€๊ณผ ใ€Œ์ผœ์ง„ ์ƒ‰ใ€์ด ํ•œ ์ค„์— ์„ž์ด๋ฉด accent(์ฃผํ™ฉ)์™€\n status-warning(์ฃผํ™ฉ)์ด ๋‚˜๋ž€ํžˆ ๋†“์—ฌ ๋ฌด์—‡์ด ๋ฌด์—‡์ธ์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค.\n */\n label[group] {\n margin-top: 8px;\n padding-top: 8px;\n font-size: var(--ui-t-micro, 11px);\n letter-spacing: 0.03em;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n border-top: 1px solid var(--md-sys-color-outline-variant);\n }\n\n /* ๊ฐ’์ด ์˜†์— ๋ถ™์–ด์•ผ ๋Œ๋ฉด์„œ ์–ผ๋งˆ์ธ์ง€ ์•ˆ๋‹ค */\n div[slider] {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n div[slider] input[type='range'] {\n flex: 1;\n accent-color: var(--md-sys-color-primary);\n cursor: pointer;\n }\n div[slider] output {\n flex: none;\n width: 2.6em;\n text-align: right;\n font: var(--mono-font, ui-monospace, monospace);\n font-size: 0.72rem;\n color: var(--md-sys-color-on-surface-variant);\n }\n button[swatch] {\n width: 26px;\n height: 26px;\n padding: 0;\n background-color: var(--swatch);\n border: 1px solid rgba(0, 0, 0, 0.16);\n border-radius: 50%;\n cursor: pointer;\n }\n button[swatch][on] {\n /* ๊ณ ๋ฅธ ๊ฒƒ์€ ํ…Œ๋‘๋ฆฌ๊ฐ€ ์•„๋‹ˆ๋ผ ๊ณ ๋ฆฌ๋กœ ํ‘œ์‹œํ•œ๋‹ค โ€” ์ƒ‰ ์ž์ฒด๋ฅผ ๊ฐ€๋ฆฌ์ง€ ์•Š์œผ๋ ค๊ณ  */\n box-shadow:\n 0 0 0 2px var(--md-sys-color-surface-container-lowest),\n 0 0 0 4px var(--md-sys-color-primary);\n }\n span[token] {\n display: block;\n margin-top: 6px;\n font-family: var(--mono-font, monospace);\n font-size: 0.68rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n label[toggle] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 7px 0 0 0;\n font-size: 0.74rem;\n color: var(--md-sys-color-on-surface);\n cursor: pointer;\n }\n label[toggle] input {\n width: auto;\n }\n div[role-choices] {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 4px;\n }\n div[role-choices] label[toggle] {\n justify-content: center;\n min-height: 30px;\n margin: 0;\n padding: 2px 4px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n font-size: 0.68rem;\n text-align: center;\n }\n div[role-choices] label[toggle]:has(input:checked) {\n color: var(--md-sys-color-on-primary-container);\n background: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n\n p[quiet] {\n margin: 0;\n font-size: 0.76rem;\n line-height: 1.6;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /*\n ๊ณ ์น  ์ˆ˜ ์—†๋Š” ๊ฐ’ โ€” ์ž…๋ ฅ์นธ์ฒ˜๋Ÿผ ๋ณด์ด์ง€ ์•Š๊ฒŒ ํ•œ๋‹ค.\n\n ์ „์—๋Š” ๊ทธ๋ƒฅ ๊ธ€์ž์˜€๊ณ , ์˜†์˜ ์ด๋ฆ„ ์นธ๊ณผ ๋‚˜๋ž€ํžˆ ์žˆ์œผ๋‹ˆ ๋ˆŒ๋Ÿฌ๋„ ๋˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์˜€๋‹ค. ์ž๋ฌผ์‡ ์™€\n ์นธ ์—†๋Š” ๋ฐ”ํƒ•์ด ใ€Œ์ฝ๋Š” ๊ฐ’ใ€์ด๋ผ๊ณ  ๋จผ์ € ๋งํ•œ๋‹ค.\n */\n code[fixed] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n border-radius: 6px;\n background-color: var(--md-sys-color-surface-container-high, rgba(0, 0, 0, 0.05));\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n font-family: var(--mono-font, monospace);\n font-size: 0.76rem;\n }\n\n code[fixed] md-icon {\n --md-icon-size: 13px;\n opacity: 0.7;\n }\n `\n ]\n\n /** ๋„ํ˜•์˜ DB ์‹๋ณ„์ž. ๋น„์–ด ์žˆ์œผ๋ฉด ๋ฏธ์ €์žฅ ์‹ ๊ทœ ๋ชจ๋ธ์ด๋‹ค. */\n @property({ type: String }) figureId = ''\n /** ๋„ํ˜•์˜ ํ‘œ์‹œ ์ด๋ฆ„. ์ •๋ณธ์€ ์ €์ž‘๋ฉด์ด ๋“ค๊ณ , ์—ฌ๊ธฐ์„œ๋Š” ๋ณด์—ฌ ์ฃผ๊ณ  ๋ฐ”๊พผ๋‹ค(`figure-rename` ์œผ๋กœ ์•Œ๋ฆฐ๋‹ค). */\n @property({ type: String }) figureName = ''\n /** ๋ถ„๋ฅ˜ ํ•˜๋‚˜ โ€” ํŒ”๋ ˆํŠธ์—์„œ ๋ฌถ๋Š” ๊ธฐ์ค€. */\n @property({ type: String }) figureCategory?: string\n /** ํƒœ๊ทธ ์—ฌ๋Ÿฟ โ€” ๋ถ„๋ฅ˜๋กœ๋Š” ๋ชป ํ•˜๋Š” ์ฐพ๊ธฐ. */\n @property({ type: Array }) figureTags?: string[]\n\n /** ํŽด ๋‘” ๋„์›€๋ง. ๋ถ€ํ’ˆ์„ ๋ฐ”๊ฟ”๋„ ์œ ์ง€๋œ๋‹ค โ€” ๋งค๋ฒˆ ๋‹ค์‹œ ํŽด๊ฒŒ ํ•˜์ง€ ์•Š๋Š”๋‹ค. */\n @state() private opened = new Set<string>()\n\n @property({ type: Object }) draft?: FigureDraft\n /** ์ดˆ์•ˆ ์œ„์˜ ๋ถ€ํ’ˆ๋“ค. ์”ฌ ๋ชจ๋ธ ๊ทธ๋Œ€๋กœ๋‹ค. */\n @property({ type: Array }) parts: PartModel[] = []\n @property({ type: Number }) selected = -1\n\n /** `part` ๋Š” HTMLElement ์˜ ์†์„ฑ(DOMTokenList)์ด๋‹ค โ€” ๊ฐ€๋ฆฌ๋ฉด ํ˜•์ด ์–ด๊ธ‹๋‚œ๋‹ค. */\n private get chosen(): PartModel | undefined {\n return this.parts?.[this.selected]\n }\n\n render() {\n const part = this.chosen\n if (!part || !this.draft) {\n return html`\n ${this.renderFigure(false)}\n <section>\n <h3>${i18next.t('figure.label.properties')}</h3>\n <p quiet>${i18next.t('figure.text.select-a-part-to-edit')}</p>\n </section>\n `\n }\n\n // ์—ฌ๊ธฐ๋ถ€ํ„ฐ๋Š” ์‚ฌ์šฉ์ž ์šฉ์–ด๋‹ค โ€” XยทYยทZ, ์œ„์น˜๋Š” ๋ถ€ํ’ˆ ์ค‘์‹ฌ, ํšŒ์ „์€ ๋„(degree).\n const shown = partToFigure(part, this.draft)\n\n /*\n ์—ญํ• ์„ ๋จผ์ € ๋ฌป๋Š”๋‹ค.\n\n ์ž๋ฆฌ(slot)๋กœ ์ง€์ •ํ•œ ๋ถ€ํ’ˆ์€ **๊ทธ๋ ค์ง€์ง€ ์•Š๋Š”๋‹ค.** ๊ทธ ์‚ฌ์‹ค์„ ๋ชจ๋ฅธ ์ฑ„ ์žฌ์งˆ๋ถ€ํ„ฐ ๊ณ ๋ฅด๋ฉด ์•ˆ ์“ฐ์ผ\n ์ƒ‰์„ ๊ณ ๋ฅด๊ฒŒ ๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ž๋ฆฌ๋Š” ๋„ํ˜•์ด ๋Šฅ๋ ฅ์„ ์งˆ ๋•Œ๋งŒ ๋œป์ด ์žˆ์œผ๋ฏ€๋กœ, ๋Šฅ๋ ฅ์ด ์—†์œผ๋ฉด ์ด\n ๋ฌถ์Œ์€ ์•„์˜ˆ ๋‚˜์˜ค์ง€ ์•Š๋Š”๋‹ค โ€” ํ•ด ๋‘ฌ๋„ ์•„๋ฌด ์ผ๋„ ์•ˆ ์ผ์–ด๋‚˜๋Š” ์นธ์„ ๋ณด์—ฌ ์ฃผ์ง€ ์•Š๋Š”๋‹ค.\n */\n return html`\n ${this.renderFigure(true)} ${this.renderIdentity(shown)} ${this.renderRole(shown)} ${this.renderJoint(shown)}\n ${this.renderPlacement(shown)} ${this.renderShape(shown)} ${this.renderMaterial(shown)}\n ${this.renderBehaviour(shown)}\n `\n }\n\n /**\n * โ”€โ”€ ์ด ๋ถ€ํ’ˆ์ด ๋Šฅ๋ ฅ์—์„œ ๋งก๋Š” ์ž๋ฆฌ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n *\n * ใ€Œ๋Šฅ๋ ฅใ€ ํƒญ์ด ๋„ํ˜• ์ „์ฒด๊ฐ€ ๋ฌด์—‡์„ ํ•˜๋Š”์ง€ ์ •ํ•˜๊ณ , ์–ด๋А ๋ถ€ํ’ˆ์ด ๊ทธ๊ฒƒ์„ ๋ฐ›์ณ ์ฃผ๋Š”์ง€๋Š” ์—ฌ๊ธฐ์„œ\n * ์ •ํ•œ๋‹ค. **๋ถ€ํ’ˆ์„ ๊ณ ์น˜๋Š” ๊ณณ์ด ํ•œ ๊ตฐ๋ฐ์—ฌ์•ผ** ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค โ€” ๋ชฉ๋ก์„ ๋”ฐ๋กœ ๋‘๋ฉด ๊ฐ™์€ ๋ถ€ํ’ˆ์„\n * ๋‘ ํ™”๋ฉด์—์„œ ๊ณ ์น˜๊ฒŒ ๋˜๊ณ , ์ €์ž‘์ž๋Š” ์–ด๋А ์ชฝ์ด ์ด๊ธฐ๋Š”์ง€ ๋งค๋ฒˆ ์ƒ๊ฐํ•ด์•ผ ํ•œ๋‹ค.\n *\n * ์นธ ์ˆ˜๋Š” `repeat` ๊ฐ€ ์žˆ์œผ๋ฉด ๋ฐ›์ง€ ์•Š๋Š”๋‹ค. ๋ฐ˜๋ณตํ•˜๋Š” ์ž๋ฆฌ์˜ ์นธ ์ˆ˜๋Š” **์ธ์Šคํ„ด์Šค ํฌ๊ธฐ**๊ฐ€ ์ •ํ•œ๋‹ค โ€”\n * ์ปจ๋ฒ ์ด์–ด๊ฐ€ ๊ธธ์–ด์ง€๋ฉด ์‹ค์„ ์ž๋ฆฌ๊ฐ€ ๋Š˜์–ด๋‚˜๋Š” ๊ฒƒ์ด ๊ทธ๊ฒƒ์ด๊ณ , ์—ฌ๊ธฐ ์ ์€ ๊ฐ’์€ ์•ˆ ์“ฐ์ธ๋‹ค.\n */\n private renderRole(part: FigurePart) {\n if (!this.draft?.capabilities?.length) return nothing\n\n const roles = part.capability?.roles ?? []\n const repeats = part.sizing === 'repeat' && !!part.repeat\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.role-in-capability')}${this.help('figure.text.anchors-are-not-drawn')}</h3>\n\n <div role-choices>\n ${(PART_ROLES as readonly PartRole[]).map(\n one => html`\n <label toggle>\n <input\n type=\"checkbox\"\n .checked=${live(roles.includes(one))}\n @change=${(e: Event) => this.toggleRole(one, (e.target as HTMLInputElement).checked)}\n />\n ${i18next.t('figure.label.role-' + one)}\n </label>\n `\n )}\n </div>\n ${roles.length === 0 ? html`<p quiet>${i18next.t('figure.text.role-none-means-drawn')}</p>` : nothing}\n\n ${roles.includes('slot')\n ? html`\n <div field>\n <label>${i18next.t('figure.label.accepts')}${this.help('figure.text.accepts-explained')}</label>\n <input\n .value=${(part.capability?.accepts ?? []).join(', ')}\n placeholder=${i18next.t('figure.text.accepts-anything')}\n @change=${(e: Event) => this.setAccepts((e.target as HTMLInputElement).value)}\n />\n </div>\n <div field>\n <label>${i18next.t('figure.label.slot-capacity')}</label>\n ${repeats\n ? html`<p quiet>${i18next.t('figure.text.capacity-from-repeat')}</p>`\n : this.number('', part.capability?.capacity ?? 1, value => this.setCapacity(value), 1)}\n </div>\n `\n : nothing}\n </section>\n `\n }\n\n /**\n * How this part hangs from another and moves relative to it (ADR-0066).\n *\n * The parent is written on the part. The joint says how the part moves relative to that parent, and the\n * parameter it comes with is what drives it; the preview shows that parameter as a slider.\n */\n private renderJoint(part: FigurePart) {\n const joint = jointOf(this.draft, part.name)\n const choices = parentChoices(this.parts, part.name)\n const unit = joint?.type === 'prismatic' ? 'mm' : 'deg'\n const axisKey = joint ? axisKeyOf(joint.axis) : undefined\n const driver = joint\n ? this.draft?.parameters?.find(one => one.clip?.channels?.some(channel => channel.target === joint.name))\n : undefined\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.joint')}${this.help('figure.text.joint-explained')}</h3>\n\n <div inline-field>\n <label>${i18next.t('figure.label.joint-parent')}</label>\n <select @change=${(e: Event) => this.setParent((e.target as HTMLSelectElement).value)}>\n <option value=\"\" ?selected=${part.parent === undefined}>${i18next.t('figure.label.joint-parent-none')}</option>\n ${part.parent !== undefined && !choices.includes(part.parent)\n ? html`<option value=${part.parent} selected>${part.parent}</option>`\n : nothing}\n ${choices.map(name => html`<option value=${name} ?selected=${name === part.parent}>${name}</option>`)}\n </select>\n </div>\n\n <div inline-field>\n <label>${i18next.t('figure.label.joint-type')}</label>\n <select @change=${(e: Event) => this.setJointType(part, (e.target as HTMLSelectElement).value)}>\n <option value=\"\" ?selected=${!joint}>${i18next.t('figure.label.joint-type-none')}</option>\n ${(JOINT_TYPES as readonly JointType[]).map(\n type => html`<option value=${type} ?selected=${joint?.type === type}>${i18next.t('figure.label.joint-type-' + type)}</option>`\n )}\n </select>\n </div>\n\n ${joint\n ? html`\n <div inline-field>\n <label>${i18next.t('figure.label.joint-axis')}</label>\n <select @change=${(e: Event) => this.setJointAxis(joint.name, (e.target as HTMLSelectElement).value)}>\n ${axisKey === undefined\n ? html`<option value=\"\" selected>${joint.axis.x}, ${joint.axis.y}, ${joint.axis.z}</option>`\n : nothing}\n ${JOINT_AXES.map(one => html`<option value=${one.key} ?selected=${one.key === axisKey}>${one.key.toUpperCase()}</option>`)}\n </select>\n </div>\n\n <div vector-row>\n <label>${i18next.t('figure.label.joint-origin')}</label>\n <div triple>\n ${(['x', 'y', 'z'] as const).map(axis =>\n this.number(axis.toUpperCase(), joint.origin[axis], value =>\n this.tellDraft(patchJoint(this.draft!, joint.name, { origin: { ...joint.origin, [axis]: value } }))\n )\n )}\n </div>\n </div>\n\n ${joint.limits\n ? html`\n <div vector-row>\n <label>${i18next.t('figure.label.joint-limits-' + unit)}</label>\n <div triple>\n ${this.number(i18next.t('figure.label.joint-limit-min'), joint.limits.min, value =>\n this.tellDraft(patchJoint(this.draft!, joint.name, { limits: { ...joint.limits!, min: value } }))\n )}\n ${this.number(i18next.t('figure.label.joint-limit-max'), joint.limits.max, value =>\n this.tellDraft(patchJoint(this.draft!, joint.name, { limits: { ...joint.limits!, max: value } }))\n )}\n </div>\n </div>\n ${joint.limits.min > 0 || joint.limits.max < 0\n ? html`<p warn>${i18next.t('figure.text.joint-limits-must-include-zero')}</p>`\n : nothing}\n `\n : nothing}\n\n <p quiet>\n ${driver\n ? i18next.t('figure.text.joint-driven-by', { name: driver.label ?? driver.name })\n : i18next.t('figure.text.joint-not-driven')}\n </p>\n `\n : nothing}\n </section>\n `\n }\n\n private setParent(name: string) {\n this.change(part => {\n const { parent: _dropped, ...rest } = part\n return name === '' ? (rest as FigurePart) : { ...rest, parent: name }\n })\n }\n\n private setJointType(part: FigurePart, value: string) {\n if (!this.draft) return\n this.tellDraft(setJointType(this.draft, part, value === '' ? undefined : (value as JointType)))\n }\n\n private setJointAxis(name: string, key: string) {\n const choice = JOINT_AXES.find(one => one.key === key)\n if (!choice || !this.draft) return\n this.tellDraft(patchJoint(this.draft, name, { axis: { ...choice.axis } }))\n }\n\n private tellDraft(draft: FigureDraft) {\n this.dispatchEvent(new CustomEvent('update-draft', { detail: { draft }, bubbles: true, composed: true }))\n }\n\n /**\n * ์—ญํ•  ํ•˜๋‚˜๋ฅผ ์ผœ๊ณ  ๋ˆ๋‹ค.\n *\n * **์—ฌ๋Ÿฟ์„ ํ•จ๊ป˜ ๋งก์„ ์ˆ˜ ์žˆ๋‹ค.** AGV ์˜ ์ƒํŒ์€ ๋ฌผ๊ฑด์„ ๋†“๋Š” ์ž๋ฆฌ์ด๋ฉด์„œ ๊ทธ ์ž๋ฆฌ๋กœ ๋ฌผ๊ฑด์ด\n * ๋“ค์–ด์˜ค๊ณ  ๋‚˜๊ฐ„๋‹ค. ๊ทธ๋ž˜์„œ ํ•˜๋‚˜๋ฅผ ๊ณ ๋ฅด๋Š” ์„ ํƒ ์ƒ์ž๊ฐ€ ์•„๋‹ˆ๋ผ ํ™•์ธ ์ƒ์ž๋‹ค.\n *\n * ๋งˆ์ง€๋ง‰ ์—ญํ• ์„ ๋„๋ฉด `capability` ๋ฅผ ํ†ต์งธ๋กœ ์ง€์šด๋‹ค. ๋นˆ ๋ฐฐ์—ด์„ ๋‚จ๊ธฐ๋ฉด ํ˜•์‹์ด ์˜ค๋ฅ˜๋กœ ๋ณด๊ณ ,\n * ์ €์ž‘์ž๊ฐ€ ๋ณด๊ธฐ์—๋Š” ์•„๋ฌด ์—ญํ• ๋„ ์—†๋Š” ํ‰๋ฒ”ํ•œ ๋ถ€ํ’ˆ์ธ๋ฐ ๋ฐœํ–‰์ด ๋ง‰ํžŒ๋‹ค.\n */\n private toggleRole(role: PartRole, on: boolean) {\n this.change(part => {\n const roles = (part.capability?.roles ?? []).filter(one => one !== role)\n if (on) roles.push(role)\n\n if (roles.length === 0) {\n const { capability, ...rest } = part\n return rest as FigurePart\n }\n\n // ํ˜•์‹์ด ์ ์€ ์ˆœ์„œ๋ฅผ ์ง€ํ‚จ๋‹ค โ€” ์ผ  ์ˆœ์„œ๋Œ€๋กœ ๋‘๋ฉด ๊ฐ™์€ ๋œป์ด ๋‹ค๋ฅธ ๊ฐ’์œผ๋กœ ์ €์žฅ๋œ๋‹ค.\n const ordered = (PART_ROLES as readonly PartRole[]).filter(one => roles.includes(one))\n return { ...part, capability: { ...part.capability, roles: ordered } }\n })\n }\n\n private setAccepts(raw: string) {\n const accepts = raw\n .split(',')\n .map(one => one.trim())\n .filter(one => one.length > 0)\n\n this.change(part => {\n const spec = { ...part.capability, roles: part.capability?.roles ?? ['slot' as PartRole] }\n // ๋นˆ ๋ชฉ๋ก์€ ์ œํ•œํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๋œป์ด๋‹ค. ๋นˆ ๋ฐฐ์—ด์„ ์ €์žฅํ•˜๋ฉด ์•„๋ฌด๊ฒƒ๋„ ๋ชป ๋ฐ›๋Š” ๊ฒƒ์œผ๋กœ ์ฝํžŒ๋‹ค.\n if (accepts.length > 0) spec.accepts = accepts\n else delete spec.accepts\n return { ...part, capability: spec as NonNullable<FigurePart['capability']> }\n })\n }\n\n private setCapacity(value: number) {\n this.change(part => {\n const spec = { ...part.capability, roles: part.capability?.roles ?? ['slot' as PartRole] }\n if (Number.isFinite(value) && value >= 1) spec.capacity = Math.floor(value)\n else delete spec.capacity\n return { ...part, capability: spec as NonNullable<FigurePart['capability']> }\n })\n }\n\n /**\n * ๋„ํ˜• ์ž์ฒด โ€” ์ด๋ฆ„๊ณผ ํƒ€์ž….\n *\n * ## ์™œ ๋จธ๋ฆฌ์ค„์ด ์•„๋‹ˆ๋ผ ์—ฌ๊ธฐ์ธ๊ฐ€\n *\n * ์ €์ž‘๋ฉด ์œ„์— ์ค„์„ ํ•˜๋‚˜ ๋” ๋‘๊ณ  ์ด๋ฆ„ ์นธ์„ ๋†“์•˜์—ˆ๋‹ค. ์•ฑ์—์„œ๋Š” ์…ธ์ด ํŽ˜์ด์ง€ ์ œ๋ชฉ์œผ๋กœ ๊ทธ ์ด๋ฆ„์„\n * ์ด๋ฏธ ๊ทธ๋ฆฌ๋ฏ€๋กœ ๊ฐ™์€ ๊ธ€์ž๊ฐ€ ๋‘ ๋ฒˆ ๋‚˜์˜ค๊ณ , ์บ”๋ฒ„์Šค๊ฐ€ ์ฃผ์ธ๊ณต์ธ ํ™”๋ฉด์—์„œ ๊ทธ ์ค„๋งŒํผ ๋†’์ด๋ฅผ ์žƒ์—ˆ๋‹ค.\n * ์†์„ฑ ํŒจ๋„์€ ใ€Œ์ด ๋„ํ˜•์ด ๋ฌด์—‡์ธ๊ฐ€ใ€๋ฅผ ๋‹ค๋ฃจ๋Š” ์ž๋ฆฌ์ด๋ฏ€๋กœ ์ด๋ฆ„๋„ ์—ฌ๊ธฐ ์‚ฐ๋‹ค.\n *\n * ## ํƒ€์ž…์€ ์ฝ๊ธฐ๋งŒ ํ•œ๋‹ค\n *\n * ์ €์žฅ๋˜๋Š” ์‹๋ณ„์ž๋‹ค. ๋ฐฐ์น˜๋œ ๋„๋ฉด์ด ์ด ์ด๋ฆ„์œผ๋กœ ํƒ€์ž…์„ ์ฐพ์œผ๋ฏ€๋กœ ๋งŒ๋“  ๋’ค์—๋Š” ๋ชป ๋ฐ”๊พผ๋‹ค.\n */\n private renderFigure(compact = false) {\n const fields = html`\n <div inline-field>\n <label>${i18next.t('figure.label.name')}</label>\n <input\n .value=${this.figureName}\n placeholder=${i18next.t('figure.text.figure-display-name')}\n @change=${(e: Event) =>\n this.dispatchEvent(\n new CustomEvent('figure-rename', {\n detail: { name: (e.target as HTMLInputElement).value },\n bubbles: true,\n composed: true\n })\n )}\n />\n </div>\n <div inline-field>\n <label>${i18next.t('figure.label.figure-type')}${this.figureId ? this.helpButton('figure.text.type-name-cannot-change') : nothing}</label>\n ${!this.figureId\n ? html`<input\n .value=${this.draft?.figureType ?? ''}\n placeholder=${i18next.t('figure.text.figure-type-placeholder', { defaultValue: '๋„ํ˜• ์‹๋ณ„ ํƒ€์ž… (์˜ˆ: OHT)' })}\n @change=${(e: Event) =>\n this.dispatchEvent(\n new CustomEvent('figure-type-change', {\n detail: { type: (e.target as HTMLInputElement).value.trim().toUpperCase() },\n bubbles: true,\n composed: true\n })\n )}\n />`\n : html`<code fixed title=${i18next.t('figure.text.type-name-cannot-change')}>\n <md-icon>lock</md-icon>${this.draft?.figureType ?? ''}\n </code>\n ${this.helpHint('figure.text.type-name-cannot-change')}`}\n </div>\n <!--\n ์™œ ๋ชป ๊ณ ์น˜๋Š”์ง€ **์ ์–ด ๋‘”๋‹ค.** ์ „์—๋Š” tooltip ์—๋งŒ ์žˆ์—ˆ๊ณ , ๊ทธ๋Ÿฌ๋ฉด ๋ˆŒ๋Ÿฌ ๋ณด๊ณ  ์•ˆ ๋˜๋Š” ๊ฒƒ์„\n ์•Œ๊ฒŒ ๋œ๋‹ค โ€” ํ™”๋ฉด์ด ์•ˆ ๋˜๋Š” ์ด์œ ๋ฅผ ๋งํ•˜์ง€ ์•Š์œผ๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ์ž๊ธฐ ์‹ค์ˆ˜๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค.\n -->\n\n <div inline-field>\n <label>${i18next.t('figure.label.figure-placement')}${this.helpButton('figure.text.placement-explained')}</label>\n <select\n .value=${this.draft?.placement ?? 'floor'}\n @change=${(e: Event) => this.setPlacement((e.target as HTMLSelectElement).value as FigurePlacement)}\n >\n <option value=\"floor\" ?selected=${(this.draft?.placement ?? 'floor') === 'floor'}>\n ${i18next.t('figure.label.placement-floor')}\n </option>\n <option value=\"ceiling\" ?selected=${this.draft?.placement === 'ceiling'}>\n ${i18next.t('figure.label.placement-ceiling')}\n </option>\n <option value=\"center\" ?selected=${this.draft?.placement === 'center'}>\n ${i18next.t('figure.label.placement-center')}\n </option>\n </select>\n ${this.helpHint('figure.text.placement-explained')}\n </div>\n\n <div inline-field>\n <label>${i18next.t('figure.label.category')}${this.helpButton('figure.text.category-explained')}</label>\n <input\n .value=${this.figureCategory ?? ''}\n placeholder=${i18next.t('figure.text.category-placeholder')}\n @change=${(e: Event) => this.tellCatalog({ category: (e.target as HTMLInputElement).value.trim() || undefined })}\n />\n ${this.helpHint('figure.text.category-explained')}\n </div>\n\n <div inline-field>\n <label>${i18next.t('figure.label.tags')}${this.helpButton('figure.text.tags-explained')}</label>\n <input\n .value=${(this.figureTags ?? []).join(', ')}\n placeholder=${i18next.t('figure.text.tags-placeholder')}\n @change=${(e: Event) => this.tellTags((e.target as HTMLInputElement).value)}\n />\n ${this.helpHint('figure.text.tags-explained')}\n </div>\n `\n\n if (compact) {\n return html`\n <section>\n <details asset>\n <summary>\n <b>${i18next.t('figure.label.figure')}</b>\n <small>${this.figureName || this.draft?.figureType || ''}</small>\n </summary>\n ${fields}\n </details>\n </section>\n `\n }\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.figure')}</h3>\n ${fields}\n </section>\n `\n }\n\n /**\n * ํƒœ๊ทธ ์ค„์„ ๋ชฉ๋ก์œผ๋กœ.\n *\n * ์‰ผํ‘œ๋กœ ๊ฐ€๋ฅด๊ณ  `#` ์€ ๋–ผ์–ด ๋‚ธ๋‹ค โ€” ์‚ฌ๋žŒ์€ `#๋ฐ˜์ถœ` ์ด๋ผ๊ณ  ์ ๊ณ , ์ €์žฅ๋˜๋Š” ๊ฒƒ์€ `๋ฐ˜์ถœ` ์ด๋‹ค.\n * ๊ฒน์นœ ๊ฒƒ์€ ํ•œ ๋ฒˆ๋งŒ ๋‚จ๊ธด๋‹ค. ๋นˆ ์ค„์€ **๋นˆ ๋ฐฐ์—ด**์ด์ง€ `undefined` ๊ฐ€ ์•„๋‹ˆ๋‹ค โ€” ์ „๋ถ€ ์ง€์šฐ๋ ค๋Š”\n * ์ €์ž‘์ž๊ฐ€ ์ง€์šธ ๋ฐฉ๋ฒ•์„ ์žƒ์ง€ ์•Š๊ฒŒ.\n */\n private tellTags(raw: string) {\n const tags = [\n ...new Set(\n raw\n .split(',')\n .map(one => one.trim().replace(/^#+/, '').trim())\n .filter(one => one.length > 0)\n )\n ]\n\n this.tellCatalog({ tags })\n }\n\n /** ์นดํƒˆ๋กœ๊ทธ ๊ฐ’์ด ๋ฐ”๋€Œ์—ˆ๋‹ค๊ณ  ์•Œ๋ฆฐ๋‹ค. ์ •๋ณธ์€ ์ €์ž‘๋ฉด์ด ๋“ ๋‹ค โ€” ์—ฌ๊ธฐ์„œ๋Š” ์•Œ๋ฆฌ๊ธฐ๋งŒ ํ•œ๋‹ค. */\n private tellCatalog(patch: { category?: string; tags?: string[] }) {\n this.dispatchEvent(new CustomEvent('figure-catalog', { detail: patch, bubbles: true, composed: true }))\n }\n\n /**\n * 3D ๋ฐฐ์น˜ ๊ธฐ์ค€๋ฉด์„ ๋ฐ”๊พผ๋‹ค ('floor' | 'ceiling' | 'center').\n *\n * **๋ถ€ํ’ˆ์€ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค.** ์ด ๊ฐ’์€ ใ€Œ์ด ์ข…๋ฅ˜๋Š” ์–ด๋А ๋ฉด์— ๋ถ™๋Š”๊ฐ€ใ€๋ฅผ ๋งํ•  ๋ฟ์ด๊ณ ,\n * ์ €์ž‘ํ•œ ๋ชจ์–‘์€ ๊ทธ๊ฒƒ๊ณผ ๋ฌด๊ด€ํ•˜๋‹ค. ํ˜•์‹์ด ๋ถ€ํ’ˆ์„ ์ƒ์ž ์ค‘์‹ฌ์—์„œ ์žฌ๋ฏ€๋กœ, ๋ฐฐ์น˜๊ฐ€ ๋‹ฌ๋ผ๋„\n * `parts` ๋Š” ํ•œ ๊ธ€์ž๋„ ์•ˆ ๋ฐ”๋€๋‹ค.\n *\n * ํ•œ๋™์•ˆ ์—ฌ๊ธฐ์„œ `zPos` ๋ฅผ ๋‹ค์‹œ ๊ณ„์‚ฐํ–ˆ๋‹ค. ํŽธ์ง‘ ์บ”๋ฒ„์Šค๊ฐ€ ์ด ๊ฐ’์„ ์”ฌ์˜ ์ขŒํ‘œ ๋ชจ๋“œ๋กœ\n * ํ˜๋ ค๋ณด๋‚ด๋˜ ๋•Œ์˜ ์ผ์ธ๋ฐ, ๊ทธ๋Ÿฌ๋ฉด ๋ฐฐ์น˜๋ฅผ ๊ณ ๋ฅผ ๋•Œ๋งˆ๋‹ค ์ €์ž‘์ž๊ฐ€ ์ ์–ด ๋‘” ๋†’์ด๊ฐ€ ์ „๋ถ€\n * ๋‹ค๋ฅธ ์ˆซ์ž๋กœ ๋ณด์˜€๋‹ค โ€” ์ €์žฅ๋˜๋Š” ๊ฒƒ์€ ๊ทธ๋Œ€๋กœ์ธ๋ฐ. ์ขŒํ‘œ ๋ชจ๋“œ๋Š” ์ด์ œ ๋ณด๊ธฐ ์„ค์ •์ด๊ณ \n * (`figure-view.ts`), ํŽธ์ง‘ ์บ”๋ฒ„์Šค๋Š” ๋Š˜ ์ƒ์ž ๊ธฐ์ค€์ด๋‹ค.\n */\n private setPlacement(placement: FigurePlacement) {\n if (!this.draft) return\n const draft = { ...this.draft, placement }\n this.dispatchEvent(new CustomEvent('update-draft', { detail: { draft }, bubbles: true, composed: true }))\n }\n\n private renderIdentity(part: FigurePart) {\n return html`\n <section>\n <h3>${i18next.t('figure.label.part')}</h3>\n <div inline-field>\n <label>${i18next.t('figure.label.name')}${this.helpButton('figure.text.renaming-a-part-breaks-bindings')}</label>\n <input\n .value=${part.name}\n @change=${(e: Event) => this.put({ name: (e.target as HTMLInputElement).value })}\n />\n ${this.helpHint('figure.text.renaming-a-part-breaks-bindings')}\n </div>\n <div inline-field>\n <label>${i18next.t('figure.label.shape')}</label>\n <select @change=${(e: Event) => this.changePrimitive((e.target as HTMLSelectElement).value as PrimitiveKind)}>\n ${PRIMITIVE_KINDS.map(\n kind => html`\n <option value=${kind} ?selected=${kind === part.primitive}>\n ${i18next.t('figure.label.primitive-' + kind)}\n </option>\n `\n )}\n </select>\n </div>\n </section>\n `\n }\n\n private renderPlacement(part: FigurePart) {\n const t = part.transform\n const rotation = t.rotation ?? {}\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.placement')}</h3>\n\n <div vector-row>\n <label>${i18next.t('figure.label.part-position')}</label>\n <div triple>\n ${(['x', 'y', 'z'] as const).map(axis =>\n this.number(axis.toUpperCase(), t.position[axis], value =>\n this.putTransform({ position: { ...t.position, [axis]: value } })\n )\n )}\n </div>\n </div>\n\n <div vector-row>\n <label>${i18next.t('figure.label.part-size')}</label>\n <div triple>\n ${(['x', 'y', 'z'] as const).map(axis =>\n this.number(\n axis.toUpperCase(),\n t.size[axis],\n value => this.putTransform({ size: { ...t.size, [axis]: value } }),\n 1\n )\n )}\n </div>\n </div>\n\n <div vector-row>\n <label>${i18next.t('figure.label.rotation-degrees')}</label>\n <div triple>\n ${(['x', 'y', 'z'] as const).map(axis =>\n this.number(axis.toUpperCase(), rotation[axis] ?? 0, value =>\n this.putTransform({ rotation: { ...rotation, [axis]: value } })\n )\n )}\n </div>\n </div>\n\n <div vector-row>\n <label>${i18next.t('figure.label.tools')}${this.helpButton('figure.text.tools-explained')}</label>\n <div tools>\n <button\n aria-label=${i18next.t('figure.button.center-x')}\n title=${i18next.t('figure.text.center-on-x')}\n @click=${() => this.ask('center', 'x')}\n >\n <md-icon>horizontal_distribute</md-icon>\n </button>\n <button\n aria-label=${i18next.t('figure.button.center-z')}\n title=${i18next.t('figure.text.center-on-z')}\n @click=${() => this.ask('center', 'z')}\n >\n <md-icon>vertical_align_center</md-icon>\n </button>\n <button\n aria-label=${i18next.t('figure.button.to-floor')}\n title=${i18next.t('figure.text.put-on-floor')}\n @click=${() => this.ask('floor', 'y')}\n >\n <md-icon>vertical_align_bottom</md-icon>\n </button>\n ${(['x', 'z'] as const).map(axis => {\n // ์ด๋ฏธ ๊ฐ€์šด๋ฐ๋ฉด ๋Œ€์นญ์ด ์ œ์ž๋ฆฌ๋‹ค โ€” ๊ฒน์นœ ๋ถ€ํ’ˆ์ด ์กฐ์šฉํžˆ ์ƒ๊ธฐ์ง€ ์•Š๊ฒŒ ๋ง‰๋Š”๋‹ค\n const able = this.draft ? canMirror(this.draft, this.parts, this.selected, axis) : false\n return html`\n <button\n ?disabled=${!able}\n aria-label=${i18next.t('figure.button.mirror-' + axis)}\n title=${i18next.t(able ? 'figure.text.mirror-explained' : 'figure.text.mirror-would-overlap')}\n @click=${() => this.ask('mirror', axis)}\n >\n <md-icon>${axis === 'x' ? 'flip' : 'flip_camera_android'}</md-icon>\n </button>\n `\n })}\n <button\n aria-label=${i18next.t('figure.button.snap')}\n title=${i18next.t('figure.text.snap-explained')}\n @click=${() => this.ask('snap', 'x')}\n >\n <md-icon>grid_on</md-icon>\n </button>\n </div>\n ${this.helpHint('figure.text.tools-explained')}\n </div>\n </section>\n `\n }\n\n /** ๋ถ„ํ•  ์ˆ˜์™€ ๋ชจ์„œ๋ฆฌ ๊ตด๋ฆผ โ€” ํ•ด๋‹นํ•˜๋Š” ๋„ํ˜•์—๋งŒ ๋‚ธ๋‹ค. */\n private renderShape(part: FigurePart) {\n const segmented = SEGMENTED_PRIMITIVES.includes(part.primitive)\n const extruded = EXTRUDE_PRIMITIVES.includes(part.primitive)\n if (!segmented && !extruded) return nothing\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.shape-detail')}</h3>\n ${segmented ? this.renderSegments(part) : nothing}\n ${segmented ? this.renderKeepRound(part) : nothing}\n ${extruded ? this.renderExtruded(part) : nothing}\n </section>\n `\n }\n\n /**\n * ๋ฏผ ๋‹จ๋ฉด โ€” ๋ชจ์„œ๋ฆฌ์™€ **์†์„ ํŒŒ๋Š” ๋‘๊ป˜.**\n *\n * ๋ฒฝ ๋‘๊ป˜๋ฅผ 0 ์œผ๋กœ ๋‘๋ฉด ํ†ต์งœ๋‹ค. 0 ๋ณด๋‹ค ํฌ๋ฉด ๊ทธ๋งŒํผ ์•ˆ์œผ๋กœ ๋“ค์–ด์˜จ ํ…Œ๊ฐ€ ์ƒ๊ธฐ๊ณ , ๊ทธ๊ฒƒ์ด\n * ํŠธ๋ ˆ์ด ยท ํ† ํŠธ ยท ํ†ต ยท ์ผ€์ด์Šค๊ฐ€ ๋˜๋Š” ์ž๋ฆฌ๋‹ค. ๋ฐ”๋‹ฅ์€ ๋น„์›Œ ๋‘๋ฉด ๋ฒฝ๊ณผ ๊ฐ™๊ณ , 0 ์œผ๋กœ ๋‘๋ฉด\n * ์œ„์•„๋ž˜๊ฐ€ ๋‹ค ๋šซ๋ฆฐ ํ…Œ๋‘๋ฆฌ๊ฐ€ ๋œ๋‹ค.\n */\n private renderExtruded(part: FigurePart) {\n const hollow = part.shape?.hollow\n const wall = hollow?.wall ?? 0\n\n const reshape = (over: Record<string, unknown>) =>\n this.put({ shape: { ...(part.shape ?? {}), ...over } })\n\n return html`\n <div inline-field>\n <label>${i18next.t('figure.label.corner-round')}</label>\n ${this.number('', part.shape?.round ?? 0, value => reshape({ round: value }))}\n </div>\n <div inline-field>\n <label>${i18next.t('figure.label.hollow-wall')}</label>\n ${this.number('', wall, value =>\n reshape({ hollow: value > 0 ? { ...(hollow ?? {}), wall: value } : undefined })\n )}\n </div>\n ${wall > 0\n ? html`\n <div inline-field>\n <label>${i18next.t('figure.label.hollow-floor')}</label>\n ${this.number('', hollow?.floor ?? wall, value => reshape({ hollow: { ...hollow, wall, floor: value } }))}\n </div>\n `\n : nothing}\n `\n }\n\n /**\n * ๋ถ„ํ•  ์ˆ˜ โ€” ๋ชจ์–‘๊ณผ ๋ฌด๊ฒŒ๋ฅผ ํ•จ๊ป˜ ๊ณ ๋ฅธ๋‹ค.\n *\n * ์‚ผ๊ฐํ˜• ์ˆ˜๋Š” ํ™”๋ฉด์ด ์…ˆํ•˜์ง€ ์•Š๋Š”๋‹ค. `trianglesOf` ์— ๊ทธ ๋ถ„ํ•  ์ˆ˜๋ฅผ ๊ฐ€์ง„ ๋ถ€ํ’ˆ์„ ์ฃผ๊ณ \n * ๋ฌผ์–ด๋ณธ๋‹ค โ€” ํ™”๋ฉด์ด ์ œ ๋‚˜๋ฆ„์˜ ๊ณต์‹์„ ๋“ค๋ฉด figure-model ์ด ๊ทœ์น™์„ ๋ฐ”๊ฟ”๋„ ํ™”๋ฉด๋งŒ\n * ์˜› ๋‹ต์„ ๊ณ„์† ๋‚ธ๋‹ค.\n */\n /**\n * ์›ํ†ต์„ ์›ํ†ต์œผ๋กœ ๋‘˜๊นŒ โ€” **๊ณ ๋ฅด๋Š” ๊ฐ’์ด๊ณ , ๊ฐ’์„ ์น˜๋ฅธ๋‹ค.**\n *\n * ์ธ์Šคํ„ด์Šค๊ฐ€ ์ถ•๋งˆ๋‹ค ๋‹ค๋ฅธ ๋ฐฐ์œจ์„ ๋ฐ›์œผ๋ฉด ์›๊ธฐ๋‘ฅ์ด ํƒ€์› ๊ธฐ๋‘ฅ์ด ๋œ๋‹ค. ์ง€ํ‚ค๋ ค๋ฉด ์ œ ๋ณ€ํ™˜์ด\n * ์žˆ์–ด์•ผ ํ•˜๊ณ , ํ•ฉ์นœ ํ˜•์ƒ์€ ๋ณ€ํ™˜์„ ํ•˜๋‚˜๋งŒ ๋ฐ›์œผ๋ฏ€๋กœ ์ง€ํ‚ค๋Š” ๊ณก๋ฉด ๋ถ€ํ’ˆ ํ•˜๋‚˜๊ฐ€ draw call\n * ํ•˜๋‚˜๋‹ค. ์ €์ž‘์ž๊ฐ€ ๊ทธ ๋Œ€๊ฐ€๋ฅผ ๋ชจ๋ฅด๊ณ  ๊ณ ๋ฅด๋ฉด ์•ˆ ๋˜๋ฏ€๋กœ ๊ทธ ์ž๋ฆฌ์— ์ ๋Š”๋‹ค.\n */\n private renderKeepRound(part: FigurePart) {\n const on = part.keepRound !== false\n\n return html`\n <div field>\n <label>${i18next.t('figure.label.keep-round')}</label>\n <div choices>\n <button choice ?on=${on} @click=${() => this.put({ keepRound: undefined })}>\n <b>${i18next.t('figure.text.keep-round-on')}</b>\n <small>${i18next.t('figure.text.keep-round-cost')}</small>\n </button>\n <button choice ?on=${!on} @click=${() => this.put({ keepRound: false })}>\n <b>${i18next.t('figure.text.keep-round-off')}</b>\n <small>${i18next.t('figure.text.keep-round-merged')}</small>\n </button>\n </div>\n </div>\n `\n }\n\n private renderSegments(part: FigurePart) {\n const current = part.segments ?? SEGMENT_PRESETS[1]\n const common = SEGMENT_PRESETS.slice(0, 4)\n const advanced = SEGMENT_PRESETS.slice(4)\n\n return html`\n <div field>\n <label>${i18next.t('figure.label.segments')}</label>\n <div segments>\n ${common.map(preset => {\n const triangles = trianglesOf({ ...part, segments: preset })\n return html`\n <button seg ?on=${current === preset} @click=${() => this.put({ segments: preset })}>\n ${this.silhouette(preset)}\n <b>${preset}</b>\n <small>${i18next.t('figure.text.n-triangles', { count: triangles })}</small>\n </button>\n `\n })}\n </div>\n\n <details free ?open=${advanced.includes(current)}>\n <summary>${i18next.t('figure.text.more-segment-options')}</summary>\n <div presets>\n ${advanced.map(preset => html`\n <button ?on=${current === preset} @click=${() => this.put({ segments: preset })}>${preset}</button>\n `)}\n </div>\n </details>\n </div>\n `\n }\n\n /**\n * ๋ถ„ํ•  ์ˆ˜์˜ ์‹ค๋ฃจ์—ฃ.\n *\n * ๊ณก๋ฉด ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ๋ฅผ ์œ„์—์„œ ๋ณธ ์œค๊ณฝ์ด ์ •ํ™•ํžˆ ์ •n๊ฐํ˜•์ด๋‹ค โ€” ์›๊ธฐ๋‘ฅ์˜ ๋‹จ๋ฉด๋„, ๊ตฌ์˜\n * ์ ๋„๋„. ๊ทธ๋ฆผ์„ ์ง€์–ด๋‚ด๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์‹ค์ œ๋กœ ๋งŒ๋“ค์–ด์ง€๋Š” ๋ชจ์–‘์ด๋‹ค.\n */\n private silhouette(segments: number) {\n const points: string[] = []\n for (let i = 0; i < segments; i++) {\n // ๊ผญ์ง“์  ํ•˜๋‚˜๊ฐ€ ์œ„๋กœ ์˜ค๊ฒŒ -90๋„์—์„œ ์‹œ์ž‘ํ•œ๋‹ค\n const angle = -Math.PI / 2 + (i * 2 * Math.PI) / segments\n points.push(`${(16 + 13 * Math.cos(angle)).toFixed(2)},${(16 + 13 * Math.sin(angle)).toFixed(2)}`)\n }\n\n return svg`\n <svg viewBox=\"0 0 32 32\" aria-hidden=\"true\">\n <polygon points=${points.join(' ')}></polygon>\n </svg>\n `\n }\n\n /** ๊ฒฌ๋ณธ ํ•œ ์ค„. ๋ฌด๋ฆฌ๋งˆ๋‹ค ๋ถ€๋ฅธ๋‹ค. */\n private palettePurpose(token?: string) {\n const purposes: Record<string, string> = {\n 'palette.primary': 'primary',\n 'palette.accent': 'accent',\n 'palette.neutral': 'neutral',\n 'palette.dark': 'dark',\n 'palette.light': 'light',\n 'palette.surface': 'surface',\n 'palette.status-danger': 'danger',\n 'palette.status-warning': 'warning',\n 'palette.status-info': 'info',\n 'palette.status-success': 'success'\n }\n\n return i18next.t(`figure.label.palette-purpose-${purposes[token ?? ''] ?? 'registered'}`)\n }\n\n private swatches(entries: [string, string][], chosen?: string) {\n return entries.map(\n ([token, color]) => {\n const purpose = this.palettePurpose(token)\n return html`\n <button\n swatch\n ?on=${token === chosen}\n aria-label=${purpose}\n title=${purpose}\n style=\"--swatch:${color}\"\n @click=${() => this.putMaterial({ token })}\n ></button>\n `\n }\n )\n }\n\n private renderMaterial(part: FigurePart) {\n const material = part.material ?? {}\n const palette = activePalette() as Record<string, string>\n\n /*\n ๋‘ ๋ฌด๋ฆฌ๋กœ ๋‚˜๋ˆ  ๋ณด์ธ๋‹ค โ€” **์น ํ•œ ์ƒ‰**๊ณผ **์ผœ์ง„ ์ƒ‰**.\n\n `palette.status-*` ๋Š” ๋žจํ”„ ยท ํ‘œ์‹œ๋“ฑ์— ์“ฐ๋ผ๊ณ  ์žˆ๋Š” ์ƒ‰์ด๋‹ค. ํ•œ ์ค„์— ์„ž์–ด ๋‘๋ฉด\n `accent`(์ฃผํ™ฉ)์™€ `status-warning`(์ฃผํ™ฉ)์ด ๋‚˜๋ž€ํžˆ ๋†“์—ฌ ๋ฌด์—‡์ด ๋ฌด์—‡์ธ์ง€ ์•Œ ์ˆ˜\n ์—†๋‹ค. ๊ฐ’์„ ๋น„ํ‹€์–ด ๋ฒŒ๋ฆฌ๋Š” ๋Œ€์‹  **๊ณ ๋ฅด๋Š” ์ž๋ฆฌ์—์„œ ๊ฒฝ๊ณ„๋ฅผ ๊ธ‹๋Š”๋‹ค.**\n */\n const entries = Object.entries(palette)\n const painted = entries.filter(([token]) => !token.startsWith('palette.status-'))\n const lit = entries.filter(([token]) => token.startsWith('palette.status-'))\n\n /** ์ž์ฒด๋ฐœ๊ด‘. ์—†์œผ๋ฉด ์•ˆ ๋น›๋‚˜๋Š” ๋ถ€ํ’ˆ์ด๋‹ค. */\n const glow = material.emissive\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.part-material')}</h3>\n\n <div field>\n <label>${i18next.t('figure.label.palette-role')}</label>\n <div swatches>\n ${this.swatches(painted, material.token)}\n </div>\n ${lit.length\n ? html`\n <label group>${i18next.t('figure.label.status-colors')}</label>\n <div swatches>\n ${this.swatches(lit, material.token)}\n </div>\n `\n : ''}\n <div palette-meaning>\n <b>${material.token ? this.palettePurpose(material.token) : i18next.t('figure.label.no-color-chosen')}</b>\n <small>${i18next.t('figure.text.palette-purpose-explained')}</small>\n </div>\n </div>\n\n <div field>\n <label>${i18next.t('figure.label.preset')}</label>\n <select\n @change=${(e: Event) => {\n const value = (e.target as HTMLSelectElement).value\n this.putMaterial({ preset: (value || undefined) as MaterialPreset | undefined })\n }}\n >\n <option value=\"\" ?selected=${!material.preset}>${i18next.t('figure.label.none')}</option>\n ${MATERIAL_PRESETS.map(\n preset => html`\n <option value=${preset} ?selected=${preset === material.preset}>\n ${i18next.t('figure.label.preset-' + preset)}\n </option>\n `\n )}\n </select>\n </div>\n\n <!-- ๊ฐ’์ด ์—†์œผ๋ฉด ๊ฐ์ง€๊ฒŒ ๊ทธ๋ฆฐ๋‹ค โ€” ํ˜•์‹์ด ๊ทธ๋ ‡๊ฒŒ ๋ชป ๋ฐ•์•˜๋‹ค. ์ฒดํฌ์ƒ์ž๋„ ๊ทธ๋Œ€๋กœ ๋ณด์ธ๋‹ค -->\n <label toggle>\n <input\n type=\"checkbox\"\n .checked=${material.flatShading ?? true}\n @change=${(e: Event) => this.putMaterial({ flatShading: (e.target as HTMLInputElement).checked })}\n />\n ${i18next.t('figure.label.flat-shading')}\n </label>\n <label toggle>\n <input\n type=\"checkbox\"\n .checked=${!!material.transparent}\n @change=${(e: Event) => this.putMaterial({ transparent: (e.target as HTMLInputElement).checked })}\n />\n ${i18next.t('figure.label.transparent')}\n </label>\n\n <div field>\n <label>${i18next.t('figure.label.emissive')}${this.help('figure.text.emissive-explained')}</label>\n\n <div slider>\n <input\n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n .value=${String(glow?.intensity ?? 0)}\n @input=${(e: Event) => this.putEmissive(Number((e.target as HTMLInputElement).value))}\n />\n <output>${(glow?.intensity ?? 0).toFixed(2)}</output>\n </div>\n </div>\n\n ${glow\n ? html`\n <div field>\n <label>${i18next.t('figure.label.emissive-color')}</label>\n <div swatches>\n <button\n swatch\n same\n ?on=${!glow.token}\n title=${i18next.t('figure.label.same-as-off')}\n style=\"--swatch:${(material.token && palette[material.token]) || palette['palette.neutral']}\"\n @click=${() => this.putMaterial({ emissive: { ...glow, token: undefined } })}\n ></button>\n ${lit.map(\n ([token, color]) => html`\n <button\n swatch\n ?on=${token === glow.token}\n title=${token}\n style=\"--swatch:${color}\"\n @click=${() => this.putMaterial({ emissive: { ...glow, token } })}\n ></button>\n `\n )}\n </div>\n <span token>${glow.token ?? i18next.t('figure.label.same-as-off')}</span>\n </div>\n\n <label toggle>\n <input\n type=\"checkbox\"\n .checked=${!!glow.on}\n @change=${(e: Event) =>\n this.putMaterial({ emissive: { ...glow, on: (e.target as HTMLInputElement).checked } })}\n />\n ${i18next.t('figure.label.on-by-default')}\n </label>\n ${this.help('figure.text.on-by-default-explained')}\n `\n : ''}\n\n </section>\n `\n }\n\n /**\n * ์ธ์Šคํ„ด์Šค ํฌ๊ธฐ๊ฐ€ ๋ฐ”๋€” ๋•Œ ์ด ๋ถ€ํ’ˆ์ด ์–ด๋–ป๊ฒŒ ๋ณ€ํ•˜๋‚˜.\n *\n * ## ๋Š˜์–ด๋‚˜๋Š” ์ถ•์€ ์•„์ง ๋ชป ๋ณด์—ฌ ์ค€๋‹ค\n *\n * `stretch` ๋Š” ํ˜•์‹์— ์ถ•์„ ์ ๋Š” ์ž๋ฆฌ๊ฐ€ ์—†์–ด์„œ ๊ทธ๋ฆฌ๋Š” ์ชฝ์ด **๊ฐ€์žฅ ๊ธธ๊ฒŒ ๋ป—์€ ์ถ•**์œผ๋กœ\n * ์ •ํ•œ๋‹ค. ๊ทธ ๋‹ต์„ ํ™”๋ฉด์— ์ ์–ด ์ฃผ๋ ค๋ฉด ๊ทœ์น™์„ ๊ฐ€์ง„ ์ชฝ์— ๋ฌผ์–ด์•ผ ํ•˜๋Š”๋ฐ, ๊ทธ ํ•จ์ˆ˜\n * (`stretchAxisOf` ยท `stretchAxis`)๊ฐ€ ์•„์ง ๋ฐฐํฌ๋œ ํŒ์— ์—†๋‹ค.\n *\n * ํ™”๋ฉด์ด ์ œ ๋‚˜๋ฆ„๋Œ€๋กœ ๊ณ„์‚ฐํ•˜์ง€ ์•Š๋Š”๋‹ค. ๊ทœ์น™์ด ๋‘ ๋ฒŒ์ด ๋˜๋ฉด ๋ณด์ด๋Š” ์ถ•๊ณผ ์‹ค์ œ๋กœ ๋Š˜์–ด๋‚˜๋Š”\n * ์ถ•์ด ๊ฐˆ๋ฆฌ๊ณ , ๊ทธ ์–ด๊ธ‹๋‚จ์€ ํ™”๋ฉด์„ ๋ฏฟ๊ฒŒ ๋งŒ๋“  ๋‹ค์Œ์— ๋“œ๋Ÿฌ๋‚œ๋‹ค. ๋ฐฐํฌ๋˜๋ฉด ์ž‡๋Š”๋‹ค.\n *\n * ## ๊ฐ’์ด ์žˆ๋Š” ๊ฒƒ์„ ๋ฐํžŒ๋‹ค\n *\n * `scale` ์ด ์•„๋‹Œ ๋ถ€ํ’ˆ์€ ํ•ฉ์ณ ๊ทธ๋ฆด ์ˆ˜ ์—†์–ด draw call ์„ ํ•˜๋‚˜ ๋” ์“ด๋‹ค. ๊ทธ ๋น„์šฉ์ด\n * ์„ฑ์ˆ™๋„์˜ ๋ฌถ์Œ ์ˆ˜์— ๊ทธ๋Œ€๋กœ ์žกํžŒ๋‹ค. ๊ณ ๋ฅด๋Š” ์ž๋ฆฌ์—์„œ ๋ฏธ๋ฆฌ ๋งํ•ด ์ค€๋‹ค.\n */\n private renderBehaviour(part: FigurePart) {\n const sizing = part.sizing ?? 'scale'\n const repeat = part.repeat ?? { axis: 'x' as Axis, pitch: 0 }\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.sizing-rule')}${this.help('figure.text.sizing-' + sizing + '-explained')}</h3>\n <div sizing-choices>\n ${SIZING_RULES.map(\n rule => html`\n <button sizing-choice ?on=${rule === sizing} @click=${() => this.put({ sizing: rule })}>\n <b>${i18next.t('figure.label.sizing-' + rule)}</b>\n <small>${i18next.t('figure.text.sizing-' + rule + '-explained')}</small>\n </button>\n `\n )}\n </div>\n ${sizing === 'scale'\n ? nothing\n : html`<p cost>${i18next.t('figure.text.sizing-costs-one-draw-call')}</p>`}\n\n ${this.renderAnchors(part)}\n\n ${sizing === 'repeat'\n ? html`\n <div inline-field>\n <label>${i18next.t('figure.label.repeat-axis')}</label>\n <select\n @change=${(e: Event) =>\n this.put({ repeat: { ...repeat, axis: (e.target as HTMLSelectElement).value as Axis } })}\n >\n ${(['x', 'y', 'z'] as const).map(\n axis => html`<option value=${axis} ?selected=${axis === repeat.axis}>${axis}</option>`\n )}\n </select>\n </div>\n <div inline-field>\n <label>${i18next.t('figure.label.repeat-pitch')}${this.helpButton('figure.text.repeat-pitch-explained')}</label>\n ${this.number('', repeat.pitch, value => this.put({ repeat: { ...repeat, pitch: value } }), 1)}\n ${this.helpHint('figure.text.repeat-pitch-explained')}\n </div>\n ${this.renderRepeatCount(part)}\n `\n : nothing}\n </section>\n `\n }\n\n /**\n * โ”€โ”€ ๋ช‡ ๊ฐœ๊ฐ€ ๋˜๋‚˜ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n *\n * ์ €์ž‘ ํ™”๋ฉด์€ ์ถ•๊ณผ ํ”ผ์น˜๋งŒ ๋ฐ›๊ณ  ์žˆ์—ˆ๋‹ค. ํ˜•์‹์ด ๊ฐ€์ง„ ๋ฐ˜๋ณต ์„ค์ •์ด ๊ทธ ๋‘˜๋ฟ์ด๋ฏ€๋กœ ํŽธ์ง‘ํ•  ๊ฒƒ์€\n * ๋‹ค ์žˆ์—ˆ๋Š”๋ฐ, **๊ฒฐ๊ณผ์ธ ๊ฐœ์ˆ˜๋ฅผ ์–ด๋””์—๋„ ํ‘œ์‹œํ•˜์ง€ ์•Š์•˜๋‹ค.** ํ”ผ์น˜ 300 ์„ ์ ์€ ์ €์ž‘์ž๊ฐ€ ๋ช‡ ๊ฐœ๊ฐ€\n * ๋˜๋Š”์ง€ ์•Œ๋ ค๋ฉด ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ฅผ ์„ธ์–ด์•ผ ํ–ˆ๋‹ค.\n *\n * ๊ฐœ์ˆ˜๋Š” ๊ทธ๋ฆฌ๋Š” ์ชฝ์ด ์“ฐ๋Š” `repeatPlan` ์„ ๊ทธ๋Œ€๋กœ ๋ถˆ๋Ÿฌ ์–ป๋Š”๋‹ค. ์—ฌ๊ธฐ์„œ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜๋ฉด ํ™”๋ฉด์ด\n * ๋งํ•˜๋Š” ๊ฐœ์ˆ˜์™€ ์‹ค์ œ๋กœ ๊ทธ๋ ค์ง€๋Š” ๊ฐœ์ˆ˜๊ฐ€ ๋‹ฌ๋ผ์ง„๋‹ค.\n *\n * ## ๋‘ ๊ฐ€์ง€ ๋ฐ˜๋ณต์ด ์žˆ๋‹ค\n *\n * ์ปจ๋ฒ ์ด์–ด์˜ ๋กค๋Ÿฌ๋Š” ๊ธธ์–ด์ง€๋ฉด **๊ฐœ์ˆ˜๊ฐ€ ๋Š˜๊ณ ** ํ•œ ์นธ ๊ฐ„๊ฒฉ์€ ๊ทธ๋Œ€๋กœ๋‹ค. ์…€ํŠธ๋ ˆ์ด์˜ ์…€์€ ์ปค์ง€๋ฉด\n * **์…€์ด ์ปค์ง€๊ณ ** ๊ฐœ์ˆ˜๋Š” ๊ทธ๋Œ€๋กœ๋‹ค โ€” ๋ช‡ ์…€์งœ๋ฆฌ ํŠธ๋ ˆ์ด๋ƒ๋Š” ํ™”๋ฉด ํฌ๊ธฐ์™€ ๋ฌด๊ด€ํ•˜๋‹ค. ๊ทธ ๊ฐˆ๋ฆผ์„\n * ์ด ์ถ•์˜ anchor ๊ฐ€ ์ •ํ•˜๋Š”๋ฐ ํ™”๋ฉด์—๋Š” ๊ทธ ๋ง์ด ์—†์—ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์–ด๋А ์ชฝ์ธ์ง€ ํ•จ๊ป˜ ์ ๋Š”๋‹ค.\n */\n private renderRepeatCount(part: FigurePart) {\n const draft = this.draft\n if (!draft) return nothing\n\n const base = { x: draft.width, y: draft.depth, z: draft.height }\n const plan = repeatPlanOfPart(part, { x: 1, y: 1, z: 1 }, base)\n if (!plan) return nothing\n\n const grows = anchorOfPart(part, base, plan.axis) !== 'scale'\n\n return html`\n <div field>\n <label>${i18next.t('figure.label.repeat-count')}</label>\n <p quiet>\n ${i18next.t('figure.text.repeat-count-now', { count: plan.count })}\n ${plan.count >= REPEAT_LIMIT\n ? html`<br />${i18next.t('figure.text.repeat-count-capped', { limit: REPEAT_LIMIT })}`\n : ''}\n <br />${i18next.t(grows ? 'figure.text.repeat-grows-with-instance' : 'figure.text.repeat-keeps-count')}\n </p>\n </div>\n `\n }\n\n /**\n * โ”€โ”€ ์–ด๋А ๋ฉด์„ ๋ถ™์žก๋‚˜ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n *\n * **์ด ์ž๋ฆฌ๊ฐ€ ์—†์—ˆ๋‹ค.** ํ˜•์‹์€ ์ถ•๋งˆ๋‹ค `anchor` ๋ฅผ ์ง€๊ณ  ๋‹ค๋‹ˆ๊ณ (`figure-source.ts` ๊ฐ€ ์™•๋ณต์‹œํ‚จ๋‹ค),\n * ๋ฐœํ–‰ ๊ฒŒ์ดํŠธ๋Š” ใ€Œvalve-wheel ์˜ anchor.z ๋ฅผ max ๋กœ ๋‘๋ผใ€๊ณ  ์‚ฌ์œ ๊นŒ์ง€ ๋งํ•˜๋Š”๋ฐ, ์ €์ž‘๋ฉด์—๋Š” ๊ทธ\n * ๊ฐ’์„ ๋ฐ”๊ฟ€ ์ž๋ฆฌ๊ฐ€ ์—†์—ˆ๋‹ค โ€” ๊ณ ์น˜๋ผ๋Š” ๋ง๋งŒ ์žˆ๊ณ  ๊ณ ์น  ๋ฌธ์ด ์—†์—ˆ๋‹ค.\n *\n * ## ใ€Œ์ž๋™ใ€์ด ๊ธฐ๋ณธ์ด๋‹ค\n *\n * ํ˜•์‹์—์„œ `anchor` ๋Š” ์ ์ง€ ์•Š์•„๋„ ๋œ๋‹ค. ์•ˆ ์ ์œผ๋ฉด **๊ฐ€๊นŒ์šด ๋ฉด**์„ ๋ถ™์žก๊ณ , ํ‘œ๋ณธ ์—ด๋„ท ์ค‘ ์–ด๋А\n * ๊ฒƒ๋„ ์ด ๊ฐ’์„ ์ ์ง€ ์•Š๊ณ  ์ œ๋Œ€๋กœ ์„ ๋‹ค. ๊ทธ๋ž˜์„œ ์ถ•๋งˆ๋‹ค ์ฒซ ํ•ญ๋ชฉ์ด ใ€Œ์ž๋™ใ€์ด๊ณ , ์ง€๊ธˆ ์ž๋™์ด ๋ฌด์—‡์œผ๋กœ\n * ์ฝํžˆ๋Š”์ง€๋ฅผ **ํ•จ๊ป˜ ๋ณด์—ฌ ์ค€๋‹ค** โ€” ๊ทธ๊ฒƒ์„ ๋ชจ๋ฅด๋ฉด ๋ฌด์—‡์„ ๋ฐ”๊พธ๋Š”์ง€ ๋ชจ๋ฅธ ์ฑ„ ๊ณ ๋ฅด๊ฒŒ ๋œ๋‹ค.\n *\n * ์ž๋™์ด ๋ฌด์—‡์ธ์ง€๋Š” ํ˜•์‹์—๊ฒŒ ๋ฌป๋Š”๋‹ค(`anchorOfPart`). ์—ฌ๊ธฐ์„œ ใ€Œ์œ„ ์ ˆ๋ฐ˜์ด๋ฉด maxใ€๋ฅผ ๋‹ค์‹œ ์„ธ๋ฉด\n * ํ™”๋ฉด์ด ๋งํ•˜๋Š” ๋ฉด๊ณผ ์‹ค์ œ๋กœ ๊ทธ๋ ค์ง€๋Š” ๋ฉด์ด ๊ฐˆ๋ฆฐ๋‹ค.\n *\n * ## `scale` ์ธ ๋ถ€ํ’ˆ์—๋„ ๋ณด์—ฌ ์ค€๋‹ค\n *\n * ์ฒ˜์Œ์—๋Š” ๊ฐ์ท„๋‹ค โ€” ํ˜•์‹ ์ฃผ์„์— ใ€Œ`sizing` ์ด `scale` ์ธ ๋ถ€ํ’ˆ์—๋Š” ๋œป์ด ์—†๋‹คใ€๊ณ  ์ ํ˜€ ์žˆ์–ด์„œ๋‹ค.\n * **๊ทธ ๋ฌธ์žฅ์€ ๊ธฐ๋ณธ๊ฐ’์— ๋Œ€ํ•œ ๊ฒƒ์ด๋‹ค.** `anchorOf` ๋Š” ์ ํžŒ ๊ฐ’์„ ๊ฐ€์žฅ ๋จผ์ € ๋ณด๊ณ (`if (said) return\n * said`), ๊ทธ ๋’ค์—์•ผ `sizing` ์„ ๋ณธ๋‹ค. ์ฆ‰ `scale` ๋ถ€ํ’ˆ์—๋„ ๋ฉด์„ ์ ์œผ๋ฉด ๊ทธ๊ฒƒ์ด ์ด๊ธด๋‹ค.\n *\n * ๊ฐ์ถฐ ๋‘๋ฉด ์–ด๊ธ‹๋‚จ์ด ๋‚œ๋‹ค: ๋ฐœํ–‰ ๊ฒŒ์ดํŠธ๊ฐ€ ๋ง‰๋Š” MIXER ์˜ `valve-wheel` ์ด `scale` ๋ถ€ํ’ˆ์ด๊ณ ,\n * ๊ฒŒ์ดํŠธ์˜ ์‚ฌ์œ ๋Š” ใ€Œ๊ทธ ๋ถ€ํ’ˆ์˜ anchor.z ๋ฅผ max ๋กœ ๋‘๋ผใ€๋‹ค. ๊ณ ์น˜๋ผ๋Š” ์ž๋ฆฌ์— ๋ฌธ์„ ๋‹ซ์•„ ๋‘” ์…ˆ์ด์—ˆ๋‹ค.\n *\n * ๋Œ€์‹  `scale` ์ผ ๋•Œ๋Š” ์ž๋™์ด ๋ฌด์—‡์ธ์ง€๊ฐ€ ใ€Œํ•จ๊ป˜ ์ปค์ง„๋‹คใ€๋กœ ๋ณด์ด๋ฏ€๋กœ, ์ €์ž‘์ž๊ฐ€ ๊ทธ๊ฒƒ์„ ๋ฐ”๊พธ๋Š”\n * ๊ฒƒ์ž„์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.\n */\n /**\n * โ”€โ”€ ๋„์›€๋ง์€ ์ž๋ฆฌ๋ฅผ ๋จน์ง€ ์•Š๋Š”๋‹ค โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n *\n * ์„ค๋ช… ๋ฌธ๋‹จ์ด ์—ด ์ค„ ์žˆ์—ˆ๊ณ  ๊ทธ ์ค„๋“ค์ด ํŒจ๋„ ๋†’์ด์˜ ์ƒ๋‹น ๋ถ€๋ถ„์ด์—ˆ๋‹ค. ์†์„ฑ์€ ์•ž์œผ๋กœ ๋” ๋Š˜์–ด๋‚œ๋‹ค\n * (๋Šฅ๋ ฅ ยท ํฌํŠธ ยท ์• ๋‹ˆ๋ฉ”์ด์…˜ ยท ๊ธฐ์ค€์ •๋ณด) โ€” ๋Š˜ ๋ณด์ด๋Š” ์„ค๋ช…์€ ๊ทธ ์ž๋ฆฌ๋ฅผ ๋จผ์ € ๋จน๋Š”๋‹ค.\n *\n * ๊ทธ๋ž˜์„œ ๋ฌผ์Œํ‘œ๋กœ ์ ‘๋Š”๋‹ค. **์ง€์šฐ์ง€ ์•Š๋Š”๋‹ค** โ€” ๊ทธ ๋ฌธ์žฅ๋“ค์€ ใ€Œ์ด๊ฑธ ๊ณ ๋ฅด๋ฉด ๋ฌด์—‡์ด ๋‹ฌ๋ผ์ง€๋‚˜ใ€๋ฅผ\n * ๋งํ•˜๋Š” ๊ฒƒ์ด๊ณ , ์—†์œผ๋ฉด ๋‹ซํžŒ ๋ชฉ๋ก์„ ๊ณ ๋ฅผ ์ˆ˜ ์—†๋‹ค. ํ•œ ๋ฒˆ ์ฝ์œผ๋ฉด ๋˜๋Š” ๊ฒƒ์ด๋ผ ์ ‘์–ด ๋‘๋Š” ๊ฒƒ์ด ๋งž๋‹ค.\n *\n * ํŽธ ๊ฒƒ์€ **๋ถ€ํ’ˆ์„ ๋ฐ”๊ฟ”๋„ ๊ทธ๋Œ€๋กœ ๋‘”๋‹ค**(`opened` ๋Š” ๋ถ€ํ’ˆ์— ๋”ธ๋ฆฐ ์ƒํƒœ๊ฐ€ ์•„๋‹ˆ๋‹ค). ๊ฐ™์€ ๊ฒƒ์„\n * ๊ณ„์† ๊ณ ์น˜๋Š” ์‚ฌ๋žŒ์ด ๋งค๋ฒˆ ๋‹ค์‹œ ํŽด์•ผ ํ•˜๋ฉด ์ ‘์€ ๊ฒƒ์ด ๋˜๋ ˆ ๋ฐฉํ•ด๊ฐ€ ๋œ๋‹ค.\n */\n private help(key: string) {\n return html`${this.helpButton(key)}${this.helpHint(key)}`\n }\n\n private helpButton(key: string) {\n const shown = this.opened.has(key)\n\n return html`\n <button\n help\n aria-label=${i18next.t('figure.label.help')}\n aria-expanded=${shown ? 'true' : 'false'}\n @click=${() => {\n shown ? this.opened.delete(key) : this.opened.add(key)\n this.requestUpdate()\n }}\n >\n <md-icon>${shown ? 'help' : 'help_outline'}</md-icon>\n </button>\n `\n }\n\n private helpHint(key: string) {\n return this.opened.has(key) ? html`<p hint>${i18next.t(key)}</p>` : nothing\n }\n\n private renderAnchors(part: FigurePart) {\n /*\n The scene draft stores the box height as depth, so format y is draft.depth and z is draft.height.\n This used to pass them swapped, and every automatic anchor still came out the same: the\n nearest-face rule reads the sign of a centred position, which does not depend on the box size.\n It is fixed so the next rule that does read the box does not inherit the mistake.\n */\n const base = this.draft\n ? { x: this.draft.width, y: this.draft.depth, z: this.draft.height }\n : { x: 0, y: 0, z: 0 }\n const nameOf = (rule: string, axis: Axis) =>\n `${i18next.t(rule === 'min' || rule === 'max' ? `figure.label.anchor-${rule}-${axis}` : `figure.label.anchor-${rule}`)} (${rule})`\n const setAnchor = (axis: Axis, rule?: AnchorRule) => {\n const anchor = { ...(part.anchor ?? {}) }\n /* ใ€Œ์ž๋™ใ€์€ ์นธ์„ ์ง€์šฐ๋Š” ๊ฒƒ์ด๋‹ค โ€” ๋นˆ ๊ฐ’์„ ๋„ฃ์–ด ๋‘๋ฉด ํ˜•์‹์ด ๊ทธ๊ฒƒ์„ ๊ฐ’์œผ๋กœ ์ฝ๋Š”๋‹ค. */\n if (rule) anchor[axis] = rule\n else delete anchor[axis]\n this.put({ anchor: Object.keys(anchor).length ? anchor : undefined })\n }\n const shortNameOf = (rule: AnchorRule | 'auto', axis: Axis) => {\n if (rule === 'auto') return i18next.t('figure.label.anchor-choice-auto')\n if (rule === 'min' || rule === 'max') return i18next.t(`figure.label.anchor-choice-${rule}-${axis}`)\n return i18next.t(`figure.label.anchor-choice-${rule}`)\n }\n\n return html`\n <div field>\n <!-- ์ €์žฅ ํ‚ค(anchor)๋Š” ๋‚จ๊ธฐ๋˜, ์‚ฌ์šฉ์ž๋Š” ์ถ•๋งˆ๋‹ค ์–ด๋А ๋ฉด์„ ๊ธฐ์ค€์œผ๋กœ ์‚ผ๋Š”์ง€ ์ฝ๋Š”๋‹ค. -->\n <label>${i18next.t('figure.label.anchor')} (anchor)${this.help('figure.text.anchor-explained')}</label>\n <div anchor-rows>\n ${(['x', 'y', 'z'] as const).map(axis => {\n const said = part.anchor?.[axis]\n const auto = anchorOfPart(part, base, axis)\n\n /*\n **๋ฉด ์ด๋ฆ„์€ ์ถ•๋งˆ๋‹ค ๋‹ค๋ฅด๋‹ค.** ์ฒ˜์Œ์—๋Š” min ์„ ใ€Œ์•„๋ž˜ยท์™ผ์ชฝยท๋’ค ๋ฉดใ€์œผ๋กœ ํ•œ ์ค„์— ๋‹ค ์ ์—ˆ๋Š”๋ฐ,\n x ์ค„์—์„œ ใ€Œ์•„๋ž˜ใ€์™€ ใ€Œ๋’คใ€๋Š” ๊ด€๊ณ„๊ฐ€ ์—†์–ด ์ฝ๋Š” ์‚ฌ๋žŒ์ด ๋ฌด์—‡์„ ๊ณ ๋ฅด๋Š”์ง€ ๋ชฐ๋ž๋‹ค.\n\n ๊ทธ๋ฆฌ๊ณ  ์ด๋ฆ„์”จ๊ฐ€ ์•„๋‹ˆ๋ผ **๋™์ž‘**์œผ๋กœ ์ ๋Š”๋‹ค โ€” ใ€Œ์˜ค๋ฅธ์ชฝ ๋ฉดใ€์ด ์•„๋‹ˆ๋ผ ใ€Œ์˜ค๋ฅธ์ชฝ ๋ฉด์— ๋ถ™์–ด\n ์žˆ๋Š”๋‹คใ€๋‹ค. ใ€Œanchor.x ๋ฅผ max ๋กœ ๋‘”๋‹คใ€๊ฐ€ ๋ฌด์Šจ ๋œป์ธ์ง€ ๋ชจ๋ฅด๊ฒ ๋‹ค๋Š” ๋ง์ด ๊ทธ ์ž๋ฆฌ์—์„œ ๋‚˜์™”๋‹ค.\n */\n /*\n **๊ฐ’ ์ด๋ฆ„์„ ํ•จ๊ป˜ ๋ณด์ธ๋‹ค.** ๋™์ž‘๋งŒ ์ ์—ˆ๋”๋‹ˆ(ใ€Œ์˜ค๋ฅธ์ชฝ ๋ฉด์— ๋ถ™์–ด ์žˆ๋Š”๋‹คยป) ๋ฐœํ–‰ ๊ฒŒ์ดํŠธ๊ฐ€\n ใ€Œanchor.x ๋ฅผ max ๋กœ ๋‘๋ผใ€๊ณ  ๋งํ•  ๋•Œ ํ™”๋ฉด์—์„œ ๊ทธ ๋‚ฑ๋ง์„ ์ฐพ์„ ์ˆ˜ ์—†์—ˆ๋‹ค โ€” ์‚ฌ์šฉ์ž๊ฐ€\n ๊ทธ ์ž๋ฆฌ์—์„œ ์ง€์ ํ–ˆ๋‹ค.\n\n `max` ๋Š” ์ •๋ณธ์— ์ €์žฅ๋˜๋Š” ์ด๋ฆ„์ด๊ณ  ์„œ๋ฒ„ ์˜ค๋ฅ˜ยทํ˜•์‹ ๋ฌธ์„œยท๊ฒŒ์ดํŠธ ์‚ฌ์œ ๊ฐ€ ๋‹ค ๊ทธ ์ด๋ฆ„์„ ์“ด๋‹ค.\n ์ˆจ๊ธฐ๋ฉด ์•ˆ ๋˜๋Š” ์ข…๋ฅ˜๋‹ค. ๋™์ž‘์ด ๋จผ์ €๊ณ  ์ด๋ฆ„์ด ๊ด„ํ˜ธ๋กœ ๋”ฐ๋ผ์˜จ๋‹ค.\n */\n return html`\n <div anchor-row>\n <label>${i18next.t('figure.label.axis-name', { axis: axis.toUpperCase() })}</label>\n <div anchor-options>\n ${(['auto', 'scale', 'min', 'center', 'max', 'span'] as const).map(rule => {\n const selected = rule === 'auto' ? !said : rule === said\n const fullName = rule === 'auto' ? i18next.t('figure.label.anchor-auto', { rule: nameOf(auto, axis) }) : nameOf(rule, axis)\n return html`\n <button\n anchor-choice\n ?on=${selected}\n aria-pressed=${selected ? 'true' : 'false'}\n title=${fullName}\n @click=${() => setAnchor(axis, rule === 'auto' ? undefined : rule)}\n >${shortNameOf(rule, axis)}</button>\n `\n })}\n </div>\n <details anchor-advanced>\n <summary>${i18next.t('figure.label.anchor-advanced')}</summary>\n <div anchor-options>\n ${ANCHOR_RULES.filter(rule => rule.startsWith('aspect-')).map(rule => html`\n <button\n anchor-choice\n ?on=${rule === said}\n aria-pressed=${rule === said ? 'true' : 'false'}\n title=${nameOf(rule, axis)}\n @click=${() => setAnchor(axis, rule)}\n >${i18next.t(`figure.label.anchor-choice-${rule}`)}</button>\n `)}\n </div>\n </details>\n </div>\n `\n })}\n </div>\n </div>\n `\n }\n\n /**\n * ์ˆซ์ž ์นธ.\n *\n * ๋นˆ ์นธ์ด๋‚˜ ๊ธ€์ž๋ฅผ ๋„ฃ์—ˆ์„ ๋•Œ 0 ์œผ๋กœ ๋ฐ”๊ฟ”์น˜์ง€ ์•Š๋Š”๋‹ค โ€” ์ €์ž‘์ž๊ฐ€ ์ง€์šฐ๋Š” ์ค‘์ผ ์ˆ˜ ์žˆ๊ณ ,\n * ์กฐ์šฉํžˆ 0 ์ด ๋˜๋ฉด ๋ถ€ํ’ˆ์ด ์‚ฌ๋ผ์ง„ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ธ๋‹ค. ์ˆซ์ž๊ฐ€ ์•„๋‹ˆ๋ฉด ๊ทธ๋ƒฅ ์•ˆ ๋ฐ›๋Š”๋‹ค.\n */\n private number(label: string, value: number, set: (value: number) => void, min?: number) {\n return html`\n <div cell>\n ${label ? html`<span axis>${label}</span>` : nothing}\n <input\n type=\"number\"\n .value=${String(value)}\n min=${min ?? nothing}\n @change=${(e: Event) => {\n const raw = (e.target as HTMLInputElement).value\n const parsed = Number(raw)\n if (raw === '' || !Number.isFinite(parsed)) {\n // ๋˜๋Œ๋ ค ๋†“๋Š”๋‹ค. ์•ˆ ๊ทธ๋Ÿฌ๋ฉด ํ™”๋ฉด๊ณผ ์ •๋ณธ์ด ๊ฐˆ๋ฆฐ๋‹ค.\n ;(e.target as HTMLInputElement).value = String(value)\n return\n }\n set(parsed)\n }}\n />\n </div>\n `\n }\n\n /**\n * ๋„ํ˜•์„ ๋ฐ”๊พผ๋‹ค.\n *\n * ๋„ํ˜•์ด ๋ฐ”๋€Œ๋ฉด ๊ทธ ๋„ํ˜•์— ๋œป ์—†๋Š” ๊ฐ’์ด ๋‚จ๋Š”๋‹ค. ๋‚จ๊ฒจ ๋‘๋ฉด ๊ฒ€์ฆ์ด ใ€Œ๋ฌด์‹œ๋จใ€ ์œ„๋ฐ˜์„\n * ๋‚ด๋ฏ€๋กœ ์—ฌ๊ธฐ์„œ ๊ฑท๋Š”๋‹ค.\n */\n private changePrimitive(primitive: PrimitiveKind) {\n this.change(part => {\n const next: FigurePart = { ...part, primitive }\n if (!SEGMENTED_PRIMITIVES.includes(primitive)) delete next.segments\n if (!EXTRUDE_PRIMITIVES.includes(primitive)) delete next.shape\n if (SEGMENTED_PRIMITIVES.includes(primitive) && next.segments === undefined) {\n next.segments = SEGMENT_PRESETS[1]\n }\n return next\n })\n }\n\n private put(patch: Partial<FigurePart>) {\n this.change(part => ({ ...part, ...patch }))\n }\n\n private putTransform(patch: Record<string, unknown>) {\n this.change(part => ({ ...part, transform: { ...part.transform, ...patch } as FigurePart['transform'] }))\n }\n\n /**\n * ๋ฐœ๊ด‘ ์„ธ๊ธฐ๋ฅผ ๊ณ ์นœ๋‹ค. **0 ์ด๋ฉด ๋ธ”๋ก์„ ํ†ต์งธ๋กœ ์ง€์šด๋‹ค.**\n *\n * ์„ธ๊ธฐ 0 ์ธ ๋ฐœ๊ด‘์„ ๋‚จ๊ฒจ ๋‘๋ฉด ใ€Œ์•ˆ ๋น›๋‚˜๋Š”๋ฐ ๋žจํ”„์ธ ๊ฒƒใ€์ด ๋˜์–ด, ์žฌ์งˆ ํ‚ค๊ฐ€ ๊ฐˆ๋ ค ๋ฌถ์Œ์ด\n * ํ—›๋˜์ด ํ•˜๋‚˜ ๋Š”๋‹ค. 0 ์€ ใ€Œ๋žจํ”„๊ฐ€ ์•„๋‹ˆ๋‹คใ€๋กœ ์ฝ๋Š” ๊ฒƒ์ด ๋งž๋‹ค.\n *\n * `Number(value) || undefined` ๋ฅผ ์“ฐ๋ฉด ์•ˆ ๋œ๋‹ค โ€” 0 ์ด falsy ๋ผ ๋ณ€๊ฒฝ์œผ๋กœ ์•ˆ ์žกํ˜€ ์˜›\n * ๊ฐ’์ด ๊ทธ๋Œ€๋กœ ๋‚จ๋Š”๋‹ค. ์‹ค์ œ๋กœ ๋žจํ”„๊ฐ€ ์•ˆ ๊บผ์กŒ๋‹ค.\n */\n private putEmissive(intensity: number) {\n // `chosen` ์€ ์”ฌ ๋ชจ๋ธ์ด๋‹ค. ํ˜•์‹์œผ๋กœ ์˜ฎ๊ธด ๊ฐ’์€ `partToFigure` ์ด ๋งŒ๋“  ๊ฒƒ์ด๋ผ ์—ฌ๊ธฐ์„œ ๋‹ค์‹œ ๊บผ๋‚ธ๋‹ค.\n const glow = this.draft && this.chosen ? partToFigure(this.chosen, this.draft).material?.emissive : undefined\n\n this.putMaterial({ emissive: intensity > 0 ? { ...glow, intensity } : undefined })\n }\n\n private putMaterial(patch: Record<string, unknown>) {\n this.change(part => ({\n ...part,\n material: { ...(part.material ?? {}), ...patch } as FigurePart['material']\n }))\n }\n\n /**\n * ์ˆ˜์ •ํ•œ ๊ฒƒ์„ ์”ฌ ๋ชจ๋ธ๋กœ ๋˜๋Œ๋ ค ์•Œ๋ฆฐ๋‹ค.\n *\n * ์‚ฌ์šฉ์ž๋Š” XยทYยทZ ๋กœ ์ˆ˜์ •ํ•˜๊ณ , ๋ชจ๋ธ๋Ÿฌ ํŽ˜์ด์ง€๋Š” ์”ฌ ๋ชจ๋ธ์„ ๊ฐ–๋Š”๋‹ค. ๊ทธ ์‚ฌ์ด๋ฅผ ์—ฌ๊ธฐ์„œ\n * ์ž‡๋Š”๋‹ค โ€” ๋ณ€ํ™˜ํ•ด์„œ ์ˆ˜์ •ํ•˜๊ณ  ๋‹ค์‹œ ๋˜๋Œ๋ฆฐ๋‹ค. **์™•๋ณต ๋ณ€ํ™˜์ด ๋ฌด์†์‹ค์ด๋ผ์•ผ** ์œ„์น˜ ํ•˜๋‚˜\n * ๊ณ ์ณค์„ ๋ฟ์ธ๋ฐ ํšŒ์ „๊ฐ’์ด ์กฐ๊ธˆ์”ฉ ๋ฐ€๋ฆฌ๋Š” ์ผ์ด ์—†๋‹ค(`fold.test.ts` ๊ฐ€ ์ด๋ฅผ ํ™•์ธํ•œ๋‹ค).\n */\n private change(edit: (part: FigurePart) => FigurePart) {\n const part = this.chosen\n const draft = this.draft\n if (!part || !draft) return\n\n this.emit(partFromFigure(edit(partToFigure(part, draft)), draft))\n }\n\n /** ์ •๋ฐ€ ๋„๊ตฌ๋ฅผ ์‹œํ‚จ๋‹ค. ์ •๋ณธ์€ ์ €์ž‘๋ฉด์ด ๊ฐ–๋Š”๋‹ค โ€” ์—ฌ๊ธฐ์„œ๋Š” ์•Œ๋ฆฌ๊ธฐ๋งŒ ํ•œ๋‹ค. */\n private ask(what: string, axis: string) {\n this.dispatchEvent(\n new CustomEvent('part-tool', {\n detail: { index: this.selected, tool: what, axis },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private emit(part: PartModel) {\n this.dispatchEvent(\n new CustomEvent('update-part', { detail: { index: this.selected, part }, bubbles: true, composed: true })\n )\n }\n}\n"]}
1
+ {"version":3,"file":"figure-inspector.js","sourceRoot":"","sources":["../../client/modeller/figure-inspector.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AAEnC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AACzD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAA;AAE7C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,YAAY,EAEZ,WAAW,EACZ,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAa5H,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAEtD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAEjE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACnF,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAGpE,6FAA6F;AAC7F,MAAM,UAAU,GAA2C;IACzD,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;IACzC,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;IAC1C,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;IACzC,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;IAC1C,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;IACzC,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE;CAC3C,CAAA;AAED,SAAS,SAAS,CAAC,IAAU;IAC3B,OAAO,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,CAAA;AAC7G,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEI,IAAM,eAAe,GAArB,MAAM,eAAgB,SAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC;IAA3D;;QAyvBL,sCAAsC;QACV,aAAQ,GAAG,EAAE,CAAA;QAEzC;;WAEG;QACyB,kBAAa,GAAG,CAAC,CAAA;QAW7C,sEAAsE;QAC1C,eAAU,GAAG,EAAE,CAAA;QAM3C,+CAA+C;QAC9B,WAAM,GAAG,IAAI,GAAG,EAAU,CAAA;QAG3C,4BAA4B;QACD,UAAK,GAAgB,EAAE,CAAA;QAElD;;;;WAIG;QACwB,aAAQ,GAAqB,EAAE,CAAA;QAI9B,aAAQ,GAAG,CAAC,CAAC,CAAA;IA+xC3C,CAAC;aA/jEQ,WAAM,GAAG;QACd,eAAe;QACf,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmvBJ;KACA,AAtvBY,CAsvBZ;IAUD;;;;;OAKG;IACH,IAAY,WAAW;QACrB,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;IACzD,CAAC;IA0BD,+DAA+D;IAC/D,IAAY,MAAM;QAChB,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACpC,CAAC;IAED,MAAM;QACJ,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAA;QACxB,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YACzB,OAAO,IAAI,CAAA;UACP,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC;;gBAElB,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC;qBAC/B,OAAO,CAAC,CAAC,CAAC,mCAAmC,CAAC;;OAE5D,CAAA;QACH,CAAC;QAED,mDAAmD;QACnD,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAA;QAE5C;;;;;;UAME;QACF,OAAO,IAAI,CAAA;QACP,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;QAC1G,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC;QACpF,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC;KAC9B,CAAA;IACH,CAAC;IAED;;;;;;;;;OASG;IACK,UAAU,CAAC,IAAgB;QACjC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,YAAY,EAAE,MAAM;YAAE,OAAO,OAAO,CAAA;QAErD,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,IAAI,EAAE,CAAA;QAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAA;QAEzD,OAAO,IAAI,CAAA;;cAED,OAAO,CAAC,CAAC,CAAC,iCAAiC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,mCAAmC,CAAC;;;YAG9F,UAAkC,CAAC,GAAG,CACvC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAA;;;;6BAIM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;4BAC1B,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,EAAG,CAAC,CAAC,MAA2B,CAAC,OAAO,CAAC;;kBAEpF,OAAO,CAAC,CAAC,CAAC,oBAAoB,GAAG,GAAG,CAAC;;aAE1C,CACF;;UAED,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA,YAAY,OAAO,CAAC,CAAC,CAAC,mCAAmC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;;UAEnG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;YACtB,CAAC,CAAC,IAAI,CAAA;;yBAES,OAAO,CAAC,CAAC,CAAC,sBAAsB,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,+BAA+B,CAAC;;2BAE5E,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;gCACtC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC;4BAC7C,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAE,CAAC,CAAC,MAA2B,CAAC,KAAK,CAAC;;;;yBAItE,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC;kBAC9C,OAAO;gBACP,CAAC,CAAC,IAAI,CAAA,YAAY,OAAO,CAAC,CAAC,CAAC,kCAAkC,CAAC,MAAM;gBACrE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,UAAU,EAAE,QAAQ,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;;aAE3F;YACH,CAAC,CAAC,OAAO;;KAEd,CAAA;IACH,CAAC;IAED;;;;;OAKG;IACK,WAAW,CAAC,IAAgB;QAClC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;QAC5C,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;QACpD,MAAM,IAAI,GAAG,KAAK,EAAE,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAA;QACvD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QACzD,MAAM,MAAM,GAAG,KAAK;YAClB,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC;YACzG,CAAC,CAAC,SAAS,CAAA;QAEb,OAAO,IAAI,CAAA;;cAED,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,6BAA6B,CAAC;;;mBAGrE,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC;4BAC7B,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAE,CAAC,CAAC,MAA4B,CAAC,KAAK,CAAC;yCACtD,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,CAAC,CAAC,gCAAgC,CAAC;cACnG,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;YAC3D,CAAC,CAAC,IAAI,CAAA,iBAAiB,IAAI,CAAC,MAAM,aAAa,IAAI,CAAC,MAAM,WAAW;YACrE,CAAC,CAAC,OAAO;cACT,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAA,iBAAiB,IAAI,cAAc,IAAI,KAAK,IAAI,CAAC,MAAM,IAAI,IAAI,WAAW,CAAC;;;;;mBAK9F,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC;4BAC3B,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAG,CAAC,CAAC,MAA4B,CAAC,KAAK,CAAC;yCAC/D,CAAC,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC;cAC7E,WAAoC,CAAC,GAAG,CACzC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAA,iBAAiB,IAAI,cAAc,KAAK,EAAE,IAAI,KAAK,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC,0BAA0B,GAAG,IAAI,CAAC,WAAW,CAC/H;;;;UAIH,KAAK;YACL,CAAC,CAAC,IAAI,CAAA;;yBAES,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC;kCAC3B,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,EAAG,CAAC,CAAC,MAA4B,CAAC,KAAK,CAAC;oBAChG,OAAO,KAAK,SAAS;gBACrB,CAAC,CAAC,IAAI,CAAA,6BAA6B,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,WAAW;gBAC5F,CAAC,CAAC,OAAO;oBACT,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAA,iBAAiB,GAAG,CAAC,GAAG,cAAc,GAAG,CAAC,GAAG,KAAK,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,WAAW,CAAC;;;;;yBAKnH,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC;;oBAE1C,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CACtC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAC1D,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,KAAM,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,CACpG,CACF;;;;gBAIH,KAAK,CAAC,MAAM;gBACZ,CAAC,CAAC,IAAI,CAAA;;+BAES,OAAO,CAAC,CAAC,CAAC,4BAA4B,GAAG,IAAI,CAAC;;0BAEnD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CACjF,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,KAAM,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,KAAK,CAAC,MAAO,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,CAClG;0BACC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CACjF,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,KAAM,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,KAAK,CAAC,MAAO,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,CAClG;;;sBAGH,KAAK,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC;oBAC5C,CAAC,CAAC,IAAI,CAAA,WAAW,OAAO,CAAC,CAAC,CAAC,4CAA4C,CAAC,MAAM;oBAC9E,CAAC,CAAC,OAAO;mBACZ;gBACH,CAAC,CAAC,OAAO;;;kBAGP,MAAM;gBACN,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;gBACjF,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC;;aAEhD;YACH,CAAC,CAAC,OAAO;;KAEd,CAAA;IACH,CAAC;IAEO,SAAS,CAAC,IAAY;QAC5B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;YACjB,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAA;YAC1C,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,CAAE,IAAmB,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA;QACvE,CAAC,CAAC,CAAA;IACJ,CAAC;IAED;;;;;OAKG;IACH;;;;;;OAMG;IACK,kBAAkB;QACxB,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,OAAO,IAAI,CAAA;;gBAED,OAAO,CAAC,CAAC,CAAC,mCAAmC,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,CAAC;WAClF,CAAA;QACP,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,oBAAoB,IAAI,GAAG,CAAC,IAAI,KAAK,mBAAmB,CAAC,CAAA;QAC/G,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,OAAO,CAAA;QAErC,OAAO,IAAI,CAAA,GAAG,IAAI,CAAC,GAAG,CACpB,GAAG,CAAC,EAAE,CAAC,IAAI,CAAA,yBAAyB,GAAG,CAAC,QAAQ;mBACnC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM;mBAC/B,GAAG,CAAC,OAAO,QAAQ,GAAG,CAAC,GAAG;WAClC,CACN,EAAE,CAAA;IACL,CAAC;IAEO,UAAU,CAAC,KAAwB;QACzC,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAM;QAEvB,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAA;QACpF,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK;YAAE,OAAM;QAErC,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,aAAa,EAAE;YAC7B,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE;YAChD,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;SACf,CAAC,CACH,CAAA;IACH,CAAC;IAED,kDAAkD;IAC1C,cAAc;QACpB,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAM;QACvB,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAA;QACvD,IAAI,MAAM;YAAE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;IACrC,CAAC;IAEO,YAAY,CAAC,IAAgB,EAAE,KAAa;QAClD,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAM;QAEvB,wDAAwD;QACxD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QACzF,IAAI,CAAC,SAAS,CACZ,YAAY,CACV,IAAI,CAAC,KAAK,EACV,IAAI,EACJ,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAE,KAAmB,EAC/C,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CACtD,CACF,CAAA;IACH,CAAC;IAEO,YAAY,CAAC,IAAY,EAAE,GAAW;QAC5C,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,CAAA;QACtD,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAM;QAClC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAA;IAC5E,CAAC;IAEO,SAAS,CAAC,KAAkB;QAClC,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IAC3G,CAAC;IAED;;;;;;;;OAQG;IACK,UAAU,CAAC,IAAc,EAAE,EAAW;QAC5C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;YACjB,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,CAAA;YACxE,IAAI,EAAE;gBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAExB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvB,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAA;gBACpC,OAAO,IAAkB,CAAA;YAC3B,CAAC;YAED,gDAAgD;YAChD,MAAM,OAAO,GAAI,UAAkC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAA;YACtF,OAAO,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAA;QACxE,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,UAAU,CAAC,GAAW;QAC5B,MAAM,OAAO,GAAG,GAAG;aAChB,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;aACtB,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;QAEhC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;YACjB,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,KAAK,IAAI,CAAC,MAAkB,CAAC,EAAE,CAAA;YAC1F,qDAAqD;YACrD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;gBAAE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;;gBACzC,OAAO,IAAI,CAAC,OAAO,CAAA;YACxB,OAAO,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,IAA6C,EAAE,CAAA;QAC/E,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,WAAW,CAAC,KAAa;QAC/B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;YACjB,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,KAAK,IAAI,CAAC,MAAkB,CAAC,EAAE,CAAA;YAC1F,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;gBAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;;gBACtE,OAAO,IAAI,CAAC,QAAQ,CAAA;YACzB,OAAO,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,IAA6C,EAAE,CAAA;QAC/E,CAAC,CAAC,CAAA;IACJ,CAAC;IAED;;;;;;;;;;;;OAYG;IACK,YAAY,CAAC,OAAO,GAAG,KAAK;QAClC,MAAM,MAAM,GAAG,IAAI,CAAA;;mBAEJ,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC;;qBAE5B,IAAI,CAAC,UAAU;0BACV,OAAO,CAAC,CAAC,CAAC,iCAAiC,CAAC;sBAChD,CAAC,CAAQ,EAAE,EAAE,CACrB,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,eAAe,EAAE;YAC/B,MAAM,EAAE,EAAE,IAAI,EAAG,CAAC,CAAC,MAA2B,CAAC,KAAK,EAAE;YACtD,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;SACf,CAAC,CACH;;;;mBAII,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,qCAAqC,CAAC,CAAC,CAAC,CAAC,OAAO;YAClI,CAAC,IAAI,CAAC,WAAW;YACjB,CAAC,CAAC,IAAI,CAAA;yBACO,IAAI,CAAC,KAAK,EAAE,UAAU,IAAI,EAAE;8BACvB,OAAO,CAAC,CAAC,CAAC,qCAAqC,CAAC;0BACpD,CAAC,CAAQ,EAAE,EAAE,CACrB,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,oBAAoB,EAAE;gBACpC,MAAM,EAAE,EAAE,IAAI,EAAG,CAAC,CAAC,MAA2B,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE;gBAC3E,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,IAAI;aACf,CAAC,CACH;iBACF;YACL,CAAC,CAAC,IAAI,CAAA,qBAAqB,OAAO,CAAC,CAAC,CAAC,qCAAqC,CAAC;yCAC9C,IAAI,CAAC,KAAK,EAAE,UAAU,IAAI,EAAE;;gBAErD,IAAI,CAAC,QAAQ,CAAC,qCAAqC,CAAC,EAAE;;;;;;;;mBAQnD,OAAO,CAAC,CAAC,CAAC,+BAA+B,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,iCAAiC,CAAC;;qBAE7F,IAAI,CAAC,KAAK,EAAE,SAAS,IAAI,OAAO;sBAC/B,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAE,CAAC,CAAC,MAA4B,CAAC,KAAwB,CAAC;;8CAEjE,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,IAAI,OAAO,CAAC,KAAK,OAAO;gBAC5E,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC;;gDAET,IAAI,CAAC,KAAK,EAAE,SAAS,KAAK,SAAS;gBACnE,OAAO,CAAC,CAAC,CAAC,gCAAgC,CAAC;;+CAEZ,IAAI,CAAC,KAAK,EAAE,SAAS,KAAK,QAAQ;gBACjE,OAAO,CAAC,CAAC,CAAC,+BAA+B,CAAC;;;YAG9C,IAAI,CAAC,QAAQ,CAAC,iCAAiC,CAAC;;;;;;;;;mBASzC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,gCAAgC,CAAC;;cAE3F,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;cACvF,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;cACvF,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;;YAE3F,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;YACrB,CAAC,CAAC,IAAI,CAAA,sBAAsB,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,UAAU,OAAO,CAAC,CAAC,CAAC,gCAAgC,CAAC;+CACzE,OAAO,CAAC,CAAC,CAAC,iCAAiC,CAAC;wBACnE;YACZ,CAAC,CAAC,OAAO;YACT,IAAI,CAAC,kBAAkB,EAAE;YACzB,IAAI,CAAC,QAAQ,CAAC,gCAAgC,CAAC;;;;mBAIxC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,gCAAgC,CAAC;;qBAEpF,IAAI,CAAC,cAAc,IAAI,EAAE;0BACpB,OAAO,CAAC,CAAC,CAAC,kCAAkC,CAAC;sBACjD,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAG,CAAC,CAAC,MAA2B,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,SAAS,EAAE,CAAC;;YAEhH,IAAI,CAAC,QAAQ,CAAC,gCAAgC,CAAC;;;;mBAIxC,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,4BAA4B,CAAC;;qBAE5E,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;0BAC7B,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC;sBAC7C,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAE,CAAC,CAAC,MAA2B,CAAC,KAAK,CAAC;;YAE3E,IAAI,CAAC,QAAQ,CAAC,4BAA4B,CAAC;;KAElD,CAAA;QAED,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,IAAI,CAAA;;;;mBAIE,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;uBAC5B,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,KAAK,EAAE,UAAU,IAAI,EAAE;;cAExD,MAAM;;;OAGb,CAAA;QACH,CAAC;QAED,OAAO,IAAI,CAAA;;cAED,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;UACpC,MAAM;;KAEX,CAAA;IACH,CAAC;IAED;;;;;;OAMG;IACK,QAAQ,CAAC,GAAW;QAC1B,MAAM,IAAI,GAAG;YACX,GAAG,IAAI,GAAG,CACR,GAAG;iBACA,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;iBAChD,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CACjC;SACF,CAAA;QAED,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;IAC5B,CAAC;IAED,qDAAqD;IAC7C,WAAW,CAAC,KAA6C;QAC/D,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,gBAAgB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IACzG,CAAC;IAED;;;;;;;;;;;OAWG;IACK,YAAY,CAAC,SAA0B;QAC7C,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAM;QACvB,MAAM,KAAK,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,CAAA;QAC1C,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IAC3G,CAAC;IAEO,cAAc,CAAC,IAAgB;QACrC,OAAO,IAAI,CAAA;;cAED,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC;;mBAEzB,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,6CAA6C,CAAC;;qBAE7F,IAAI,CAAC,IAAI;sBACR,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,EAAG,CAAC,CAAC,MAA2B,CAAC,KAAK,EAAE,CAAC;;YAEhF,IAAI,CAAC,QAAQ,CAAC,6CAA6C,CAAC;;;mBAGrD,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC;4BACtB,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,eAAe,CAAE,CAAC,CAAC,MAA4B,CAAC,KAAsB,CAAC;cACxG,eAAe,CAAC,GAAG,CACnB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAA;gCACM,IAAI,cAAc,IAAI,KAAK,IAAI,CAAC,SAAS;oBACrD,OAAO,CAAC,CAAC,CAAC,yBAAyB,GAAG,IAAI,CAAC;;eAEhD,CACF;;;;KAIR,CAAA;IACH,CAAC;IAEO,eAAe,CAAC,IAAgB;QACtC,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAA;QACxB,MAAM,QAAQ,GAAG,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAA;QAEjC,OAAO,IAAI,CAAA;;cAED,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAAC;;;mBAG9B,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC;;cAE3C,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CACtC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CACxD,IAAI,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAClE,CACF;;;;;mBAKM,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAAC;;cAEvC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CACtC,IAAI,CAAC,MAAM,CACT,IAAI,CAAC,WAAW,EAAE,EAClB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EACZ,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,EAClE,CAAC,CACF,CACF;;;;;mBAKM,OAAO,CAAC,CAAC,CAAC,+BAA+B,CAAC;;cAE9C,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CACtC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAC3D,IAAI,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE,GAAG,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAChE,CACF;;;;;mBAKM,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,6BAA6B,CAAC;;;2BAGxE,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAAC;sBACxC,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC;uBACnC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC;;;;;2BAKzB,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAAC;sBACxC,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC;uBACnC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC;;;;;2BAKzB,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAAC;sBACxC,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC;uBACpC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC;;;;cAIpC,CAAC,GAAG,EAAE,GAAG,CAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YACjC,2CAA2C;YAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;YACxF,OAAO,IAAI,CAAA;;8BAEK,CAAC,IAAI;+BACJ,OAAO,CAAC,CAAC,CAAC,uBAAuB,GAAG,IAAI,CAAC;0BAC9C,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,kCAAkC,CAAC;2BACpF,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC;;6BAE5B,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,qBAAqB;;eAE3D,CAAA;QACH,CAAC,CAAC;;2BAEa,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC;sBACpC,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC;uBACtC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC;;;;;YAKtC,IAAI,CAAC,QAAQ,CAAC,6BAA6B,CAAC;;;KAGnD,CAAA;IACH,CAAC;IAED,mCAAmC;IAC3B,WAAW,CAAC,IAAgB;QAClC,MAAM,SAAS,GAAG,oBAAoB,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAC/D,MAAM,QAAQ,GAAG,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAC5D,IAAI,CAAC,SAAS,IAAI,CAAC,QAAQ;YAAE,OAAO,OAAO,CAAA;QAE3C,OAAO,IAAI,CAAA;;cAED,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC;UAC1C,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO;UAC/C,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO;UAChD,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO;;KAEnD,CAAA;IACH,CAAC;IAED;;;;;;OAMG;IACK,cAAc,CAAC,IAAgB;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,MAAM,CAAA;QACjC,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,IAAI,CAAC,CAAA;QAE9B,MAAM,OAAO,GAAG,CAAC,IAA6B,EAAE,EAAE,CAChD,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC,CAAA;QAEzD,OAAO,IAAI,CAAA;;iBAEE,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC;UAC7C,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;;;iBAGpE,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC;UAC5C,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,CAC9B,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAChF;;QAED,IAAI,GAAG,CAAC;YACR,CAAC,CAAC,IAAI,CAAA;;uBAES,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC;gBAC7C,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,IAAI,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;;WAE5G;YACH,CAAC,CAAC,OAAO;KACZ,CAAA;IACH,CAAC;IAED;;;;;;OAMG;IACH;;;;;;OAMG;IACK,eAAe,CAAC,IAAgB;QACtC,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,KAAK,KAAK,CAAA;QAEnC,OAAO,IAAI,CAAA;;iBAEE,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC;;+BAEtB,EAAE,WAAW,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;iBACnE,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC;qBAClC,OAAO,CAAC,CAAC,CAAC,6BAA6B,CAAC;;+BAE9B,CAAC,EAAE,WAAW,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;iBAChE,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC;qBACnC,OAAO,CAAC,CAAC,CAAC,+BAA+B,CAAC;;;;KAI1D,CAAA;IACH,CAAC;IAEO,cAAc,CAAC,IAAgB;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,IAAI,eAAe,CAAC,CAAC,CAAC,CAAA;QACnD,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QAC1C,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAEzC,OAAO,IAAI,CAAA;;iBAEE,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC;;YAEvC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;YACpB,MAAM,SAAS,GAAG,WAAW,CAAC,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAA;YAC5D,OAAO,IAAI,CAAA;gCACS,OAAO,KAAK,MAAM,WAAW,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;kBAC/E,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;qBACpB,MAAM;yBACF,OAAO,CAAC,CAAC,CAAC,yBAAyB,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;;aAEtE,CAAA;QACH,CAAC,CAAC;;;8BAGkB,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;qBACnC,OAAO,CAAC,CAAC,CAAC,kCAAkC,CAAC;;cAEpD,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAA;4BACb,OAAO,KAAK,MAAM,WAAW,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,IAAI,MAAM;aAC1F,CAAC;;;;KAIT,CAAA;IACH,CAAC;IAED;;;;;OAKG;IACK,UAAU,CAAC,QAAgB;QACjC,MAAM,MAAM,GAAa,EAAE,CAAA;QAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;YAClC,4BAA4B;YAC5B,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAA;YACzD,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QACpG,CAAC;QAED,OAAO,GAAG,CAAA;;0BAEY,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;;KAErC,CAAA;IACH,CAAC;IAED,wBAAwB;IAChB,cAAc,CAAC,KAAc;QACnC,MAAM,QAAQ,GAA2B;YACvC,iBAAiB,EAAE,SAAS;YAC5B,gBAAgB,EAAE,QAAQ;YAC1B,iBAAiB,EAAE,SAAS;YAC5B,cAAc,EAAE,MAAM;YACtB,eAAe,EAAE,OAAO;YACxB,iBAAiB,EAAE,SAAS;YAC5B,uBAAuB,EAAE,QAAQ;YACjC,wBAAwB,EAAE,SAAS;YACnC,qBAAqB,EAAE,MAAM;YAC7B,wBAAwB,EAAE,SAAS;SACpC,CAAA;QAED,OAAO,OAAO,CAAC,CAAC,CAAC,gCAAgC,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,YAAY,EAAE,CAAC,CAAA;IAC3F,CAAC;IAEO,QAAQ,CAAC,OAA2B,EAAE,MAAe;QAC3D,OAAO,OAAO,CAAC,GAAG,CAChB,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE;YACjB,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;YAC1C,OAAO,IAAI,CAAA;;;gBAGH,KAAK,KAAK,MAAM;uBACT,OAAO;kBACZ,OAAO;4BACG,KAAK;mBACd,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,CAAC;;OAE7C,CAAA;QACD,CAAC,CACF,CAAA;IACH,CAAC;IAEO,cAAc,CAAC,IAAgB;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAA;QACpC,MAAM,OAAO,GAAG,aAAa,EAA4B,CAAA;QAEzD;;;;;;UAME;QACF,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QACvC,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAA;QACjF,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAA;QAE5E,4BAA4B;QAC5B,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAA;QAE9B,OAAO,IAAI,CAAA;;cAED,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC;;;mBAGlC,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC;;cAE3C,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC;;YAExC,GAAG,CAAC,MAAM;YACV,CAAC,CAAC,IAAI,CAAA;+BACa,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC;;oBAElD,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC;;eAEvC;YACH,CAAC,CAAC,EAAE;;iBAEC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC;qBAC5F,OAAO,CAAC,CAAC,CAAC,uCAAuC,CAAC;;;;;mBAKpD,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;;sBAE7B,CAAC,CAAQ,EAAE,EAAE;YACrB,MAAM,KAAK,GAAI,CAAC,CAAC,MAA4B,CAAC,KAAK,CAAA;YACnD,IAAI,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,IAAI,SAAS,CAA+B,EAAE,CAAC,CAAA;QAClF,CAAC;;yCAE4B,CAAC,QAAQ,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC;cAC7E,gBAAgB,CAAC,GAAG,CACpB,MAAM,CAAC,EAAE,CAAC,IAAI,CAAA;gCACI,MAAM,cAAc,MAAM,KAAK,QAAQ,CAAC,MAAM;oBAC1D,OAAO,CAAC,CAAC,CAAC,sBAAsB,GAAG,MAAM,CAAC;;eAE/C,CACF;;;;;;;;uBAQU,QAAQ,CAAC,WAAW,IAAI,IAAI;sBAC7B,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,WAAW,EAAG,CAAC,CAAC,MAA2B,CAAC,OAAO,EAAE,CAAC;;YAEjG,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC;;;;;uBAK3B,CAAC,CAAC,QAAQ,CAAC,WAAW;sBACvB,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,WAAW,EAAG,CAAC,CAAC,MAA2B,CAAC,OAAO,EAAE,CAAC;;YAEjG,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC;;;;mBAI9B,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,gCAAgC,CAAC;;;;;;;;uBAQ5E,MAAM,CAAC,IAAI,EAAE,SAAS,IAAI,CAAC,CAAC;uBAC5B,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAE,CAAC,CAAC,MAA2B,CAAC,KAAK,CAAC,CAAC;;sBAE7E,CAAC,IAAI,EAAE,SAAS,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;;;;UAI7C,IAAI;YACJ,CAAC,CAAC,IAAI,CAAA;;yBAES,OAAO,CAAC,CAAC,CAAC,6BAA6B,CAAC;;;;;0BAKvC,CAAC,IAAI,CAAC,KAAK;4BACT,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC;sCAC3B,CAAC,QAAQ,CAAC,KAAK,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,iBAAiB,CAAC;6BAClF,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC;;oBAE5E,GAAG,CAAC,GAAG,CACP,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,IAAI,CAAA;;;8BAGd,KAAK,KAAK,IAAI,CAAC,KAAK;gCAClB,KAAK;0CACK,KAAK;iCACd,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;;qBAEpE,CACF;;8BAEW,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC;;;;;;6BAMpD,CAAC,CAAC,IAAI,CAAC,EAAE;4BACV,CAAC,CAAQ,EAAE,EAAE,CACrB,IAAI,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE,EAAG,CAAC,CAAC,MAA2B,CAAC,OAAO,EAAE,EAAE,CAAC;;kBAEzF,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC;;gBAEzC,IAAI,CAAC,IAAI,CAAC,qCAAqC,CAAC;aACnD;YACH,CAAC,CAAC,EAAE;;;KAGT,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;;;;;OAgBG;IACK,eAAe,CAAC,IAAgB;QACtC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,CAAA;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,IAAI,EAAE,GAAW,EAAE,KAAK,EAAE,CAAC,EAAE,CAAA;QAE7D,OAAO,IAAI,CAAA;;cAED,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,qBAAqB,GAAG,MAAM,GAAG,YAAY,CAAC;;YAElG,YAAY,CAAC,GAAG,CAChB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAA;0CACkB,IAAI,KAAK,MAAM,WAAW,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;qBAC/E,OAAO,CAAC,CAAC,CAAC,sBAAsB,GAAG,IAAI,CAAC;yBACpC,OAAO,CAAC,CAAC,CAAC,qBAAqB,GAAG,IAAI,GAAG,YAAY,CAAC;;aAElE,CACF;;UAED,MAAM,KAAK,OAAO;YAClB,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,IAAI,CAAA,WAAW,OAAO,CAAC,CAAC,CAAC,wCAAwC,CAAC,MAAM;;UAE1E,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;;UAExB,MAAM,KAAK,QAAQ;YACnB,CAAC,CAAC,IAAI,CAAA;;yBAES,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC;;4BAElC,CAAC,CAAQ,EAAE,EAAE,CACrB,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,IAAI,EAAG,CAAC,CAAC,MAA4B,CAAC,KAAa,EAAE,EAAE,CAAC;;oBAEvF,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAW,CAAC,GAAG,CAC9B,IAAI,CAAC,EAAE,CAAC,IAAI,CAAA,iBAAiB,IAAI,cAAc,IAAI,KAAK,MAAM,CAAC,IAAI,IAAI,IAAI,WAAW,CACvF;;;;yBAIM,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,oCAAoC,CAAC;kBACrG,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;kBAC5F,IAAI,CAAC,QAAQ,CAAC,oCAAoC,CAAC;;gBAErD,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC;aAC/B;YACH,CAAC,CAAC,OAAO;;KAEd,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACK,iBAAiB,CAAC,IAAgB;QACxC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;QACxB,IAAI,CAAC,KAAK;YAAE,OAAO,OAAO,CAAA;QAE1B,MAAM,IAAI,GAAG,EAAE,CAAC,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,CAAA;QAChE,MAAM,IAAI,GAAG,gBAAgB,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;QAC/D,IAAI,CAAC,IAAI;YAAE,OAAO,OAAO,CAAA;QAEzB,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,OAAO,CAAA;QAE7D,OAAO,IAAI,CAAA;;iBAEE,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC;;YAE3C,OAAO,CAAC,CAAC,CAAC,8BAA8B,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;YAChE,IAAI,CAAC,KAAK,IAAI,YAAY;YAC1B,CAAC,CAAC,IAAI,CAAA,SAAS,OAAO,CAAC,CAAC,CAAC,iCAAiC,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE;YACtF,CAAC,CAAC,EAAE;kBACE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,wCAAwC,CAAC,CAAC,CAAC,gCAAgC,CAAC;;;KAG3G,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH;;;;;;;;;;;OAWG;IACK,IAAI,CAAC,GAAW;QACtB,OAAO,IAAI,CAAA,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAA;IAC3D,CAAC;IAEO,UAAU,CAAC,GAAW;QAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAElC,OAAO,IAAI,CAAA;;;qBAGM,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC;wBAC3B,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;iBAC/B,GAAG,EAAE;YACZ,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACtD,IAAI,CAAC,aAAa,EAAE,CAAA;QACtB,CAAC;;mBAEU,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc;;KAE7C,CAAA;IACH,CAAC;IAEO,QAAQ,CAAC,GAAW;QAC1B,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA,WAAW,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAA;IAC7E,CAAC;IAEO,aAAa,CAAC,IAAgB;QACpC;;;;;UAKE;QACF,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK;YACrB,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;YACpE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAA;QACxB,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,IAAU,EAAE,EAAE,CAC1C,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,uBAAuB,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,uBAAuB,IAAI,EAAE,CAAC,KAAK,IAAI,GAAG,CAAA;QACpI,MAAM,SAAS,GAAG,CAAC,IAAU,EAAE,IAAiB,EAAE,EAAE;YAClD,MAAM,MAAM,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAA;YACzC,oDAAoD;YACpD,IAAI,IAAI;gBAAE,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;;gBACxB,OAAO,MAAM,CAAC,IAAI,CAAC,CAAA;YACxB,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAA;QACvE,CAAC,CAAA;QACD,MAAM,WAAW,GAAG,CAAC,IAAyB,EAAE,IAAU,EAAE,EAAE;YAC5D,IAAI,IAAI,KAAK,MAAM;gBAAE,OAAO,OAAO,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAA;YACxE,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK;gBAAE,OAAO,OAAO,CAAC,CAAC,CAAC,8BAA8B,IAAI,IAAI,IAAI,EAAE,CAAC,CAAA;YACpG,OAAO,OAAO,CAAC,CAAC,CAAC,8BAA8B,IAAI,EAAE,CAAC,CAAA;QACxD,CAAC,CAAA;QAED,OAAO,IAAI,CAAA;;;iBAGE,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAC;;YAEzF,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YACxC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,CAAA;YAChC,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;YAE3C;;;;;;cAME;YACF;;;;;;;cAOE;YACF,OAAO,IAAI,CAAA;;uBAEE,OAAO,CAAC,CAAC,CAAC,wBAAwB,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;;kBAErE,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;gBACxE,MAAM,QAAQ,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAA;gBACxD,MAAM,QAAQ,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,0BAA0B,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;gBAC3H,OAAO,IAAI,CAAA;;;4BAGD,QAAQ;qCACC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;8BAClC,QAAQ;+BACP,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;uBACjE,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC;mBAC3B,CAAA;YACH,CAAC,CAAC;;;2BAGS,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC;;oBAEhD,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAA;;;4BAGhE,IAAI,KAAK,IAAI;qCACJ,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;8BACvC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC;+BACjB,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC;uBACnC,OAAO,CAAC,CAAC,CAAC,8BAA8B,IAAI,EAAE,CAAC;mBACnD,CAAC;;;;WAIT,CAAA;QACD,CAAC,CAAC;;;KAGP,CAAA;IACH,CAAC;IAED;;;;;OAKG;IACK,MAAM,CAAC,KAAa,EAAE,KAAa,EAAE,GAA4B,EAAE,GAAY;QACrF,OAAO,IAAI,CAAA;;UAEL,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO;;;mBAGzC,MAAM,CAAC,KAAK,CAAC;gBAChB,GAAG,IAAI,OAAO;oBACV,CAAC,CAAQ,EAAE,EAAE;YACrB,MAAM,GAAG,GAAI,CAAC,CAAC,MAA2B,CAAC,KAAK,CAAA;YAChD,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;YAC1B,IAAI,GAAG,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3C,8BAA8B;gBAC9B,CAAC;gBAAC,CAAC,CAAC,MAA2B,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;gBACrD,OAAM;YACR,CAAC;YACD,GAAG,CAAC,MAAM,CAAC,CAAA;QACb,CAAC;;;KAGN,CAAA;IACH,CAAC;IAED;;;;;OAKG;IACK,eAAe,CAAC,SAAwB;QAC9C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;YACjB,MAAM,IAAI,GAAe,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,CAAA;YAC/C,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAAE,OAAO,IAAI,CAAC,QAAQ,CAAA;YACnE,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAAE,OAAO,IAAI,CAAC,KAAK,CAAA;YAC9D,IAAI,oBAAoB,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC5E,IAAI,CAAC,QAAQ,GAAG,eAAe,CAAC,CAAC,CAAC,CAAA;YACpC,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,GAAG,CAAC,KAA0B;QACpC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAA;IAC9C,CAAC;IAEO,YAAY,CAAC,KAA8B;QACjD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,KAAK,EAA6B,EAAE,CAAC,CAAC,CAAA;IAC3G,CAAC;IAED;;;;;;;;OAQG;IACK,WAAW,CAAC,SAAiB;QACnC,oEAAoE;QACpE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAA;QAE7G,IAAI,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAA;IACpF,CAAC;IAEO,WAAW,CAAC,KAA8B;QAChD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACnB,GAAG,IAAI;YACP,QAAQ,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,GAAG,KAAK,EAA4B;SAC3E,CAAC,CAAC,CAAA;IACL,CAAC;IAED;;;;;;OAMG;IACK,MAAM,CAAC,IAAsC;QACnD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAA;QACxB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;QACxB,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK;YAAE,OAAM;QAE3B,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAA;IACnE,CAAC;IAED,+CAA+C;IACvC,GAAG,CAAC,IAAY,EAAE,IAAY;QACpC,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,WAAW,EAAE;YAC3B,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE;YAClD,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;SACf,CAAC,CACH,CAAA;IACH,CAAC;IAEO,IAAI,CAAC,IAAe;QAC1B,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,aAAa,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAC1G,CAAA;IACH,CAAC;;AAr0C2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;iDAAc;AAKb;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;sDAAkB;AAYjB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;mDAAgB;AAEf;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;uDAAwB;AAExB;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;;mDAAsB;AAG/B;IAAhB,KAAK,EAAE;;+CAAmC;AAEf;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;8CAAoB;AAEpB;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;;8CAAwB;AAOvB;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;;iDAAgC;AAG9B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;wDAAyB;AACxB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;iDAAc;AAjyB9B,eAAe;IAD3B,aAAa,CAAC,kBAAkB,CAAC;GACrB,eAAe,CAgkE3B","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { css, html, LitElement, nothing, svg } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { live } from 'lit/directives/live.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\nimport {\n EXTRUDE_PRIMITIVES,\n MATERIAL_PRESETS,\n PRIMITIVE_KINDS,\n SEGMENTED_PRIMITIVES,\n SEGMENT_PRESETS,\n SIZING_RULES,\n FIGURE_PLACEMENTS,\n trianglesOf\n} from '@hatiolab/figure-model'\nimport { ANCHOR_RULES, JOINT_TYPES, PART_ROLES, REPEAT_LIMIT, anchorOfPart, repeatPlanOfPart } from '@hatiolab/figure-model'\nimport type {\n AnchorRule,\n Axis,\n ContractChange,\n FigurePart,\n FigurePlacement,\n JointType,\n MaterialPreset,\n PartRole,\n PrimitiveKind,\n Vec3\n} from '@hatiolab/figure-model'\nimport { activePalette } from '@hatiolab/things-scene'\n\nimport { partToFigure, partFromFigure } from './figure-source.js'\nimport type { FigureDraft, PartModel } from './figure-source.js'\nimport { canMirror } from './part-edits.js'\nimport { jointOf, parentChoices, patchJoint, setJointType } from './joint-edits.js'\nimport { baseFittingParts, baseOf, resizeBase } from './base-box.js'\nimport type { BaseSize } from './base-box.js'\n\n/** Axis choices for a joint. Written as a direction the author reads, stored as a vector. */\nconst JOINT_AXES: readonly { key: string; axis: Vec3 }[] = [\n { key: '+x', axis: { x: 1, y: 0, z: 0 } },\n { key: '-x', axis: { x: -1, y: 0, z: 0 } },\n { key: '+y', axis: { x: 0, y: 1, z: 0 } },\n { key: '-y', axis: { x: 0, y: -1, z: 0 } },\n { key: '+z', axis: { x: 0, y: 0, z: 1 } },\n { key: '-z', axis: { x: 0, y: 0, z: -1 } }\n]\n\nfunction axisKeyOf(axis: Vec3): string | undefined {\n return JOINT_AXES.find(one => one.axis.x === axis.x && one.axis.y === axis.y && one.axis.z === axis.z)?.key\n}\n\n/**\n * ๊ณ ๋ฅธ ๋ถ€ํ’ˆ์˜ ์†์„ฑ.\n *\n * ## ์—ฌ๊ธฐ๊ฐ€ ์‚ฌ์šฉ์ž ์šฉ์–ด๋กœ ๋ณด์—ฌ ์ฃผ๋Š” ์ž๋ฆฌ๋‹ค\n *\n * ๋ชจ๋ธ๋Ÿฌ ํŽ˜์ด์ง€๊ฐ€ ๊ฐ–๊ณ  ์žˆ๋Š” ๊ฒƒ์€ **์”ฌ ๋ชจ๋ธ**์ด๋‹ค โ€” ๊ธฐ์ค€ ์ƒ์ž ์œ„์— ๋ถ€ํ’ˆ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋†“์ธ ์ƒํƒœ.\n * ๊ทธ๋Ÿฐ๋ฐ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์”ฌ ์†์„ฑ ์ด๋ฆ„(`left`ยท`top`ยท`zPos`)์ด ์•„๋‹ˆ๋ผ\n * **XยทYยทZ** ๋‹ค. ๋‹ค๋ฅธ 3D ๋„๊ตฌ๊ฐ€ ๋ชจ๋‘ ๊ทธ๋ ‡๊ฒŒ ๋ถ€๋ฅด๊ณ , ์œ„์น˜๋„ ๋ถ€ํ’ˆ์˜ **์ค‘์‹ฌ**์œผ๋กœ ์ฝ๋Š”๋‹ค.\n *\n * ๊ทธ๋ž˜์„œ ์ด ํŒจ๋„์€ ๋ฐ›์€ ๋ถ€ํ’ˆ์„ FigureSource ํ˜•ํƒœ๋กœ **๋ณ€ํ™˜ํ•ด์„œ ๋ณด์—ฌ ์ฃผ๊ณ , ์ˆ˜์ •ํ•œ ๊ฒƒ์„\n * ๋‹ค์‹œ ์”ฌ ๋ชจ๋ธ๋กœ ๋˜๋Œ๋ ค ์•Œ๋ฆฐ๋‹ค.** ๋ณ€ํ™˜์€ `figure-source.ts` ๊ฐ€ ํ•œ๋‹ค โ€” ์—ฌ๊ธฐ์„œ ์ถ•์„ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜์ง€\n * ์•Š๋Š”๋‹ค.\n *\n * ## ์žˆ๋Š” ๊ฒƒ๋งŒ ๋ณด์—ฌ ์ค€๋‹ค\n *\n * ๋ถ„ํ•  ์ˆ˜๋Š” ๊ณก๋ฉด์ด ์žˆ๋Š” ๋„ํ˜•์—๋งŒ, ๋ชจ์„œ๋ฆฌ ๊ตด๋ฆผ์€ ๋‹จ๋ฉด์„ ๋ฝ‘๋Š” ๋„ํ˜•์—๋งŒ ๋œป์ด ์žˆ๋‹ค.\n * ๋œป ์—†๋Š” ์นธ์„ ํšŒ์ƒ‰์œผ๋กœ ๋Š˜์–ด๋†“์œผ๋ฉด ์ €์ž‘์ž๊ฐ€ ใ€Œ์™œ ์•ˆ ๋จน์ง€ใ€๋ฅผ ๊ณ ๋ฏผํ•˜๊ฒŒ ๋œ๋‹ค โ€”\n * ์•„์˜ˆ ๋‚ด์ง€ ์•Š๋Š”๋‹ค.\n *\n * ## ์ด๋ฆ„์€ ์ €์žฅ๋˜๋Š” ์‹๋ณ„์ž๋‹ค\n *\n * `FigurePart.name` ์€ ๋ฐ”์ธ๋”ฉยท์• ๋‹ˆ๋ฉ”์ด์…˜ยท์Šฌ๋กฏ์ด ๊ฐ€๋ฆฌํ‚ค๋Š” ์ด๋ฆ„์ด๋‹ค. ๊ณ ์น˜๋ฉด ๋ฐฐ์น˜๋œ\n * ์ธ์Šคํ„ด์Šค์˜ ๋ฐ”์ธ๋”ฉ์ด **์กฐ์šฉํžˆ** ๋Š๊ธด๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋ฆ„ ์นธ์—๋งŒ ๊ฒฝ๊ณ ๋ฅผ ๋ถ™์ธ๋‹ค.\n *\n * ## ใ€Œ์ƒํƒœ ์ƒ‰์ด ๋ถ™๋Š” ์ž๋ฆฌใ€๋ฅผ ๊ฑท์—ˆ๋‹ค\n *\n * `FigurePart.materialSlot`(๋‹น์‹œ ์ด๋ฆ„์€ `slot`) ์„ ๊ณ ๋ฅด๋Š” ์นธ์ด ์žˆ์—ˆ๋Š”๋ฐ **์•„๋ฌด ์ผ๋„ ํ•˜์ง€ ์•Š์•˜๋‹ค.** things-scene ์˜\n * figure ๋Ÿฐํƒ€์ž„์ด `slot` ์„ ์ฝ์ง€ ์•Š๋Š”๋‹ค โ€” ์„ ์–ธ ํ•œ ์ค„์ด ์ „๋ถ€๋‹ค. ๋˜๋Š” ์ค„ ์•Œ๊ณ  ๋งŒ๋“ค์—ˆ๊ณ ,\n * ํ™•์ธํ•˜์ง€ ์•Š์€ ๊ฒƒ์ด ์ž˜๋ชป์ด๋‹ค.\n *\n * ๊ทธ๋ฆฌ๊ณ  ๋˜๊ฒŒ ๋งŒ๋“ค๋”๋ผ๋„ ์ด ๋ชจ์–‘์ด ์•„๋‹ˆ๋‹ค. ์ƒํƒœ ์ƒ‰์€ ํŠน๋ณ„ํ•œ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ **์†์„ฑ ํ•˜๋‚˜**์ด๊ณ ,\n * ํˆดํŒยท๋ผ๋ฒจยทํ‘œ์‹œ ์—ฌ๋ถ€์™€ ๊ฐ™์€ ์ž๋ฆฌ์—์„œ ๋‹ค๋ค„์ ธ์•ผ ํ•œ๋‹ค. ๊ทธ ์„ค๊ณ„๊ฐ€ ์ •ํ•ด์ง€๋ฉด(figure-model#2)\n * ์ด ์ž๋ฆฌ์— **์†์„ฑ ์„ ์–ธ๊ณผ ๋ถ€ํ’ˆ ๋ฐ”์ธ๋”ฉ** ํŽธ์ง‘๊ธฐ๊ฐ€ ๋“ค์–ด์˜จ๋‹ค.\n *\n * ๊ทธ๋•Œ๊นŒ์ง€ ๋นˆ ์•ฝ์†์„ ๋‘์ง€ ์•Š๋Š”๋‹ค. ์•„๋ฌด ์ผ๋„ ์•ˆ ํ•˜๋Š” ์นธ์€ ์—†๋А๋‹ˆ๋งŒ ๋ชปํ•˜๋‹ค.\n *\n * ## ๊ณ ์น˜์ง€ ์•Š๋Š”๋‹ค\n *\n * ์ •๋ณธ ํ•œ ๋ฒŒ์€ ์ €์ž‘๋ฉด์ด ๊ฐ–๋Š”๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ๋ฐ”๋€ ๋ถ€ํ’ˆ์„ ์•Œ๋ฆด ๋ฟ์ด๋‹ค.\n */\n@customElement('figure-inspector')\nexport class FigureInspector extends localize(i18next)(LitElement) {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n min-height: 0;\n --figure-control-height: 30px;\n overflow-y: auto;\n background-color: var(--md-sys-color-surface-container-lowest);\n color: var(--md-sys-color-on-surface);\n font: var(--label-font, inherit);\n /*\n ์ด ํŒจ๋„์˜ ๋ณธ๋ฌธ ํฌ๊ธฐ๋ฅผ ์—ฌ๊ธฐ์„œ ํ•œ ๋ฒˆ ์ •ํ•œ๋‹ค.\n\n ์ „์—๋Š” ๊ทœ์น™๋งˆ๋‹ค ๋”ฐ๋กœ ์ ์—ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋น ๋œจ๋ฆฐ ๊ทœ์น™์ด ๋ณธ๋ฌธ ๊ธฐ๋ณธ ํฌ๊ธฐ(1rem)๋ฅผ\n ๋ฌผ๋ ค๋ฐ›์•„ ๊ทธ ์ค„๋งŒ ์ œ๋ชฉ์ฒ˜๋Ÿผ ์ปค์ง„๋‹ค. ์˜ค๋ฅ˜๊ฐ€ ์•„๋‹ˆ๋ผ์„œ ํ™”๋ฉด์„ ๋„์›Œ ๋ด์•ผ ์•ˆ๋‹ค.\n ์ด ํŒŒ์ผ์—์„œ๋งŒ ๋‘ ๋ฒˆ ๋‚ฌ๋‹ค.\n\n form ์š”์†Œ(input ยท select ยท button)๋Š” ๊ธ€๊ผด์„ ๋ฌผ๋ ค๋ฐ›์ง€ ์•Š์œผ๋ฏ€๋กœ ๊ฐ์ž ์ ์–ด์•ผ ํ•œ๋‹ค.\n ๊ทธ๊ฒƒ ๋ง๊ณ ๋Š” ์—ฌ๊ธฐ ๊ฐ’์„ ๋”ฐ๋ฅธ๋‹ค.\n */\n font-size: 0.76rem;\n }\n\n /*\n โ”€โ”€ ์ž๋ฆฌ๋ฅผ ์•„๋ผ๋Š” ํŒ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n ์†์„ฑ์€ ์•ž์œผ๋กœ ๋” ๋Š˜์–ด๋‚œ๋‹ค(๋Šฅ๋ ฅ ยท ํฌํŠธ ยท ์• ๋‹ˆ๋ฉ”์ด์…˜ ยท ๊ธฐ์ค€์ •๋ณด). ์ง€๊ธˆ ์—ฌ๋ฐฑ์„ ๊ทธ๋Œ€๋กœ ๋‘๋ฉด\n ๊ทธ๊ฒƒ๋“ค์ด ๋“ค์–ด์˜ฌ ์ž๋ฆฌ๊ฐ€ ์—†๋‹ค. ์ ˆ ์—ฌ๋ฐฑ์„ 6/10 ์œผ๋กœ, ์ œ๋ชฉ ์•„๋ž˜๋ฅผ 4px ๋กœ ์ค„์˜€๋‹ค โ€” ๊ธ€์ž ํฌ๊ธฐ์™€\n ์นธ ๋†’์ด๋Š” ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค(์ž‘๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ **๋นˆ ๊ณณ์„ ์ค„์ด๋Š” ๊ฒƒ**์ด๋‹ค).\n */\n section {\n padding: 8px 10px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n /* ์ž…๋ ฅ ํ–‰์€ ์ด˜์ด˜ํ•˜๊ฒŒ, ์„œ๋กœ ๋‹ค๋ฅธ ํŽธ์ง‘ ์˜๋„ ์‚ฌ์ด์—๋Š” ํ˜ธํก์„ ๋‘”๋‹ค. */\n section + section {\n margin-top: 6px;\n }\n section[collapsible] {\n padding: 0;\n }\n details[group] > summary {\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 34px;\n padding: 0 10px;\n cursor: pointer;\n list-style: none;\n }\n details[group] > summary::-webkit-details-marker {\n display: none;\n }\n details[group] > summary h3 {\n margin: 0;\n }\n details[group] > summary md-icon {\n --md-icon-size: 16px;\n color: var(--md-sys-color-on-surface-variant);\n }\n details[group] > div[group-content] {\n padding: 4px 10px 8px;\n border-top: 1px solid var(--md-sys-color-outline-variant);\n }\n h3 {\n display: flex;\n align-items: center;\n gap: 4px;\n margin: 0 0 4px 0;\n font-size: var(--ui-t-micro, 11px);\n font-weight: 700;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /* ์ž์‚ฐ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋Š” ๋ถ€ํ’ˆ์„ ๊ณ ์นœ๋‹ค๋Š” ํ˜„์žฌ ๋ฌธ๋งฅ์—์„œ๋Š” ์š”์•ฝ์œผ๋กœ๋งŒ ๋‘”๋‹ค. */\n details[asset] {\n margin: -1px 0;\n }\n details[asset] summary {\n display: flex;\n align-items: center;\n gap: 6px;\n min-height: 26px;\n cursor: pointer;\n list-style: none;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n details[asset] summary::-webkit-details-marker {\n display: none;\n }\n details[asset] summary::before {\n content: 'โ€บ';\n font-size: 1.1rem;\n line-height: 1;\n transition: transform 120ms ease;\n }\n details[asset][open] summary::before {\n transform: rotate(90deg);\n }\n details[asset] summary b {\n font-size: var(--ui-t-micro, 11px);\n letter-spacing: 0.04em;\n }\n details[asset] summary small {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 0.7rem;\n }\n\n label {\n display: flex;\n align-items: center;\n gap: 3px;\n margin-bottom: 2px;\n font-size: 0.68rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /*\n ๋„์›€๋ง ๋ฌผ์Œํ‘œ. **๊ธ€์ž ์ค„์„ ํ•˜๋‚˜ ๋จน์ง€ ์•Š๋Š”๋‹ค** โ€” ๋ผ๋ฒจยท์ œ๋ชฉ ์ค„์˜ ๋‚จ๋Š” ํญ์— ์–นํžŒ๋‹ค.\n ์•„์ด์ฝ˜๋งŒ ๋‘๊ณ  ํ…Œ๋‘๋ฆฌ๋ฅผ ์•ˆ ๋‘๋Š” ์ด์œ ๋Š” ์ด๊ฒƒ์ด ๋ˆ„๋ฅผ ๊ฒƒ์ด๋ผ๊ธฐ๋ณด๋‹ค ใ€Œ๋” ์žˆ๋‹คใ€๋Š” ํ‘œ์‹œ๋ผ์„œ๋‹ค.\n */\n button[help] {\n display: inline-flex;\n align-items: center;\n padding: 0;\n margin: 0;\n color: var(--md-sys-color-outline);\n background: none;\n border: none;\n cursor: pointer;\n }\n button[help] md-icon {\n --md-icon-size: 13px;\n font-size: 13px;\n }\n button[help]:hover,\n button[help][aria-expanded='true'] {\n color: var(--md-sys-color-primary);\n }\n\n /* ํŽธ ๋„์›€๋ง. ๋ผ๋ฒจ ์•„๋ž˜ ํ•œ ์นธ ๋“ค์—ฌ ๋ถ™์ธ๋‹ค โ€” ๋ฌด์—‡์— ๋”ธ๋ฆฐ ๋ง์ธ์ง€ ๋ณด์ด๊ฒŒ. */\n p[hint] {\n margin: 2px 0 4px 0;\n padding-left: 6px;\n font-size: 0.68rem;\n line-height: 1.5;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n border-left: 2px solid var(--md-sys-color-outline-variant);\n }\n\n input,\n select {\n width: 100%;\n min-height: var(--figure-control-height);\n box-sizing: border-box;\n padding: 4px 7px;\n font: var(--input-field-font, inherit);\n font-size: 0.76rem;\n color: var(--md-sys-color-on-surface);\n background-color: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n }\n input:focus,\n select:focus {\n outline: 2px solid var(--md-sys-color-primary);\n outline-offset: -1px;\n }\n\n /*\n ์ˆซ์ž ์นธ โ€” ๋ผ๋ฒจ์„ ์นธ **์•ˆ** ์™ผ์ชฝ์— ๋‘”๋‹ค.\n\n ๋ฒกํ„ฐ ์ €์ž‘๋„๊ตฌ(SketchยทFigma)๊ฐ€ XยทYยทWยทH ๋ฅผ ์ด๋ ‡๊ฒŒ ๋‘”๋‹ค. ๋ผ๋ฒจ์„ ์œ„์— ์–น์œผ๋ฉด ์ค„๋งˆ๋‹ค\n ๋‘ ์ค„์„ ๋จน์–ด์„œ, ์ž๋ฆฌยทํฌ๊ธฐยทํšŒ์ „ ์•„ํ™‰ ์นธ์ด ํ™”๋ฉด ์ ˆ๋ฐ˜์„ ์ฐจ์ง€ํ•œ๋‹ค. ์•ˆ์— ๋‘๋ฉด ํ•œ ์ค„์—\n ์…‹์ด ๋“ค์–ด๊ฐ€๊ณ  ๋ฌด์—‡์ด ๋ฌด์—‡์ธ์ง€๋„ ๋ถ™์–ด ์ฝํžŒ๋‹ค.\n */\n div[cell] {\n display: flex;\n box-sizing: border-box;\n height: var(--figure-control-height);\n min-height: var(--figure-control-height);\n align-items: center;\n gap: 2px;\n padding-left: 6px;\n background-color: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n }\n div[cell]:focus-within {\n outline: 2px solid var(--md-sys-color-primary);\n outline-offset: -1px;\n border-color: transparent;\n }\n div[cell] span[axis] {\n flex: none;\n font-size: 0.64rem;\n letter-spacing: 0.02em;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n div[cell] input {\n min-width: 0;\n min-height: 0;\n height: calc(var(--figure-control-height) - 2px);\n padding: 4px 6px 4px 2px;\n font-family: var(--mono-font, monospace);\n text-align: right;\n background: none;\n border: none;\n border-radius: 0;\n }\n div[cell] input:focus {\n outline: none;\n }\n\n /* ์ถ• ์…‹์„ ํ•œ ์ค„์— โ€” ์ขŒํ‘œ๋Š” ์…‹์ด ๊ฐ™์ด ์ฝํ˜€์•ผ ํ•œ๋‹ค */\n div[triple] {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 4px;\n }\n /*\n ๊ฐ’์ด ๋‘˜์ธ ์ค„์€ ์…‹์œผ๋กœ ๋‚˜๋ˆ„์ง€ ์•Š๋Š”๋‹ค. ๊ฐ€๋™ ๋ฒ”์œ„๋ฅผ ์„ธ ์นธ์งœ๋ฆฌ ์ค„์— ๋„ฃ์—ˆ๋”๋‹ˆ ์นธ์ด ํญ์˜ 1/3 ์ด๋ผ\n ใ€Œ์ตœ์†Œใ€๋ผ๋Š” ๋ง๊ณผ -120 ์ด ํ•œ ์นธ์— ๋ชป ๋“ค์–ด๊ฐ€ ์ˆซ์ž๊ฐ€ ์ž˜๋ ธ๋‹ค.\n */\n div[double] {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 4px;\n }\n /* ์นธ ์•„๋ž˜์— ๋ถ™๋Š” ํ•œ ์ค„์งœ๋ฆฌ ํ–‰๋™. ์นธ๊ณผ ๊ฐ™์€ ํญ์œผ๋กœ ๋‘ฌ์•ผ ํ•œ ๋ฌถ์Œ์œผ๋กœ ์ฝํžŒ๋‹ค. */\n button[fit] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n width: 100%;\n margin-top: 4px;\n padding: 3px 8px;\n font: inherit;\n font-size: 0.72rem;\n color: var(--md-sys-color-on-surface);\n background-color: var(--md-sys-color-surface-container);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n /* ๊ณ ์นœ ์นธ ๋ฐ”๋กœ ์•„๋ž˜์— ๋ถ™๋Š” ๋ง. ๋ง‰๋Š” ๊ฒƒ์€ ์˜ค๋ฅ˜ ์ƒ‰, ์•Œ๋ฆฌ๋Š” ๊ฒƒ์€ ์กฐ์šฉํ•œ ์ƒ‰. */\n p[contract] {\n display: flex;\n gap: 4px;\n margin: 4px 0 0;\n font-size: 0.68rem;\n line-height: 1.4;\n color: var(--md-sys-color-on-surface-variant);\n }\n p[contract][blocking] {\n color: var(--md-sys-color-error);\n }\n p[contract] md-icon {\n --md-icon-size: 14px;\n flex: none;\n }\n\n button[fit]:hover {\n background-color: var(--md-sys-color-surface-container-high);\n }\n button[fit] md-icon {\n --md-icon-size: 15px;\n }\n div[field] + div[field],\n div[triple] + div[field],\n div[field] + div[triple],\n div[double] + div[field],\n div[field] + div[double],\n div[inline-field] + div[inline-field],\n div[inline-field] + div[field],\n div[field] + div[inline-field],\n div[vector-row] + div[vector-row],\n div[vector-row] + div[field],\n div[field] + div[vector-row] {\n /* ์นธ ์‚ฌ์ด 7 โ†’ 5. ์นธ ์ž์ฒด๋Š” ๊ทธ๋Œ€๋กœ ๋‘๊ณ  ์‚ฌ์ด๋งŒ ์ขํžŒ๋‹ค. */\n margin-top: 5px;\n }\n\n /* ์งง์€ ๋ผ๋ฒจ๊ณผ ๋‹จ์ผ ๊ฐ’์€ ๊ฐ™์€ ์ค„์—์„œ ์ฝ๋Š”๋‹ค. ๋ณต์žกํ•œ ์„ ํƒ๊ธฐ์—๋Š” ์“ฐ์ง€ ์•Š๋Š”๋‹ค. */\n div[inline-field] {\n display: grid;\n /* ๊ฐ™์€ ํŽธ์ง‘ ๋ฐ€๋„ ์•ˆ์—์„œ๋Š” ์ž…๋ ฅ ์‹œ์ž‘์„ ์„ ๋งž์ถ˜๋‹ค. ๋ผ๋ฒจ ๊ธธ์ด๊ฐ€ ์นธ ํญ์„ ํ”๋“ค๋ฉด ์•ˆ ๋œ๋‹ค. */\n grid-template-columns: 64px minmax(0, 1fr);\n align-items: center;\n gap: 7px;\n }\n div[inline-field] > label {\n margin: 0;\n white-space: nowrap;\n }\n /* ํ•œ ์ค„ ์ž…๋ ฅ์˜ ์„ค๋ช…์€ ์ž…๋ ฅ์นธ์„ ๋ฐ€์–ด๋‚ด์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ์•„๋ž˜ ์ „ํญ์—์„œ ์ฝ๋Š”๋‹ค. */\n div[inline-field] > p[hint] {\n grid-column: 1 / -1;\n margin: -2px 0 1px;\n }\n div[inline-field] > code[fixed] {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n /* XยทYยทZ๋Š” ํ•จ๊ป˜ ๋น„๊ตํ•˜๋Š” ๊ฐ’์ด๋ฏ€๋กœ, ๋ฌถ์Œ ์ œ๋ชฉ๋งŒ ์™ผ์ชฝ์— ๋‘๊ณ  ์ž…๋ ฅ์€ ํ•œ ํ–‰์— ๋‘”๋‹ค. */\n div[vector-row] {\n display: grid;\n grid-template-columns: 64px minmax(0, 1fr);\n align-items: center;\n gap: 7px;\n }\n div[vector-row] > label {\n margin: 0;\n white-space: nowrap;\n }\n div[vector-row] > p[hint] {\n grid-column: 1 / -1;\n margin: -2px 0 1px;\n }\n div[sizing-choices] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 5px;\n }\n button[sizing-choice] {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 2px;\n min-height: 52px;\n padding: 7px 8px;\n color: var(--md-sys-color-on-surface);\n background: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 7px;\n text-align: left;\n cursor: pointer;\n }\n button[sizing-choice][on] {\n color: var(--md-sys-color-on-primary-container);\n background: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n button[sizing-choice] b {\n font-size: 0.74rem;\n }\n button[sizing-choice] small {\n font-size: 0.64rem;\n line-height: 1.35;\n opacity: 0.8;\n }\n div[anchor-rows] {\n display: grid;\n gap: 6px;\n }\n div[anchor-row] {\n display: grid;\n grid-template-columns: 46px minmax(0, 1fr);\n align-items: start;\n gap: 8px;\n padding: 6px 7px;\n background: var(--md-sys-color-surface-container);\n border-radius: 7px;\n }\n div[anchor-row] label {\n margin: 0;\n font-size: 0.7rem;\n font-weight: 700;\n }\n div[anchor-options] {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 4px;\n }\n button[anchor-choice] {\n min-width: 0;\n height: var(--figure-control-height);\n box-sizing: border-box;\n padding: 4px 3px;\n overflow: hidden;\n color: var(--md-sys-color-on-surface);\n font: var(--label-font, inherit);\n font-size: 0.63rem;\n line-height: 1.2;\n text-overflow: ellipsis;\n white-space: nowrap;\n background: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 5px;\n cursor: pointer;\n }\n button[anchor-choice][on] {\n color: var(--md-sys-color-on-primary-container);\n background: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n details[anchor-advanced] {\n grid-column: 2;\n margin-top: 4px;\n }\n details[anchor-advanced] summary {\n cursor: pointer;\n font-size: 0.62rem;\n color: var(--md-sys-color-on-surface-variant);\n }\n details[anchor-advanced] div[anchor-options] {\n margin-top: 4px;\n }\n div[palette-meaning] {\n display: grid;\n gap: 2px;\n margin-top: 7px;\n padding: 6px 8px;\n color: var(--md-sys-color-on-surface);\n background: var(--md-sys-color-surface-container);\n border-radius: 7px;\n }\n div[palette-meaning] b {\n font-size: 0.72rem;\n }\n div[palette-meaning] small {\n color: var(--md-sys-color-on-surface-variant);\n font-size: 0.64rem;\n line-height: 1.35;\n }\n\n /*\n ์ •๋ฐ€ ์ œ์ž‘ ๋„๊ตฌ.\n\n ๋„๋ฉด ํŽธ์ง‘๊ธฐ๋Š” ์ž์‚ฐ์„ ๋ฐฐ์น˜ํ•˜๋Š” ๊ณณ์ด๋ผ ๋Œ€์ถฉ ๋†“์•„๋„ ๋˜์ง€๋งŒ, ์—ฌ๊ธฐ๋Š” ์ž์‚ฐ์„ ๋งŒ๋“œ๋Š”\n ๊ณณ์ด๋‹ค. ใ€Œ๋ชธํ†ต ํ•œ๊ฐ€์šด๋ฐใ€ยทใ€Œ๋ฐ”๋‹ฅ์— ๋ถ™์ด๊ธฐใ€ยทใ€Œ๋ฐ˜๋Œ€์ชฝ์—๋„ ํ•˜๋‚˜ใ€๋ฅผ ์†์œผ๋กœ ๊ณ„์‚ฐํ•˜๋ฉด\n ๋Š˜ ์กฐ๊ธˆ์”ฉ ์–ด๊ธ‹๋‚˜๊ณ , ๊ธฐ์ค€ ์น˜์ˆ˜๋ฅผ ๋ฐ”๊พธ๋ฉด ์ „๋ถ€ ๋‹ค์‹œ ํ•ด์•ผ ํ•œ๋‹ค.\n */\n div[tools] {\n display: grid;\n grid-template-columns: repeat(6, minmax(0, 1fr));\n gap: 4px;\n }\n div[tools] button {\n display: grid;\n place-items: center;\n min-width: 0;\n height: var(--figure-control-height);\n box-sizing: border-box;\n padding: 0;\n font: var(--label-font, inherit);\n font-size: 0.7rem;\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n div[tools] button md-icon {\n font-size: 17px;\n }\n div[tools] button[disabled] {\n opacity: 0.35;\n cursor: default;\n }\n div[tools] button:hover:not([disabled]) {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n\n /* ์ง€๊ธˆ ์–ด๋А ์ถ•์ด ๋Š˜์–ด๋‚˜๋‚˜ โ€” ํฌ๊ธฐ๋ฅผ ๊ณ ์น˜๋ฉด ๋ฐ”๋€” ์ˆ˜ ์žˆ์–ด์„œ ๊ฐ’์œผ๋กœ ์ ๋Š”๋‹ค */\n p[axis-now] {\n margin: 4px 0 0 0;\n font-size: 0.7rem;\n color: var(--md-sys-color-primary);\n }\n /* ์ด ์„ ํƒ์ด ๋ฌด์—‡์„ ๋ฌด๋Š”์ง€ โ€” ์„ฑ์ˆ™๋„์˜ ๋ฌถ์Œ ์ˆ˜์— ๊ทธ๋Œ€๋กœ ์žกํžŒ๋‹ค */\n p[cost] {\n margin: 4px 0 0 0;\n font-size: 0.68rem;\n line-height: 1.5;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /* ์ด๋ฆ„์„ ๋ฐ”๊พธ๋ฉด ๋ฌด์—‡์ด ๋Š๊ธฐ๋Š”์ง€ ๋งํ•œ๋‹ค */\n p[warn] {\n margin: 4px 0 0 0;\n font-size: 0.68rem;\n line-height: 1.5;\n color: var(--md-sys-color-tertiary);\n }\n\n /* ๋ถ„ํ•  ์ˆ˜ ํ”„๋ฆฌ์…‹ โ€” ์ž์œ  ์ž…๋ ฅ๋ณด๋‹ค ์ด ์…‹์„ ๊ถŒํ•œ๋‹ค */\n div[presets] {\n display: flex;\n gap: 4px;\n margin-top: 4px;\n }\n div[presets] button {\n flex: 1;\n padding: 3px 0;\n font: var(--label-font, inherit);\n font-size: 0.72rem;\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n div[presets] button[on] {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n\n /*\n ๋ถ„ํ•  ์ˆ˜ ์„ ํƒ โ€” ๋ชจ์–‘๊ณผ ์‚ผ๊ฐํ˜• ์ˆ˜๋ฅผ **ํ•จ๊ป˜** ๋ณด์—ฌ ์ค€๋‹ค.\n\n ์ˆซ์ž๋งŒ ๋Š˜์–ด๋†“์œผ๋ฉด 8 ๊ณผ 16 ์ด ๋ฌด์—‡์ด ๋‹ค๋ฅธ์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค. ๋กœ์šฐํด๋ฆฌ์—์„œ ์ด ์„ ํƒ์ด\n ๊ณง ใ€Œ๋ช‡ ๊ฐœ๊นŒ์ง€ ํŽธํ•˜๊ฒŒ ๋†“์„ ์ˆ˜ ์žˆ๋‚˜ใ€๋ฅผ ์ •ํ•˜๋ฏ€๋กœ, ๊ฐ์ง€๋Š” ์ •๋„์™€ ๊ทธ ๊ฐ’์ด ๋ฌด๋Š”\n ์‚ผ๊ฐํ˜• ์ˆ˜๋ฅผ ํ•œ์ž๋ฆฌ์—์„œ ๋ณด์•„์•ผ ํ•œ๋‹ค.\n\n ์‹ค๋ฃจ์—ฃ์€ ์ง€์–ด๋‚ธ ๊ทธ๋ฆผ์ด ์•„๋‹ˆ๋‹ค โ€” ๊ณก๋ฉด ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ๋ฅผ ์œ„์—์„œ ๋ณธ ์œค๊ณฝ์ด ์ •ํ™•ํžˆ\n ์ •n๊ฐํ˜•์ด๋‹ค. ์‚ผ๊ฐํ˜• ์ˆ˜๋Š” ํ™”๋ฉด์ด ์…ˆํ•˜์ง€ ์•Š๊ณ  figure-model ์˜ trianglesOf ๊ฐ€ ๋‚ธ๋‹ค.\n */\n div[segments] {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 4px;\n }\n /* ์› ์œ ์ง€ ยท ๋„๊ธฐ โ€” ๊ณ ๋ฅด๋Š” ๊ฐ’์ด๋ผ ๋ถ„ํ•  ์ˆ˜์™€ ๊ฐ™์€ ๋ชจ์–‘์œผ๋กœ ๋‘”๋‹ค */\n div[choices] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 4px;\n }\n button[choice] {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 1px;\n padding: 6px 8px;\n text-align: left;\n font: var(--label-font, inherit);\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n button[choice]:hover:not([on]) {\n background-color: var(--md-sys-color-surface-container);\n }\n button[choice][on] {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n button[choice] small {\n opacity: 0.75;\n }\n button[seg] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1px;\n padding: 6px 2px 4px 2px;\n font: var(--label-font, inherit);\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n button[seg]:hover:not([on]) {\n background-color: var(--md-sys-color-surface-container);\n }\n button[seg][on] {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n button[seg] svg {\n display: block;\n /* ์ž‘์œผ๋ฉด 12 ์™€ 16 ์ด ๋‘˜ ๋‹ค ๋™๊ทธ๋ผ๋ฏธ๋กœ ๋ณด์ธ๋‹ค โ€” ๊ฐ์ด ์ฝํž ๋งŒํผ์€ ํ‚ค์šด๋‹ค */\n width: 32px;\n height: 32px;\n }\n button[seg] svg polygon {\n fill: var(--md-sys-color-surface-container-highest);\n stroke: currentColor;\n stroke-width: 1.1;\n stroke-linejoin: miter;\n }\n button[seg][on] svg polygon {\n fill: var(--md-sys-color-surface-container-lowest);\n }\n button[seg] b {\n font-size: 0.8rem;\n font-weight: 700;\n line-height: 1.1;\n }\n button[seg] small {\n font-size: 0.62rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n button[seg][on] small {\n color: inherit;\n }\n /* ์„ฑ๋Šฅยท์‹ค๋ฃจ์—ฃ ๊ฒ€์ฆ์„ ๋งˆ์นœ ํ”„๋ฆฌ์…‹๋งŒ ๊ณ ๋ฅธ๋‹ค. */\n details[free] {\n margin-top: 6px;\n }\n details[free] summary {\n font-size: 0.68rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n cursor: pointer;\n }\n details[free] div[cell] {\n margin-top: 4px;\n }\n\n /*\n ์ƒ‰ ๊ฒฌ๋ณธ.\n\n ํ† ํฐ์„ ๊ธ€์ž๋กœ ๋ฐ›์ง€ ์•Š๋Š”๋‹ค. things-scene ์˜ ํŒ”๋ ˆํŠธ ์„ ์–ธ์ด ใ€Œ์—ฌ๊ธฐ ๋“  ์ด๋ฆ„์ด ์ €์ž‘์—์„œ\n ๊ณ ๋ฅผ ์ˆ˜ ์žˆ๋Š” ์ „๋ถ€์ด๊ณ , ์ž์œ ์ƒ‰์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ๊ฐ๊ฐ์ ์ธ ๋กœ์šฐํด๋ฆฌ์˜ ์ฒซ ๊ทœ์น™ใ€\n ์ด๋ผ๊ณ  ๋ชป๋ฐ•๊ณ  ์žˆ๋‹ค. ๊ธ€์ž ์นธ์œผ๋กœ ๋‘๋ฉด ๊ทธ ๊ทœ์น™์ด ํ™”๋ฉด์—์„œ ์‚ฌ๋ผ์ง€๊ณ , ์˜คํƒ€ ํ•˜๋‚˜๋กœ\n resolveToken ์ด ๋˜์ง„๋‹ค.\n */\n div[swatches] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n /*\n ๋‘ ๋ฌด๋ฆฌ์˜ ๊ฒฝ๊ณ„. ใ€Œ์น ํ•œ ์ƒ‰ใ€๊ณผ ใ€Œ์ผœ์ง„ ์ƒ‰ใ€์ด ํ•œ ์ค„์— ์„ž์ด๋ฉด accent(์ฃผํ™ฉ)์™€\n status-warning(์ฃผํ™ฉ)์ด ๋‚˜๋ž€ํžˆ ๋†“์—ฌ ๋ฌด์—‡์ด ๋ฌด์—‡์ธ์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค.\n */\n label[group] {\n margin-top: 8px;\n padding-top: 8px;\n font-size: var(--ui-t-micro, 11px);\n letter-spacing: 0.03em;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n border-top: 1px solid var(--md-sys-color-outline-variant);\n }\n\n /* ๊ฐ’์ด ์˜†์— ๋ถ™์–ด์•ผ ๋Œ๋ฉด์„œ ์–ผ๋งˆ์ธ์ง€ ์•ˆ๋‹ค */\n div[slider] {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n div[slider] input[type='range'] {\n flex: 1;\n accent-color: var(--md-sys-color-primary);\n cursor: pointer;\n }\n div[slider] output {\n flex: none;\n width: 2.6em;\n text-align: right;\n font: var(--mono-font, ui-monospace, monospace);\n font-size: 0.72rem;\n color: var(--md-sys-color-on-surface-variant);\n }\n button[swatch] {\n width: 26px;\n height: 26px;\n padding: 0;\n background-color: var(--swatch);\n border: 1px solid rgba(0, 0, 0, 0.16);\n border-radius: 50%;\n cursor: pointer;\n }\n button[swatch][on] {\n /* ๊ณ ๋ฅธ ๊ฒƒ์€ ํ…Œ๋‘๋ฆฌ๊ฐ€ ์•„๋‹ˆ๋ผ ๊ณ ๋ฆฌ๋กœ ํ‘œ์‹œํ•œ๋‹ค โ€” ์ƒ‰ ์ž์ฒด๋ฅผ ๊ฐ€๋ฆฌ์ง€ ์•Š์œผ๋ ค๊ณ  */\n box-shadow:\n 0 0 0 2px var(--md-sys-color-surface-container-lowest),\n 0 0 0 4px var(--md-sys-color-primary);\n }\n span[token] {\n display: block;\n margin-top: 6px;\n font-family: var(--mono-font, monospace);\n font-size: 0.68rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n label[toggle] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 7px 0 0 0;\n font-size: 0.74rem;\n color: var(--md-sys-color-on-surface);\n cursor: pointer;\n }\n label[toggle] input {\n width: auto;\n }\n div[role-choices] {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 4px;\n }\n div[role-choices] label[toggle] {\n justify-content: center;\n min-height: 30px;\n margin: 0;\n padding: 2px 4px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n font-size: 0.68rem;\n text-align: center;\n }\n div[role-choices] label[toggle]:has(input:checked) {\n color: var(--md-sys-color-on-primary-container);\n background: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n\n p[quiet] {\n margin: 0;\n font-size: 0.76rem;\n line-height: 1.6;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /*\n ๊ณ ์น  ์ˆ˜ ์—†๋Š” ๊ฐ’ โ€” ์ž…๋ ฅ์นธ์ฒ˜๋Ÿผ ๋ณด์ด์ง€ ์•Š๊ฒŒ ํ•œ๋‹ค.\n\n ์ „์—๋Š” ๊ทธ๋ƒฅ ๊ธ€์ž์˜€๊ณ , ์˜†์˜ ์ด๋ฆ„ ์นธ๊ณผ ๋‚˜๋ž€ํžˆ ์žˆ์œผ๋‹ˆ ๋ˆŒ๋Ÿฌ๋„ ๋˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์˜€๋‹ค. ์ž๋ฌผ์‡ ์™€\n ์นธ ์—†๋Š” ๋ฐ”ํƒ•์ด ใ€Œ์ฝ๋Š” ๊ฐ’ใ€์ด๋ผ๊ณ  ๋จผ์ € ๋งํ•œ๋‹ค.\n */\n code[fixed] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n border-radius: 6px;\n background-color: var(--md-sys-color-surface-container-high, rgba(0, 0, 0, 0.05));\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n font-family: var(--mono-font, monospace);\n font-size: 0.76rem;\n }\n\n code[fixed] md-icon {\n --md-icon-size: 13px;\n opacity: 0.7;\n }\n `\n ]\n\n /** ๋„ํ˜•์˜ DB ์‹๋ณ„์ž. ๋น„์–ด ์žˆ์œผ๋ฉด ๋ฏธ์ €์žฅ ์‹ ๊ทœ ๋ชจ๋ธ์ด๋‹ค. */\n @property({ type: String }) figureId = ''\n\n /**\n * ๋ฐœํ–‰ ํŒ ๋ฒˆํ˜ธ. 0 ์ด๋ฉด ํ•œ ๋ฒˆ๋„ ๋ฐœํ–‰๋˜์ง€ ์•Š์•˜๊ณ , ๊ทธ๋•Œ๋งŒ `type` ์„ ๊ณ ์น  ์ˆ˜ ์žˆ๋‹ค(ADR-0063 ๊ฒฐ์ • 4).\n */\n @property({ type: Number }) figureVersion = 0\n\n /**\n * ํƒ€์ž…์ด ๊ตณ์—ˆ๋‚˜ โ€” **ํ•œ ๋ฒˆ์ด๋ผ๋„ ๋ฐœํ–‰๋์œผ๋ฉด ๊ตณ๋Š”๋‹ค**(ADR-0063 ๊ฒฐ์ • 4).\n *\n * ์ €์žฅ๋˜์ง€ ์•Š์€ ์ƒˆ ๋„ํ˜•๊ณผ ์•„์ง ๋ฐœํ–‰ ์ „์ธ ์ดˆ์•ˆ์—์„œ๋Š” ๊ณ ์น  ์ˆ˜ ์žˆ๋‹ค. ์ „์—๋Š” ใ€Œ์ €์žฅ๋๋‚˜ใ€๋กœ\n * ๊ฐˆ๋ž๊ณ , ๊ทธ๋ž˜์„œ ์ €์ž‘์ž๊ฐ€ ๊ธฐ๊ณ„๊ฐ€ ์ง€์€ ์ด๋ฆ„(`FIGURE_MU6RJH47`)์„ ํ•œ ๋ฒˆ๋„ ๋ชป ๊ณ ์ณค๋‹ค.\n */\n private get typeIsFixed(): boolean {\n return !!this.figureId && (this.figureVersion ?? 0) > 0\n }\n /** ๋„ํ˜•์˜ ํ‘œ์‹œ ์ด๋ฆ„. ์ •๋ณธ์€ ์ €์ž‘๋ฉด์ด ๋“ค๊ณ , ์—ฌ๊ธฐ์„œ๋Š” ๋ณด์—ฌ ์ฃผ๊ณ  ๋ฐ”๊พผ๋‹ค(`figure-rename` ์œผ๋กœ ์•Œ๋ฆฐ๋‹ค). */\n @property({ type: String }) figureName = ''\n /** ๋ถ„๋ฅ˜ ํ•˜๋‚˜ โ€” ํŒ”๋ ˆํŠธ์—์„œ ๋ฌถ๋Š” ๊ธฐ์ค€. */\n @property({ type: String }) figureCategory?: string\n /** ํƒœ๊ทธ ์—ฌ๋Ÿฟ โ€” ๋ถ„๋ฅ˜๋กœ๋Š” ๋ชป ํ•˜๋Š” ์ฐพ๊ธฐ. */\n @property({ type: Array }) figureTags?: string[]\n\n /** ํŽด ๋‘” ๋„์›€๋ง. ๋ถ€ํ’ˆ์„ ๋ฐ”๊ฟ”๋„ ์œ ์ง€๋œ๋‹ค โ€” ๋งค๋ฒˆ ๋‹ค์‹œ ํŽด๊ฒŒ ํ•˜์ง€ ์•Š๋Š”๋‹ค. */\n @state() private opened = new Set<string>()\n\n @property({ type: Object }) draft?: FigureDraft\n /** ์ดˆ์•ˆ ์œ„์˜ ๋ถ€ํ’ˆ๋“ค. ์”ฌ ๋ชจ๋ธ ๊ทธ๋Œ€๋กœ๋‹ค. */\n @property({ type: Array }) parts: PartModel[] = []\n\n /**\n * ์ด ๊ณ ์นจ์ด ์ด๋ฏธ ๋†“์ธ ์ธ์Šคํ„ด์Šค์— ๋ฌด์—‡์„ ํ•˜๋‚˜ โ€” ๋ฐœํ–‰๋œ ๋„ํ˜•์—๋งŒ ์žˆ๋‹ค(ADR-0063 ๊ฒฐ์ • 3).\n *\n * ๋ฐœํ–‰ ๋ฌธ์—์„œ๋งŒ ๋งํ•˜๋ฉด ์ €์ž‘์ž๋Š” ์—ด ๊ตฐ๋ฐ๋ฅผ ๊ณ ์นœ ๋’ค์— ๋“ฃ๋Š”๋‹ค. ๊ณ ์น˜๋Š” ์นธ ์˜†์—์„œ ๋งํ•œ๋‹ค.\n */\n @property({ type: Array }) contract: ContractChange[] = []\n\n /** ๊ฒฌ์ฃผ์ง€ ๋ชปํ•œ ๊นŒ๋‹ญ. ๋นˆ ๋ชฉ๋ก๊ณผ ๋œป์ด ๋‹ค๋ฅด๋‹ค โ€” ใ€Œ๊นจ์ง€ ์•Š๋Š”๋‹คใ€๊ฐ€ ์•„๋‹ˆ๋ผ ใ€Œ๋ชจ๋ฅธ๋‹คใ€๋‹ค. */\n @property({ type: String }) contractFailure?: string\n @property({ type: Number }) selected = -1\n\n /** `part` ๋Š” HTMLElement ์˜ ์†์„ฑ(DOMTokenList)์ด๋‹ค โ€” ๊ฐ€๋ฆฌ๋ฉด ํ˜•์ด ์–ด๊ธ‹๋‚œ๋‹ค. */\n private get chosen(): PartModel | undefined {\n return this.parts?.[this.selected]\n }\n\n render() {\n const part = this.chosen\n if (!part || !this.draft) {\n return html`\n ${this.renderFigure(false)}\n <section>\n <h3>${i18next.t('figure.label.properties')}</h3>\n <p quiet>${i18next.t('figure.text.select-a-part-to-edit')}</p>\n </section>\n `\n }\n\n // ์—ฌ๊ธฐ๋ถ€ํ„ฐ๋Š” ์‚ฌ์šฉ์ž ์šฉ์–ด๋‹ค โ€” XยทYยทZ, ์œ„์น˜๋Š” ๋ถ€ํ’ˆ ์ค‘์‹ฌ, ํšŒ์ „์€ ๋„(degree).\n const shown = partToFigure(part, this.draft)\n\n /*\n ์—ญํ• ์„ ๋จผ์ € ๋ฌป๋Š”๋‹ค.\n\n ์ž๋ฆฌ(slot)๋กœ ์ง€์ •ํ•œ ๋ถ€ํ’ˆ์€ **๊ทธ๋ ค์ง€์ง€ ์•Š๋Š”๋‹ค.** ๊ทธ ์‚ฌ์‹ค์„ ๋ชจ๋ฅธ ์ฑ„ ์žฌ์งˆ๋ถ€ํ„ฐ ๊ณ ๋ฅด๋ฉด ์•ˆ ์“ฐ์ผ\n ์ƒ‰์„ ๊ณ ๋ฅด๊ฒŒ ๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ž๋ฆฌ๋Š” ๋„ํ˜•์ด ๋Šฅ๋ ฅ์„ ์งˆ ๋•Œ๋งŒ ๋œป์ด ์žˆ์œผ๋ฏ€๋กœ, ๋Šฅ๋ ฅ์ด ์—†์œผ๋ฉด ์ด\n ๋ฌถ์Œ์€ ์•„์˜ˆ ๋‚˜์˜ค์ง€ ์•Š๋Š”๋‹ค โ€” ํ•ด ๋‘ฌ๋„ ์•„๋ฌด ์ผ๋„ ์•ˆ ์ผ์–ด๋‚˜๋Š” ์นธ์„ ๋ณด์—ฌ ์ฃผ์ง€ ์•Š๋Š”๋‹ค.\n */\n return html`\n ${this.renderFigure(true)} ${this.renderIdentity(shown)} ${this.renderRole(shown)} ${this.renderJoint(shown)}\n ${this.renderPlacement(shown)} ${this.renderShape(shown)} ${this.renderMaterial(shown)}\n ${this.renderBehaviour(shown)}\n `\n }\n\n /**\n * โ”€โ”€ ์ด ๋ถ€ํ’ˆ์ด ๋Šฅ๋ ฅ์—์„œ ๋งก๋Š” ์ž๋ฆฌ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n *\n * ใ€Œ๋Šฅ๋ ฅใ€ ํƒญ์ด ๋„ํ˜• ์ „์ฒด๊ฐ€ ๋ฌด์—‡์„ ํ•˜๋Š”์ง€ ์ •ํ•˜๊ณ , ์–ด๋А ๋ถ€ํ’ˆ์ด ๊ทธ๊ฒƒ์„ ๋ฐ›์ณ ์ฃผ๋Š”์ง€๋Š” ์—ฌ๊ธฐ์„œ\n * ์ •ํ•œ๋‹ค. **๋ถ€ํ’ˆ์„ ๊ณ ์น˜๋Š” ๊ณณ์ด ํ•œ ๊ตฐ๋ฐ์—ฌ์•ผ** ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค โ€” ๋ชฉ๋ก์„ ๋”ฐ๋กœ ๋‘๋ฉด ๊ฐ™์€ ๋ถ€ํ’ˆ์„\n * ๋‘ ํ™”๋ฉด์—์„œ ๊ณ ์น˜๊ฒŒ ๋˜๊ณ , ์ €์ž‘์ž๋Š” ์–ด๋А ์ชฝ์ด ์ด๊ธฐ๋Š”์ง€ ๋งค๋ฒˆ ์ƒ๊ฐํ•ด์•ผ ํ•œ๋‹ค.\n *\n * ์นธ ์ˆ˜๋Š” `repeat` ๊ฐ€ ์žˆ์œผ๋ฉด ๋ฐ›์ง€ ์•Š๋Š”๋‹ค. ๋ฐ˜๋ณตํ•˜๋Š” ์ž๋ฆฌ์˜ ์นธ ์ˆ˜๋Š” **์ธ์Šคํ„ด์Šค ํฌ๊ธฐ**๊ฐ€ ์ •ํ•œ๋‹ค โ€”\n * ์ปจ๋ฒ ์ด์–ด๊ฐ€ ๊ธธ์–ด์ง€๋ฉด ์‹ค์„ ์ž๋ฆฌ๊ฐ€ ๋Š˜์–ด๋‚˜๋Š” ๊ฒƒ์ด ๊ทธ๊ฒƒ์ด๊ณ , ์—ฌ๊ธฐ ์ ์€ ๊ฐ’์€ ์•ˆ ์“ฐ์ธ๋‹ค.\n */\n private renderRole(part: FigurePart) {\n if (!this.draft?.capabilities?.length) return nothing\n\n const roles = part.capability?.roles ?? []\n const repeats = part.sizing === 'repeat' && !!part.repeat\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.role-in-capability')}${this.help('figure.text.anchors-are-not-drawn')}</h3>\n\n <div role-choices>\n ${(PART_ROLES as readonly PartRole[]).map(\n one => html`\n <label toggle>\n <input\n type=\"checkbox\"\n .checked=${live(roles.includes(one))}\n @change=${(e: Event) => this.toggleRole(one, (e.target as HTMLInputElement).checked)}\n />\n ${i18next.t('figure.label.role-' + one)}\n </label>\n `\n )}\n </div>\n ${roles.length === 0 ? html`<p quiet>${i18next.t('figure.text.role-none-means-drawn')}</p>` : nothing}\n\n ${roles.includes('slot')\n ? html`\n <div field>\n <label>${i18next.t('figure.label.accepts')}${this.help('figure.text.accepts-explained')}</label>\n <input\n .value=${(part.capability?.accepts ?? []).join(', ')}\n placeholder=${i18next.t('figure.text.accepts-anything')}\n @change=${(e: Event) => this.setAccepts((e.target as HTMLInputElement).value)}\n />\n </div>\n <div field>\n <label>${i18next.t('figure.label.slot-capacity')}</label>\n ${repeats\n ? html`<p quiet>${i18next.t('figure.text.capacity-from-repeat')}</p>`\n : this.number('', part.capability?.capacity ?? 1, value => this.setCapacity(value), 1)}\n </div>\n `\n : nothing}\n </section>\n `\n }\n\n /**\n * How this part hangs from another and moves relative to it (ADR-0066).\n *\n * The parent is written on the part. The joint says how the part moves relative to that parent, and the\n * parameter it comes with is what drives it; the preview shows that parameter as a slider.\n */\n private renderJoint(part: FigurePart) {\n const joint = jointOf(this.draft, part.name)\n const choices = parentChoices(this.parts, part.name)\n const unit = joint?.type === 'prismatic' ? 'mm' : 'deg'\n const axisKey = joint ? axisKeyOf(joint.axis) : undefined\n const driver = joint\n ? this.draft?.parameters?.find(one => one.clip?.channels?.some(channel => channel.target === joint.name))\n : undefined\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.joint')}${this.help('figure.text.joint-explained')}</h3>\n\n <div inline-field>\n <label>${i18next.t('figure.label.joint-parent')}</label>\n <select @change=${(e: Event) => this.setParent((e.target as HTMLSelectElement).value)}>\n <option value=\"\" ?selected=${part.parent === undefined}>${i18next.t('figure.label.joint-parent-none')}</option>\n ${part.parent !== undefined && !choices.includes(part.parent)\n ? html`<option value=${part.parent} selected>${part.parent}</option>`\n : nothing}\n ${choices.map(name => html`<option value=${name} ?selected=${name === part.parent}>${name}</option>`)}\n </select>\n </div>\n\n <div inline-field>\n <label>${i18next.t('figure.label.joint-type')}</label>\n <select @change=${(e: Event) => this.setJointType(part, (e.target as HTMLSelectElement).value)}>\n <option value=\"\" ?selected=${!joint}>${i18next.t('figure.label.joint-type-none')}</option>\n ${(JOINT_TYPES as readonly JointType[]).map(\n type => html`<option value=${type} ?selected=${joint?.type === type}>${i18next.t('figure.label.joint-type-' + type)}</option>`\n )}\n </select>\n </div>\n\n ${joint\n ? html`\n <div inline-field>\n <label>${i18next.t('figure.label.joint-axis')}</label>\n <select @change=${(e: Event) => this.setJointAxis(joint.name, (e.target as HTMLSelectElement).value)}>\n ${axisKey === undefined\n ? html`<option value=\"\" selected>${joint.axis.x}, ${joint.axis.y}, ${joint.axis.z}</option>`\n : nothing}\n ${JOINT_AXES.map(one => html`<option value=${one.key} ?selected=${one.key === axisKey}>${one.key.toUpperCase()}</option>`)}\n </select>\n </div>\n\n <div vector-row>\n <label>${i18next.t('figure.label.joint-origin')}</label>\n <div triple>\n ${(['x', 'y', 'z'] as const).map(axis =>\n this.number(axis.toUpperCase(), joint.origin[axis], value =>\n this.tellDraft(patchJoint(this.draft!, joint.name, { origin: { ...joint.origin, [axis]: value } }))\n )\n )}\n </div>\n </div>\n\n ${joint.limits\n ? html`\n <div vector-row>\n <label>${i18next.t('figure.label.joint-limits-' + unit)}</label>\n <div double>\n ${this.number(i18next.t('figure.label.joint-limit-min'), joint.limits.min, value =>\n this.tellDraft(patchJoint(this.draft!, joint.name, { limits: { ...joint.limits!, min: value } }))\n )}\n ${this.number(i18next.t('figure.label.joint-limit-max'), joint.limits.max, value =>\n this.tellDraft(patchJoint(this.draft!, joint.name, { limits: { ...joint.limits!, max: value } }))\n )}\n </div>\n </div>\n ${joint.limits.min > 0 || joint.limits.max < 0\n ? html`<p warn>${i18next.t('figure.text.joint-limits-must-include-zero')}</p>`\n : nothing}\n `\n : nothing}\n\n <p quiet>\n ${driver\n ? i18next.t('figure.text.joint-driven-by', { name: driver.label ?? driver.name })\n : i18next.t('figure.text.joint-not-driven')}\n </p>\n `\n : nothing}\n </section>\n `\n }\n\n private setParent(name: string) {\n this.change(part => {\n const { parent: _dropped, ...rest } = part\n return name === '' ? (rest as FigurePart) : { ...rest, parent: name }\n })\n }\n\n /**\n * ๊ธฐ์ค€ ์ƒ์ž๋ฅผ ๊ณ ์นœ๋‹ค โ€” ๋ถ€ํ’ˆ์€ ์ €์žฅ๋˜๋Š” ์ž๋ฆฌ์— ๊ทธ๋Œ€๋กœ ๋‘” ์ฑ„(`base-box.ts`).\n *\n * ์ดˆ์•ˆ๊ณผ ๋ถ€ํ’ˆ์ด ํ•จ๊ป˜ ๋ฐ”๋€Œ๋ฏ€๋กœ ๋‘˜์„ ํ•œ ๋ฒˆ์— ์˜ฌ๋ฆฐ๋‹ค. ๋”ฐ๋กœ ์˜ฌ๋ฆฌ๋ฉด ๋˜๋Œ๋ฆฌ๊ธฐ๊ฐ€ ๋‘˜๋กœ ๊ฐˆ๋ฆฌ๊ณ , ๊ทธ ์‚ฌ์ด\n * ํ•œ ๋ฒˆ๋งŒ ๋˜๋Œ๋ฆฐ ํ™”๋ฉด์€ ๋ถ€ํ’ˆ์ด ๋ฐ˜์ฏค ๋ฐ€๋ฆฐ ๋ชจ์Šต์ด ๋œ๋‹ค.\n */\n /**\n * ๊ธฐ์ค€ ์ƒ์ž๋ฅผ ๊ณ ์นœ ๊ฒƒ์ด **์ด๋ฏธ ๋†“์ธ ์ธ์Šคํ„ด์Šค์— ๋ฌด์—‡์„ ํ•˜๋‚˜** โ€” ๊ณ ์นœ ์นธ ๋ฐ”๋กœ ์•„๋ž˜์—์„œ ๋งํ•œ๋‹ค.\n *\n * ๋ง‰๋Š” ๊ฒƒ๊ณผ ์•Œ๋ฆฌ๋Š” ๊ฒƒ์„ ๊ฐ€๋ฅธ๋‹ค. ๋น„์œจ์ด ๋‹ฌ๋ผ์ง€๋ฉด ๋†“์ธ ๊ฒƒ์ด ์ฐŒ๊ทธ๋Ÿฌ์ง€๋ฏ€๋กœ ๋ฐœํ–‰์ด ๋ง‰ํžˆ๊ณ , ํฌ๊ธฐ๋งŒ\n * ๋‹ฌ๋ผ์ง€๋Š” ๊ฒƒ์€ ์‹ค์ฒ™์ด ์–ด๊ธ‹๋‚  ๋ฟ์ด๋ผ ์•Œ๋ฆฌ๊ธฐ๋งŒ ํ•œ๋‹ค. ๊นŒ๋‹ญ์€ ํ˜•์‹์ด ์ ์€ ๊ฒƒ์„ ๊ทธ๋Œ€๋กœ ์˜ฎ๊ธด๋‹ค โ€”\n * ์—ฌ๊ธฐ์„œ ๋‹ค์‹œ ์“ฐ๋ฉด ๋‘ ๋ฒŒ์ด ๋˜๊ณ  ๊ณง ๊ฐˆ๋ฆฐ๋‹ค.\n */\n private renderBaseContract() {\n if (this.contractFailure) {\n return html`<p contract>\n <md-icon>help</md-icon>\n <span>${i18next.t('figure.text.contract-not-compared', { why: this.contractFailure })}</span>\n </p>`\n }\n\n const mine = this.contract.filter(one => one.code === 'base-ratio-changed' || one.code === 'base-size-changed')\n if (mine.length === 0) return nothing\n\n return html`${mine.map(\n one => html`<p contract ?blocking=${one.blocking}>\n <md-icon>${one.blocking ? 'block' : 'info'}</md-icon>\n <span><b>${one.message}</b> ${one.why}</span>\n </p>`\n )}`\n }\n\n private resizeBase(patch: Partial<BaseSize>) {\n if (!this.draft) return\n\n const next = resizeBase(this.draft, this.parts, { ...baseOf(this.draft), ...patch })\n if (next.draft === this.draft) return\n\n this.dispatchEvent(\n new CustomEvent('resize-base', {\n detail: { draft: next.draft, parts: next.parts },\n bubbles: true,\n composed: true\n })\n )\n }\n\n /** ๋ถ€ํ’ˆ ์ „๋ถ€๋ฅผ ๊ฐ์‹ธ๋Š” ๊ฐ€์žฅ ์ž‘์€ ์ƒ์ž๋กœ. ๋งž์ถœ ๊ฒƒ์ด ์—†์œผ๋ฉด ์•„๋ฌด ์ผ๋„ ์•ˆ ํ•œ๋‹ค. */\n private fitBaseToParts() {\n if (!this.draft) return\n const fitted = baseFittingParts(this.draft, this.parts)\n if (fitted) this.resizeBase(fitted)\n }\n\n private setJointType(part: FigurePart, value: string) {\n if (!this.draft) return\n\n /* ๋ถ™์€ ๋ถ€ํ’ˆ์„ ํ•จ๊ป˜ ์ค€๋‹ค โ€” ์ƒˆ ๊ด€์ ˆ์ด ๋‘˜์ด ๋งž๋‹ฟ๋Š” ์ž๋ฆฌ์— ์„œ๋ ค๋ฉด ๊ทธ์ชฝ ์น˜์ˆ˜๋ฅผ ์•Œ์•„์•ผ ํ•œ๋‹ค. */\n const parent = part.parent ? this.parts.find(one => one.name === part.parent) : undefined\n this.tellDraft(\n setJointType(\n this.draft,\n part,\n value === '' ? undefined : (value as JointType),\n parent ? partToFigure(parent, this.draft) : undefined\n )\n )\n }\n\n private setJointAxis(name: string, key: string) {\n const choice = JOINT_AXES.find(one => one.key === key)\n if (!choice || !this.draft) return\n this.tellDraft(patchJoint(this.draft, name, { axis: { ...choice.axis } }))\n }\n\n private tellDraft(draft: FigureDraft) {\n this.dispatchEvent(new CustomEvent('update-draft', { detail: { draft }, bubbles: true, composed: true }))\n }\n\n /**\n * ์—ญํ•  ํ•˜๋‚˜๋ฅผ ์ผœ๊ณ  ๋ˆ๋‹ค.\n *\n * **์—ฌ๋Ÿฟ์„ ํ•จ๊ป˜ ๋งก์„ ์ˆ˜ ์žˆ๋‹ค.** AGV ์˜ ์ƒํŒ์€ ๋ฌผ๊ฑด์„ ๋†“๋Š” ์ž๋ฆฌ์ด๋ฉด์„œ ๊ทธ ์ž๋ฆฌ๋กœ ๋ฌผ๊ฑด์ด\n * ๋“ค์–ด์˜ค๊ณ  ๋‚˜๊ฐ„๋‹ค. ๊ทธ๋ž˜์„œ ํ•˜๋‚˜๋ฅผ ๊ณ ๋ฅด๋Š” ์„ ํƒ ์ƒ์ž๊ฐ€ ์•„๋‹ˆ๋ผ ํ™•์ธ ์ƒ์ž๋‹ค.\n *\n * ๋งˆ์ง€๋ง‰ ์—ญํ• ์„ ๋„๋ฉด `capability` ๋ฅผ ํ†ต์งธ๋กœ ์ง€์šด๋‹ค. ๋นˆ ๋ฐฐ์—ด์„ ๋‚จ๊ธฐ๋ฉด ํ˜•์‹์ด ์˜ค๋ฅ˜๋กœ ๋ณด๊ณ ,\n * ์ €์ž‘์ž๊ฐ€ ๋ณด๊ธฐ์—๋Š” ์•„๋ฌด ์—ญํ• ๋„ ์—†๋Š” ํ‰๋ฒ”ํ•œ ๋ถ€ํ’ˆ์ธ๋ฐ ๋ฐœํ–‰์ด ๋ง‰ํžŒ๋‹ค.\n */\n private toggleRole(role: PartRole, on: boolean) {\n this.change(part => {\n const roles = (part.capability?.roles ?? []).filter(one => one !== role)\n if (on) roles.push(role)\n\n if (roles.length === 0) {\n const { capability, ...rest } = part\n return rest as FigurePart\n }\n\n // ํ˜•์‹์ด ์ ์€ ์ˆœ์„œ๋ฅผ ์ง€ํ‚จ๋‹ค โ€” ์ผ  ์ˆœ์„œ๋Œ€๋กœ ๋‘๋ฉด ๊ฐ™์€ ๋œป์ด ๋‹ค๋ฅธ ๊ฐ’์œผ๋กœ ์ €์žฅ๋œ๋‹ค.\n const ordered = (PART_ROLES as readonly PartRole[]).filter(one => roles.includes(one))\n return { ...part, capability: { ...part.capability, roles: ordered } }\n })\n }\n\n private setAccepts(raw: string) {\n const accepts = raw\n .split(',')\n .map(one => one.trim())\n .filter(one => one.length > 0)\n\n this.change(part => {\n const spec = { ...part.capability, roles: part.capability?.roles ?? ['slot' as PartRole] }\n // ๋นˆ ๋ชฉ๋ก์€ ์ œํ•œํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๋œป์ด๋‹ค. ๋นˆ ๋ฐฐ์—ด์„ ์ €์žฅํ•˜๋ฉด ์•„๋ฌด๊ฒƒ๋„ ๋ชป ๋ฐ›๋Š” ๊ฒƒ์œผ๋กœ ์ฝํžŒ๋‹ค.\n if (accepts.length > 0) spec.accepts = accepts\n else delete spec.accepts\n return { ...part, capability: spec as NonNullable<FigurePart['capability']> }\n })\n }\n\n private setCapacity(value: number) {\n this.change(part => {\n const spec = { ...part.capability, roles: part.capability?.roles ?? ['slot' as PartRole] }\n if (Number.isFinite(value) && value >= 1) spec.capacity = Math.floor(value)\n else delete spec.capacity\n return { ...part, capability: spec as NonNullable<FigurePart['capability']> }\n })\n }\n\n /**\n * ๋„ํ˜• ์ž์ฒด โ€” ์ด๋ฆ„๊ณผ ํƒ€์ž….\n *\n * ## ์™œ ๋จธ๋ฆฌ์ค„์ด ์•„๋‹ˆ๋ผ ์—ฌ๊ธฐ์ธ๊ฐ€\n *\n * ์ €์ž‘๋ฉด ์œ„์— ์ค„์„ ํ•˜๋‚˜ ๋” ๋‘๊ณ  ์ด๋ฆ„ ์นธ์„ ๋†“์•˜์—ˆ๋‹ค. ์•ฑ์—์„œ๋Š” ์…ธ์ด ํŽ˜์ด์ง€ ์ œ๋ชฉ์œผ๋กœ ๊ทธ ์ด๋ฆ„์„\n * ์ด๋ฏธ ๊ทธ๋ฆฌ๋ฏ€๋กœ ๊ฐ™์€ ๊ธ€์ž๊ฐ€ ๋‘ ๋ฒˆ ๋‚˜์˜ค๊ณ , ์บ”๋ฒ„์Šค๊ฐ€ ์ฃผ์ธ๊ณต์ธ ํ™”๋ฉด์—์„œ ๊ทธ ์ค„๋งŒํผ ๋†’์ด๋ฅผ ์žƒ์—ˆ๋‹ค.\n * ์†์„ฑ ํŒจ๋„์€ ใ€Œ์ด ๋„ํ˜•์ด ๋ฌด์—‡์ธ๊ฐ€ใ€๋ฅผ ๋‹ค๋ฃจ๋Š” ์ž๋ฆฌ์ด๋ฏ€๋กœ ์ด๋ฆ„๋„ ์—ฌ๊ธฐ ์‚ฐ๋‹ค.\n *\n * ## ํƒ€์ž…์€ ์ฝ๊ธฐ๋งŒ ํ•œ๋‹ค\n *\n * ์ €์žฅ๋˜๋Š” ์‹๋ณ„์ž๋‹ค. ๋ฐฐ์น˜๋œ ๋„๋ฉด์ด ์ด ์ด๋ฆ„์œผ๋กœ ํƒ€์ž…์„ ์ฐพ์œผ๋ฏ€๋กœ ๋งŒ๋“  ๋’ค์—๋Š” ๋ชป ๋ฐ”๊พผ๋‹ค.\n */\n private renderFigure(compact = false) {\n const fields = html`\n <div inline-field>\n <label>${i18next.t('figure.label.name')}</label>\n <input\n .value=${this.figureName}\n placeholder=${i18next.t('figure.text.figure-display-name')}\n @change=${(e: Event) =>\n this.dispatchEvent(\n new CustomEvent('figure-rename', {\n detail: { name: (e.target as HTMLInputElement).value },\n bubbles: true,\n composed: true\n })\n )}\n />\n </div>\n <div inline-field>\n <label>${i18next.t('figure.label.figure-type')}${this.typeIsFixed ? this.helpButton('figure.text.type-name-cannot-change') : nothing}</label>\n ${!this.typeIsFixed\n ? html`<input\n .value=${this.draft?.figureType ?? ''}\n placeholder=${i18next.t('figure.text.figure-type-placeholder')}\n @change=${(e: Event) =>\n this.dispatchEvent(\n new CustomEvent('figure-type-change', {\n detail: { type: (e.target as HTMLInputElement).value.trim().toUpperCase() },\n bubbles: true,\n composed: true\n })\n )}\n />`\n : html`<code fixed title=${i18next.t('figure.text.type-name-cannot-change')}>\n <md-icon>lock</md-icon>${this.draft?.figureType ?? ''}\n </code>\n ${this.helpHint('figure.text.type-name-cannot-change')}`}\n </div>\n <!--\n ์™œ ๋ชป ๊ณ ์น˜๋Š”์ง€ **์ ์–ด ๋‘”๋‹ค.** ์ „์—๋Š” tooltip ์—๋งŒ ์žˆ์—ˆ๊ณ , ๊ทธ๋Ÿฌ๋ฉด ๋ˆŒ๋Ÿฌ ๋ณด๊ณ  ์•ˆ ๋˜๋Š” ๊ฒƒ์„\n ์•Œ๊ฒŒ ๋œ๋‹ค โ€” ํ™”๋ฉด์ด ์•ˆ ๋˜๋Š” ์ด์œ ๋ฅผ ๋งํ•˜์ง€ ์•Š์œผ๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ์ž๊ธฐ ์‹ค์ˆ˜๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค.\n -->\n\n <div inline-field>\n <label>${i18next.t('figure.label.figure-placement')}${this.helpButton('figure.text.placement-explained')}</label>\n <select\n .value=${this.draft?.placement ?? 'floor'}\n @change=${(e: Event) => this.setPlacement((e.target as HTMLSelectElement).value as FigurePlacement)}\n >\n <option value=\"floor\" ?selected=${(this.draft?.placement ?? 'floor') === 'floor'}>\n ${i18next.t('figure.label.placement-floor')}\n </option>\n <option value=\"ceiling\" ?selected=${this.draft?.placement === 'ceiling'}>\n ${i18next.t('figure.label.placement-ceiling')}\n </option>\n <option value=\"center\" ?selected=${this.draft?.placement === 'center'}>\n ${i18next.t('figure.label.placement-center')}\n </option>\n </select>\n ${this.helpHint('figure.text.placement-explained')}\n </div>\n\n <!--\n ๊ธฐ์ค€ ์ƒ์ž โ€” **๊ณ ์น˜๋Š” ๊ธธ์ด ํ™”๋ฉด์— ์žˆ์–ด์•ผ ํ•œ๋‹ค.** ๋ถ€ํ’ˆ์ด ์ด ์ƒ์ž๋ฅผ ๋„˜์œผ๋ฉด ๋ฐœํ–‰์ด ๋ง‰ํžˆ๊ณ ,\n ๊ณ ์น˜๋Š” ๋ฐฉ๋ฒ•์€ ์ƒ์ž ์ˆซ์ž๋ฅผ ํ‚ค์šฐ๋Š” ๊ฒƒ์ด๋‹ค(ADR-0044 โ‘ฃ). ๊ทธ ์นธ์ด ์—†์–ด์„œ ์ €์ž‘์ž๋Š” ๋„˜์ณค๋‹ค๋Š”\n ๋ง๋งŒ ๋“ฃ๊ณ  ๊ณ ์น  ์ž๋ฆฌ๋ฅผ ๋ชป ์ฐพ์•˜๋‹ค.\n -->\n <div field>\n <label>${i18next.t('figure.label.base-box')}${this.helpButton('figure.text.base-box-explained')}</label>\n <div triple>\n ${this.number('X', this.draft?.width ?? 0, value => this.resizeBase({ width: value }), 1)}\n ${this.number('Y', this.draft?.depth ?? 0, value => this.resizeBase({ depth: value }), 1)}\n ${this.number('Z', this.draft?.height ?? 0, value => this.resizeBase({ height: value }), 1)}\n </div>\n ${this.parts.length > 0\n ? html`<button fit @click=${() => this.fitBaseToParts()} title=${i18next.t('figure.text.fit-base-explained')}>\n <md-icon>fit_screen</md-icon>${i18next.t('figure.button.fit-base-to-parts')}\n </button>`\n : nothing}\n ${this.renderBaseContract()}\n ${this.helpHint('figure.text.base-box-explained')}\n </div>\n\n <div inline-field>\n <label>${i18next.t('figure.label.category')}${this.helpButton('figure.text.category-explained')}</label>\n <input\n .value=${this.figureCategory ?? ''}\n placeholder=${i18next.t('figure.text.category-placeholder')}\n @change=${(e: Event) => this.tellCatalog({ category: (e.target as HTMLInputElement).value.trim() || undefined })}\n />\n ${this.helpHint('figure.text.category-explained')}\n </div>\n\n <div inline-field>\n <label>${i18next.t('figure.label.tags')}${this.helpButton('figure.text.tags-explained')}</label>\n <input\n .value=${(this.figureTags ?? []).join(', ')}\n placeholder=${i18next.t('figure.text.tags-placeholder')}\n @change=${(e: Event) => this.tellTags((e.target as HTMLInputElement).value)}\n />\n ${this.helpHint('figure.text.tags-explained')}\n </div>\n `\n\n if (compact) {\n return html`\n <section>\n <details asset>\n <summary>\n <b>${i18next.t('figure.label.figure')}</b>\n <small>${this.figureName || this.draft?.figureType || ''}</small>\n </summary>\n ${fields}\n </details>\n </section>\n `\n }\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.figure')}</h3>\n ${fields}\n </section>\n `\n }\n\n /**\n * ํƒœ๊ทธ ์ค„์„ ๋ชฉ๋ก์œผ๋กœ.\n *\n * ์‰ผํ‘œ๋กœ ๊ฐ€๋ฅด๊ณ  `#` ์€ ๋–ผ์–ด ๋‚ธ๋‹ค โ€” ์‚ฌ๋žŒ์€ `#๋ฐ˜์ถœ` ์ด๋ผ๊ณ  ์ ๊ณ , ์ €์žฅ๋˜๋Š” ๊ฒƒ์€ `๋ฐ˜์ถœ` ์ด๋‹ค.\n * ๊ฒน์นœ ๊ฒƒ์€ ํ•œ ๋ฒˆ๋งŒ ๋‚จ๊ธด๋‹ค. ๋นˆ ์ค„์€ **๋นˆ ๋ฐฐ์—ด**์ด์ง€ `undefined` ๊ฐ€ ์•„๋‹ˆ๋‹ค โ€” ์ „๋ถ€ ์ง€์šฐ๋ ค๋Š”\n * ์ €์ž‘์ž๊ฐ€ ์ง€์šธ ๋ฐฉ๋ฒ•์„ ์žƒ์ง€ ์•Š๊ฒŒ.\n */\n private tellTags(raw: string) {\n const tags = [\n ...new Set(\n raw\n .split(',')\n .map(one => one.trim().replace(/^#+/, '').trim())\n .filter(one => one.length > 0)\n )\n ]\n\n this.tellCatalog({ tags })\n }\n\n /** ์นดํƒˆ๋กœ๊ทธ ๊ฐ’์ด ๋ฐ”๋€Œ์—ˆ๋‹ค๊ณ  ์•Œ๋ฆฐ๋‹ค. ์ •๋ณธ์€ ์ €์ž‘๋ฉด์ด ๋“ ๋‹ค โ€” ์—ฌ๊ธฐ์„œ๋Š” ์•Œ๋ฆฌ๊ธฐ๋งŒ ํ•œ๋‹ค. */\n private tellCatalog(patch: { category?: string; tags?: string[] }) {\n this.dispatchEvent(new CustomEvent('figure-catalog', { detail: patch, bubbles: true, composed: true }))\n }\n\n /**\n * 3D ๋ฐฐ์น˜ ๊ธฐ์ค€๋ฉด์„ ๋ฐ”๊พผ๋‹ค ('floor' | 'ceiling' | 'center').\n *\n * **๋ถ€ํ’ˆ์€ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค.** ์ด ๊ฐ’์€ ใ€Œ์ด ์ข…๋ฅ˜๋Š” ์–ด๋А ๋ฉด์— ๋ถ™๋Š”๊ฐ€ใ€๋ฅผ ๋งํ•  ๋ฟ์ด๊ณ ,\n * ์ €์ž‘ํ•œ ๋ชจ์–‘์€ ๊ทธ๊ฒƒ๊ณผ ๋ฌด๊ด€ํ•˜๋‹ค. ํ˜•์‹์ด ๋ถ€ํ’ˆ์„ ์ƒ์ž ์ค‘์‹ฌ์—์„œ ์žฌ๋ฏ€๋กœ, ๋ฐฐ์น˜๊ฐ€ ๋‹ฌ๋ผ๋„\n * `parts` ๋Š” ํ•œ ๊ธ€์ž๋„ ์•ˆ ๋ฐ”๋€๋‹ค.\n *\n * ํ•œ๋™์•ˆ ์—ฌ๊ธฐ์„œ `zPos` ๋ฅผ ๋‹ค์‹œ ๊ณ„์‚ฐํ–ˆ๋‹ค. ํŽธ์ง‘ ์บ”๋ฒ„์Šค๊ฐ€ ์ด ๊ฐ’์„ ์”ฌ์˜ ์ขŒํ‘œ ๋ชจ๋“œ๋กœ\n * ํ˜๋ ค๋ณด๋‚ด๋˜ ๋•Œ์˜ ์ผ์ธ๋ฐ, ๊ทธ๋Ÿฌ๋ฉด ๋ฐฐ์น˜๋ฅผ ๊ณ ๋ฅผ ๋•Œ๋งˆ๋‹ค ์ €์ž‘์ž๊ฐ€ ์ ์–ด ๋‘” ๋†’์ด๊ฐ€ ์ „๋ถ€\n * ๋‹ค๋ฅธ ์ˆซ์ž๋กœ ๋ณด์˜€๋‹ค โ€” ์ €์žฅ๋˜๋Š” ๊ฒƒ์€ ๊ทธ๋Œ€๋กœ์ธ๋ฐ. ์ขŒํ‘œ ๋ชจ๋“œ๋Š” ์ด์ œ ๋ณด๊ธฐ ์„ค์ •์ด๊ณ \n * (`figure-view.ts`), ํŽธ์ง‘ ์บ”๋ฒ„์Šค๋Š” ๋Š˜ ์ƒ์ž ๊ธฐ์ค€์ด๋‹ค.\n */\n private setPlacement(placement: FigurePlacement) {\n if (!this.draft) return\n const draft = { ...this.draft, placement }\n this.dispatchEvent(new CustomEvent('update-draft', { detail: { draft }, bubbles: true, composed: true }))\n }\n\n private renderIdentity(part: FigurePart) {\n return html`\n <section>\n <h3>${i18next.t('figure.label.part')}</h3>\n <div inline-field>\n <label>${i18next.t('figure.label.name')}${this.helpButton('figure.text.renaming-a-part-breaks-bindings')}</label>\n <input\n .value=${part.name}\n @change=${(e: Event) => this.put({ name: (e.target as HTMLInputElement).value })}\n />\n ${this.helpHint('figure.text.renaming-a-part-breaks-bindings')}\n </div>\n <div inline-field>\n <label>${i18next.t('figure.label.shape')}</label>\n <select @change=${(e: Event) => this.changePrimitive((e.target as HTMLSelectElement).value as PrimitiveKind)}>\n ${PRIMITIVE_KINDS.map(\n kind => html`\n <option value=${kind} ?selected=${kind === part.primitive}>\n ${i18next.t('figure.label.primitive-' + kind)}\n </option>\n `\n )}\n </select>\n </div>\n </section>\n `\n }\n\n private renderPlacement(part: FigurePart) {\n const t = part.transform\n const rotation = t.rotation ?? {}\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.placement')}</h3>\n\n <div vector-row>\n <label>${i18next.t('figure.label.part-position')}</label>\n <div triple>\n ${(['x', 'y', 'z'] as const).map(axis =>\n this.number(axis.toUpperCase(), t.position[axis], value =>\n this.putTransform({ position: { ...t.position, [axis]: value } })\n )\n )}\n </div>\n </div>\n\n <div vector-row>\n <label>${i18next.t('figure.label.part-size')}</label>\n <div triple>\n ${(['x', 'y', 'z'] as const).map(axis =>\n this.number(\n axis.toUpperCase(),\n t.size[axis],\n value => this.putTransform({ size: { ...t.size, [axis]: value } }),\n 1\n )\n )}\n </div>\n </div>\n\n <div vector-row>\n <label>${i18next.t('figure.label.rotation-degrees')}</label>\n <div triple>\n ${(['x', 'y', 'z'] as const).map(axis =>\n this.number(axis.toUpperCase(), rotation[axis] ?? 0, value =>\n this.putTransform({ rotation: { ...rotation, [axis]: value } })\n )\n )}\n </div>\n </div>\n\n <div vector-row>\n <label>${i18next.t('figure.label.tools')}${this.helpButton('figure.text.tools-explained')}</label>\n <div tools>\n <button\n aria-label=${i18next.t('figure.button.center-x')}\n title=${i18next.t('figure.text.center-on-x')}\n @click=${() => this.ask('center', 'x')}\n >\n <md-icon>horizontal_distribute</md-icon>\n </button>\n <button\n aria-label=${i18next.t('figure.button.center-z')}\n title=${i18next.t('figure.text.center-on-z')}\n @click=${() => this.ask('center', 'z')}\n >\n <md-icon>vertical_align_center</md-icon>\n </button>\n <button\n aria-label=${i18next.t('figure.button.to-floor')}\n title=${i18next.t('figure.text.put-on-floor')}\n @click=${() => this.ask('floor', 'y')}\n >\n <md-icon>vertical_align_bottom</md-icon>\n </button>\n ${(['x', 'z'] as const).map(axis => {\n // ์ด๋ฏธ ๊ฐ€์šด๋ฐ๋ฉด ๋Œ€์นญ์ด ์ œ์ž๋ฆฌ๋‹ค โ€” ๊ฒน์นœ ๋ถ€ํ’ˆ์ด ์กฐ์šฉํžˆ ์ƒ๊ธฐ์ง€ ์•Š๊ฒŒ ๋ง‰๋Š”๋‹ค\n const able = this.draft ? canMirror(this.draft, this.parts, this.selected, axis) : false\n return html`\n <button\n ?disabled=${!able}\n aria-label=${i18next.t('figure.button.mirror-' + axis)}\n title=${i18next.t(able ? 'figure.text.mirror-explained' : 'figure.text.mirror-would-overlap')}\n @click=${() => this.ask('mirror', axis)}\n >\n <md-icon>${axis === 'x' ? 'flip' : 'flip_camera_android'}</md-icon>\n </button>\n `\n })}\n <button\n aria-label=${i18next.t('figure.button.snap')}\n title=${i18next.t('figure.text.snap-explained')}\n @click=${() => this.ask('snap', 'x')}\n >\n <md-icon>grid_on</md-icon>\n </button>\n </div>\n ${this.helpHint('figure.text.tools-explained')}\n </div>\n </section>\n `\n }\n\n /** ๋ถ„ํ•  ์ˆ˜์™€ ๋ชจ์„œ๋ฆฌ ๊ตด๋ฆผ โ€” ํ•ด๋‹นํ•˜๋Š” ๋„ํ˜•์—๋งŒ ๋‚ธ๋‹ค. */\n private renderShape(part: FigurePart) {\n const segmented = SEGMENTED_PRIMITIVES.includes(part.primitive)\n const extruded = EXTRUDE_PRIMITIVES.includes(part.primitive)\n if (!segmented && !extruded) return nothing\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.shape-detail')}</h3>\n ${segmented ? this.renderSegments(part) : nothing}\n ${segmented ? this.renderKeepRound(part) : nothing}\n ${extruded ? this.renderExtruded(part) : nothing}\n </section>\n `\n }\n\n /**\n * ๋ฏผ ๋‹จ๋ฉด โ€” ๋ชจ์„œ๋ฆฌ์™€ **์†์„ ํŒŒ๋Š” ๋‘๊ป˜.**\n *\n * ๋ฒฝ ๋‘๊ป˜๋ฅผ 0 ์œผ๋กœ ๋‘๋ฉด ํ†ต์งœ๋‹ค. 0 ๋ณด๋‹ค ํฌ๋ฉด ๊ทธ๋งŒํผ ์•ˆ์œผ๋กœ ๋“ค์–ด์˜จ ํ…Œ๊ฐ€ ์ƒ๊ธฐ๊ณ , ๊ทธ๊ฒƒ์ด\n * ํŠธ๋ ˆ์ด ยท ํ† ํŠธ ยท ํ†ต ยท ์ผ€์ด์Šค๊ฐ€ ๋˜๋Š” ์ž๋ฆฌ๋‹ค. ๋ฐ”๋‹ฅ์€ ๋น„์›Œ ๋‘๋ฉด ๋ฒฝ๊ณผ ๊ฐ™๊ณ , 0 ์œผ๋กœ ๋‘๋ฉด\n * ์œ„์•„๋ž˜๊ฐ€ ๋‹ค ๋šซ๋ฆฐ ํ…Œ๋‘๋ฆฌ๊ฐ€ ๋œ๋‹ค.\n */\n private renderExtruded(part: FigurePart) {\n const hollow = part.shape?.hollow\n const wall = hollow?.wall ?? 0\n\n const reshape = (over: Record<string, unknown>) =>\n this.put({ shape: { ...(part.shape ?? {}), ...over } })\n\n return html`\n <div inline-field>\n <label>${i18next.t('figure.label.corner-round')}</label>\n ${this.number('', part.shape?.round ?? 0, value => reshape({ round: value }))}\n </div>\n <div inline-field>\n <label>${i18next.t('figure.label.hollow-wall')}</label>\n ${this.number('', wall, value =>\n reshape({ hollow: value > 0 ? { ...(hollow ?? {}), wall: value } : undefined })\n )}\n </div>\n ${wall > 0\n ? html`\n <div inline-field>\n <label>${i18next.t('figure.label.hollow-floor')}</label>\n ${this.number('', hollow?.floor ?? wall, value => reshape({ hollow: { ...hollow, wall, floor: value } }))}\n </div>\n `\n : nothing}\n `\n }\n\n /**\n * ๋ถ„ํ•  ์ˆ˜ โ€” ๋ชจ์–‘๊ณผ ๋ฌด๊ฒŒ๋ฅผ ํ•จ๊ป˜ ๊ณ ๋ฅธ๋‹ค.\n *\n * ์‚ผ๊ฐํ˜• ์ˆ˜๋Š” ํ™”๋ฉด์ด ์…ˆํ•˜์ง€ ์•Š๋Š”๋‹ค. `trianglesOf` ์— ๊ทธ ๋ถ„ํ•  ์ˆ˜๋ฅผ ๊ฐ€์ง„ ๋ถ€ํ’ˆ์„ ์ฃผ๊ณ \n * ๋ฌผ์–ด๋ณธ๋‹ค โ€” ํ™”๋ฉด์ด ์ œ ๋‚˜๋ฆ„์˜ ๊ณต์‹์„ ๋“ค๋ฉด figure-model ์ด ๊ทœ์น™์„ ๋ฐ”๊ฟ”๋„ ํ™”๋ฉด๋งŒ\n * ์˜› ๋‹ต์„ ๊ณ„์† ๋‚ธ๋‹ค.\n */\n /**\n * ์›ํ†ต์„ ์›ํ†ต์œผ๋กœ ๋‘˜๊นŒ โ€” **๊ณ ๋ฅด๋Š” ๊ฐ’์ด๊ณ , ๊ฐ’์„ ์น˜๋ฅธ๋‹ค.**\n *\n * ์ธ์Šคํ„ด์Šค๊ฐ€ ์ถ•๋งˆ๋‹ค ๋‹ค๋ฅธ ๋ฐฐ์œจ์„ ๋ฐ›์œผ๋ฉด ์›๊ธฐ๋‘ฅ์ด ํƒ€์› ๊ธฐ๋‘ฅ์ด ๋œ๋‹ค. ์ง€ํ‚ค๋ ค๋ฉด ์ œ ๋ณ€ํ™˜์ด\n * ์žˆ์–ด์•ผ ํ•˜๊ณ , ํ•ฉ์นœ ํ˜•์ƒ์€ ๋ณ€ํ™˜์„ ํ•˜๋‚˜๋งŒ ๋ฐ›์œผ๋ฏ€๋กœ ์ง€ํ‚ค๋Š” ๊ณก๋ฉด ๋ถ€ํ’ˆ ํ•˜๋‚˜๊ฐ€ draw call\n * ํ•˜๋‚˜๋‹ค. ์ €์ž‘์ž๊ฐ€ ๊ทธ ๋Œ€๊ฐ€๋ฅผ ๋ชจ๋ฅด๊ณ  ๊ณ ๋ฅด๋ฉด ์•ˆ ๋˜๋ฏ€๋กœ ๊ทธ ์ž๋ฆฌ์— ์ ๋Š”๋‹ค.\n */\n private renderKeepRound(part: FigurePart) {\n const on = part.keepRound !== false\n\n return html`\n <div field>\n <label>${i18next.t('figure.label.keep-round')}</label>\n <div choices>\n <button choice ?on=${on} @click=${() => this.put({ keepRound: undefined })}>\n <b>${i18next.t('figure.text.keep-round-on')}</b>\n <small>${i18next.t('figure.text.keep-round-cost')}</small>\n </button>\n <button choice ?on=${!on} @click=${() => this.put({ keepRound: false })}>\n <b>${i18next.t('figure.text.keep-round-off')}</b>\n <small>${i18next.t('figure.text.keep-round-merged')}</small>\n </button>\n </div>\n </div>\n `\n }\n\n private renderSegments(part: FigurePart) {\n const current = part.segments ?? SEGMENT_PRESETS[1]\n const common = SEGMENT_PRESETS.slice(0, 4)\n const advanced = SEGMENT_PRESETS.slice(4)\n\n return html`\n <div field>\n <label>${i18next.t('figure.label.segments')}</label>\n <div segments>\n ${common.map(preset => {\n const triangles = trianglesOf({ ...part, segments: preset })\n return html`\n <button seg ?on=${current === preset} @click=${() => this.put({ segments: preset })}>\n ${this.silhouette(preset)}\n <b>${preset}</b>\n <small>${i18next.t('figure.text.n-triangles', { count: triangles })}</small>\n </button>\n `\n })}\n </div>\n\n <details free ?open=${advanced.includes(current)}>\n <summary>${i18next.t('figure.text.more-segment-options')}</summary>\n <div presets>\n ${advanced.map(preset => html`\n <button ?on=${current === preset} @click=${() => this.put({ segments: preset })}>${preset}</button>\n `)}\n </div>\n </details>\n </div>\n `\n }\n\n /**\n * ๋ถ„ํ•  ์ˆ˜์˜ ์‹ค๋ฃจ์—ฃ.\n *\n * ๊ณก๋ฉด ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ๋ฅผ ์œ„์—์„œ ๋ณธ ์œค๊ณฝ์ด ์ •ํ™•ํžˆ ์ •n๊ฐํ˜•์ด๋‹ค โ€” ์›๊ธฐ๋‘ฅ์˜ ๋‹จ๋ฉด๋„, ๊ตฌ์˜\n * ์ ๋„๋„. ๊ทธ๋ฆผ์„ ์ง€์–ด๋‚ด๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์‹ค์ œ๋กœ ๋งŒ๋“ค์–ด์ง€๋Š” ๋ชจ์–‘์ด๋‹ค.\n */\n private silhouette(segments: number) {\n const points: string[] = []\n for (let i = 0; i < segments; i++) {\n // ๊ผญ์ง“์  ํ•˜๋‚˜๊ฐ€ ์œ„๋กœ ์˜ค๊ฒŒ -90๋„์—์„œ ์‹œ์ž‘ํ•œ๋‹ค\n const angle = -Math.PI / 2 + (i * 2 * Math.PI) / segments\n points.push(`${(16 + 13 * Math.cos(angle)).toFixed(2)},${(16 + 13 * Math.sin(angle)).toFixed(2)}`)\n }\n\n return svg`\n <svg viewBox=\"0 0 32 32\" aria-hidden=\"true\">\n <polygon points=${points.join(' ')}></polygon>\n </svg>\n `\n }\n\n /** ๊ฒฌ๋ณธ ํ•œ ์ค„. ๋ฌด๋ฆฌ๋งˆ๋‹ค ๋ถ€๋ฅธ๋‹ค. */\n private palettePurpose(token?: string) {\n const purposes: Record<string, string> = {\n 'palette.primary': 'primary',\n 'palette.accent': 'accent',\n 'palette.neutral': 'neutral',\n 'palette.dark': 'dark',\n 'palette.light': 'light',\n 'palette.surface': 'surface',\n 'palette.status-danger': 'danger',\n 'palette.status-warning': 'warning',\n 'palette.status-info': 'info',\n 'palette.status-success': 'success'\n }\n\n return i18next.t(`figure.label.palette-purpose-${purposes[token ?? ''] ?? 'registered'}`)\n }\n\n private swatches(entries: [string, string][], chosen?: string) {\n return entries.map(\n ([token, color]) => {\n const purpose = this.palettePurpose(token)\n return html`\n <button\n swatch\n ?on=${token === chosen}\n aria-label=${purpose}\n title=${purpose}\n style=\"--swatch:${color}\"\n @click=${() => this.putMaterial({ token })}\n ></button>\n `\n }\n )\n }\n\n private renderMaterial(part: FigurePart) {\n const material = part.material ?? {}\n const palette = activePalette() as Record<string, string>\n\n /*\n ๋‘ ๋ฌด๋ฆฌ๋กœ ๋‚˜๋ˆ  ๋ณด์ธ๋‹ค โ€” **์น ํ•œ ์ƒ‰**๊ณผ **์ผœ์ง„ ์ƒ‰**.\n\n `palette.status-*` ๋Š” ๋žจํ”„ ยท ํ‘œ์‹œ๋“ฑ์— ์“ฐ๋ผ๊ณ  ์žˆ๋Š” ์ƒ‰์ด๋‹ค. ํ•œ ์ค„์— ์„ž์–ด ๋‘๋ฉด\n `accent`(์ฃผํ™ฉ)์™€ `status-warning`(์ฃผํ™ฉ)์ด ๋‚˜๋ž€ํžˆ ๋†“์—ฌ ๋ฌด์—‡์ด ๋ฌด์—‡์ธ์ง€ ์•Œ ์ˆ˜\n ์—†๋‹ค. ๊ฐ’์„ ๋น„ํ‹€์–ด ๋ฒŒ๋ฆฌ๋Š” ๋Œ€์‹  **๊ณ ๋ฅด๋Š” ์ž๋ฆฌ์—์„œ ๊ฒฝ๊ณ„๋ฅผ ๊ธ‹๋Š”๋‹ค.**\n */\n const entries = Object.entries(palette)\n const painted = entries.filter(([token]) => !token.startsWith('palette.status-'))\n const lit = entries.filter(([token]) => token.startsWith('palette.status-'))\n\n /** ์ž์ฒด๋ฐœ๊ด‘. ์—†์œผ๋ฉด ์•ˆ ๋น›๋‚˜๋Š” ๋ถ€ํ’ˆ์ด๋‹ค. */\n const glow = material.emissive\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.part-material')}</h3>\n\n <div field>\n <label>${i18next.t('figure.label.palette-role')}</label>\n <div swatches>\n ${this.swatches(painted, material.token)}\n </div>\n ${lit.length\n ? html`\n <label group>${i18next.t('figure.label.status-colors')}</label>\n <div swatches>\n ${this.swatches(lit, material.token)}\n </div>\n `\n : ''}\n <div palette-meaning>\n <b>${material.token ? this.palettePurpose(material.token) : i18next.t('figure.label.no-color-chosen')}</b>\n <small>${i18next.t('figure.text.palette-purpose-explained')}</small>\n </div>\n </div>\n\n <div field>\n <label>${i18next.t('figure.label.preset')}</label>\n <select\n @change=${(e: Event) => {\n const value = (e.target as HTMLSelectElement).value\n this.putMaterial({ preset: (value || undefined) as MaterialPreset | undefined })\n }}\n >\n <option value=\"\" ?selected=${!material.preset}>${i18next.t('figure.label.none')}</option>\n ${MATERIAL_PRESETS.map(\n preset => html`\n <option value=${preset} ?selected=${preset === material.preset}>\n ${i18next.t('figure.label.preset-' + preset)}\n </option>\n `\n )}\n </select>\n </div>\n\n <!-- ๊ฐ’์ด ์—†์œผ๋ฉด ๊ฐ์ง€๊ฒŒ ๊ทธ๋ฆฐ๋‹ค โ€” ํ˜•์‹์ด ๊ทธ๋ ‡๊ฒŒ ๋ชป ๋ฐ•์•˜๋‹ค. ์ฒดํฌ์ƒ์ž๋„ ๊ทธ๋Œ€๋กœ ๋ณด์ธ๋‹ค -->\n <label toggle>\n <input\n type=\"checkbox\"\n .checked=${material.flatShading ?? true}\n @change=${(e: Event) => this.putMaterial({ flatShading: (e.target as HTMLInputElement).checked })}\n />\n ${i18next.t('figure.label.flat-shading')}\n </label>\n <label toggle>\n <input\n type=\"checkbox\"\n .checked=${!!material.transparent}\n @change=${(e: Event) => this.putMaterial({ transparent: (e.target as HTMLInputElement).checked })}\n />\n ${i18next.t('figure.label.transparent')}\n </label>\n\n <div field>\n <label>${i18next.t('figure.label.emissive')}${this.help('figure.text.emissive-explained')}</label>\n\n <div slider>\n <input\n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n .value=${String(glow?.intensity ?? 0)}\n @input=${(e: Event) => this.putEmissive(Number((e.target as HTMLInputElement).value))}\n />\n <output>${(glow?.intensity ?? 0).toFixed(2)}</output>\n </div>\n </div>\n\n ${glow\n ? html`\n <div field>\n <label>${i18next.t('figure.label.emissive-color')}</label>\n <div swatches>\n <button\n swatch\n same\n ?on=${!glow.token}\n title=${i18next.t('figure.label.same-as-off')}\n style=\"--swatch:${(material.token && palette[material.token]) || palette['palette.neutral']}\"\n @click=${() => this.putMaterial({ emissive: { ...glow, token: undefined } })}\n ></button>\n ${lit.map(\n ([token, color]) => html`\n <button\n swatch\n ?on=${token === glow.token}\n title=${token}\n style=\"--swatch:${color}\"\n @click=${() => this.putMaterial({ emissive: { ...glow, token } })}\n ></button>\n `\n )}\n </div>\n <span token>${glow.token ?? i18next.t('figure.label.same-as-off')}</span>\n </div>\n\n <label toggle>\n <input\n type=\"checkbox\"\n .checked=${!!glow.on}\n @change=${(e: Event) =>\n this.putMaterial({ emissive: { ...glow, on: (e.target as HTMLInputElement).checked } })}\n />\n ${i18next.t('figure.label.on-by-default')}\n </label>\n ${this.help('figure.text.on-by-default-explained')}\n `\n : ''}\n\n </section>\n `\n }\n\n /**\n * ์ธ์Šคํ„ด์Šค ํฌ๊ธฐ๊ฐ€ ๋ฐ”๋€” ๋•Œ ์ด ๋ถ€ํ’ˆ์ด ์–ด๋–ป๊ฒŒ ๋ณ€ํ•˜๋‚˜.\n *\n * ## ๋Š˜์–ด๋‚˜๋Š” ์ถ•์€ ์•„์ง ๋ชป ๋ณด์—ฌ ์ค€๋‹ค\n *\n * `stretch` ๋Š” ํ˜•์‹์— ์ถ•์„ ์ ๋Š” ์ž๋ฆฌ๊ฐ€ ์—†์–ด์„œ ๊ทธ๋ฆฌ๋Š” ์ชฝ์ด **๊ฐ€์žฅ ๊ธธ๊ฒŒ ๋ป—์€ ์ถ•**์œผ๋กœ\n * ์ •ํ•œ๋‹ค. ๊ทธ ๋‹ต์„ ํ™”๋ฉด์— ์ ์–ด ์ฃผ๋ ค๋ฉด ๊ทœ์น™์„ ๊ฐ€์ง„ ์ชฝ์— ๋ฌผ์–ด์•ผ ํ•˜๋Š”๋ฐ, ๊ทธ ํ•จ์ˆ˜\n * (`stretchAxisOf` ยท `stretchAxis`)๊ฐ€ ์•„์ง ๋ฐฐํฌ๋œ ํŒ์— ์—†๋‹ค.\n *\n * ํ™”๋ฉด์ด ์ œ ๋‚˜๋ฆ„๋Œ€๋กœ ๊ณ„์‚ฐํ•˜์ง€ ์•Š๋Š”๋‹ค. ๊ทœ์น™์ด ๋‘ ๋ฒŒ์ด ๋˜๋ฉด ๋ณด์ด๋Š” ์ถ•๊ณผ ์‹ค์ œ๋กœ ๋Š˜์–ด๋‚˜๋Š”\n * ์ถ•์ด ๊ฐˆ๋ฆฌ๊ณ , ๊ทธ ์–ด๊ธ‹๋‚จ์€ ํ™”๋ฉด์„ ๋ฏฟ๊ฒŒ ๋งŒ๋“  ๋‹ค์Œ์— ๋“œ๋Ÿฌ๋‚œ๋‹ค. ๋ฐฐํฌ๋˜๋ฉด ์ž‡๋Š”๋‹ค.\n *\n * ## ๊ฐ’์ด ์žˆ๋Š” ๊ฒƒ์„ ๋ฐํžŒ๋‹ค\n *\n * `scale` ์ด ์•„๋‹Œ ๋ถ€ํ’ˆ์€ ํ•ฉ์ณ ๊ทธ๋ฆด ์ˆ˜ ์—†์–ด draw call ์„ ํ•˜๋‚˜ ๋” ์“ด๋‹ค. ๊ทธ ๋น„์šฉ์ด\n * ์„ฑ์ˆ™๋„์˜ ๋ฌถ์Œ ์ˆ˜์— ๊ทธ๋Œ€๋กœ ์žกํžŒ๋‹ค. ๊ณ ๋ฅด๋Š” ์ž๋ฆฌ์—์„œ ๋ฏธ๋ฆฌ ๋งํ•ด ์ค€๋‹ค.\n */\n private renderBehaviour(part: FigurePart) {\n const sizing = part.sizing ?? 'scale'\n const repeat = part.repeat ?? { axis: 'x' as Axis, pitch: 0 }\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.sizing-rule')}${this.help('figure.text.sizing-' + sizing + '-explained')}</h3>\n <div sizing-choices>\n ${SIZING_RULES.map(\n rule => html`\n <button sizing-choice ?on=${rule === sizing} @click=${() => this.put({ sizing: rule })}>\n <b>${i18next.t('figure.label.sizing-' + rule)}</b>\n <small>${i18next.t('figure.text.sizing-' + rule + '-explained')}</small>\n </button>\n `\n )}\n </div>\n ${sizing === 'scale'\n ? nothing\n : html`<p cost>${i18next.t('figure.text.sizing-costs-one-draw-call')}</p>`}\n\n ${this.renderAnchors(part)}\n\n ${sizing === 'repeat'\n ? html`\n <div inline-field>\n <label>${i18next.t('figure.label.repeat-axis')}</label>\n <select\n @change=${(e: Event) =>\n this.put({ repeat: { ...repeat, axis: (e.target as HTMLSelectElement).value as Axis } })}\n >\n ${(['x', 'y', 'z'] as const).map(\n axis => html`<option value=${axis} ?selected=${axis === repeat.axis}>${axis}</option>`\n )}\n </select>\n </div>\n <div inline-field>\n <label>${i18next.t('figure.label.repeat-pitch')}${this.helpButton('figure.text.repeat-pitch-explained')}</label>\n ${this.number('', repeat.pitch, value => this.put({ repeat: { ...repeat, pitch: value } }), 1)}\n ${this.helpHint('figure.text.repeat-pitch-explained')}\n </div>\n ${this.renderRepeatCount(part)}\n `\n : nothing}\n </section>\n `\n }\n\n /**\n * โ”€โ”€ ๋ช‡ ๊ฐœ๊ฐ€ ๋˜๋‚˜ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n *\n * ์ €์ž‘ ํ™”๋ฉด์€ ์ถ•๊ณผ ํ”ผ์น˜๋งŒ ๋ฐ›๊ณ  ์žˆ์—ˆ๋‹ค. ํ˜•์‹์ด ๊ฐ€์ง„ ๋ฐ˜๋ณต ์„ค์ •์ด ๊ทธ ๋‘˜๋ฟ์ด๋ฏ€๋กœ ํŽธ์ง‘ํ•  ๊ฒƒ์€\n * ๋‹ค ์žˆ์—ˆ๋Š”๋ฐ, **๊ฒฐ๊ณผ์ธ ๊ฐœ์ˆ˜๋ฅผ ์–ด๋””์—๋„ ํ‘œ์‹œํ•˜์ง€ ์•Š์•˜๋‹ค.** ํ”ผ์น˜ 300 ์„ ์ ์€ ์ €์ž‘์ž๊ฐ€ ๋ช‡ ๊ฐœ๊ฐ€\n * ๋˜๋Š”์ง€ ์•Œ๋ ค๋ฉด ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ฅผ ์„ธ์–ด์•ผ ํ–ˆ๋‹ค.\n *\n * ๊ฐœ์ˆ˜๋Š” ๊ทธ๋ฆฌ๋Š” ์ชฝ์ด ์“ฐ๋Š” `repeatPlan` ์„ ๊ทธ๋Œ€๋กœ ๋ถˆ๋Ÿฌ ์–ป๋Š”๋‹ค. ์—ฌ๊ธฐ์„œ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜๋ฉด ํ™”๋ฉด์ด\n * ๋งํ•˜๋Š” ๊ฐœ์ˆ˜์™€ ์‹ค์ œ๋กœ ๊ทธ๋ ค์ง€๋Š” ๊ฐœ์ˆ˜๊ฐ€ ๋‹ฌ๋ผ์ง„๋‹ค.\n *\n * ## ๋‘ ๊ฐ€์ง€ ๋ฐ˜๋ณต์ด ์žˆ๋‹ค\n *\n * ์ปจ๋ฒ ์ด์–ด์˜ ๋กค๋Ÿฌ๋Š” ๊ธธ์–ด์ง€๋ฉด **๊ฐœ์ˆ˜๊ฐ€ ๋Š˜๊ณ ** ํ•œ ์นธ ๊ฐ„๊ฒฉ์€ ๊ทธ๋Œ€๋กœ๋‹ค. ์…€ํŠธ๋ ˆ์ด์˜ ์…€์€ ์ปค์ง€๋ฉด\n * **์…€์ด ์ปค์ง€๊ณ ** ๊ฐœ์ˆ˜๋Š” ๊ทธ๋Œ€๋กœ๋‹ค โ€” ๋ช‡ ์…€์งœ๋ฆฌ ํŠธ๋ ˆ์ด๋ƒ๋Š” ํ™”๋ฉด ํฌ๊ธฐ์™€ ๋ฌด๊ด€ํ•˜๋‹ค. ๊ทธ ๊ฐˆ๋ฆผ์„\n * ์ด ์ถ•์˜ anchor ๊ฐ€ ์ •ํ•˜๋Š”๋ฐ ํ™”๋ฉด์—๋Š” ๊ทธ ๋ง์ด ์—†์—ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์–ด๋А ์ชฝ์ธ์ง€ ํ•จ๊ป˜ ์ ๋Š”๋‹ค.\n */\n private renderRepeatCount(part: FigurePart) {\n const draft = this.draft\n if (!draft) return nothing\n\n const base = { x: draft.width, y: draft.depth, z: draft.height }\n const plan = repeatPlanOfPart(part, { x: 1, y: 1, z: 1 }, base)\n if (!plan) return nothing\n\n const grows = anchorOfPart(part, base, plan.axis) !== 'scale'\n\n return html`\n <div field>\n <label>${i18next.t('figure.label.repeat-count')}</label>\n <p quiet>\n ${i18next.t('figure.text.repeat-count-now', { count: plan.count })}\n ${plan.count >= REPEAT_LIMIT\n ? html`<br />${i18next.t('figure.text.repeat-count-capped', { limit: REPEAT_LIMIT })}`\n : ''}\n <br />${i18next.t(grows ? 'figure.text.repeat-grows-with-instance' : 'figure.text.repeat-keeps-count')}\n </p>\n </div>\n `\n }\n\n /**\n * โ”€โ”€ ์–ด๋А ๋ฉด์„ ๋ถ™์žก๋‚˜ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n *\n * **์ด ์ž๋ฆฌ๊ฐ€ ์—†์—ˆ๋‹ค.** ํ˜•์‹์€ ์ถ•๋งˆ๋‹ค `anchor` ๋ฅผ ์ง€๊ณ  ๋‹ค๋‹ˆ๊ณ (`figure-source.ts` ๊ฐ€ ์™•๋ณต์‹œํ‚จ๋‹ค),\n * ๋ฐœํ–‰ ๊ฒŒ์ดํŠธ๋Š” ใ€Œvalve-wheel ์˜ anchor.z ๋ฅผ max ๋กœ ๋‘๋ผใ€๊ณ  ์‚ฌ์œ ๊นŒ์ง€ ๋งํ•˜๋Š”๋ฐ, ์ €์ž‘๋ฉด์—๋Š” ๊ทธ\n * ๊ฐ’์„ ๋ฐ”๊ฟ€ ์ž๋ฆฌ๊ฐ€ ์—†์—ˆ๋‹ค โ€” ๊ณ ์น˜๋ผ๋Š” ๋ง๋งŒ ์žˆ๊ณ  ๊ณ ์น  ๋ฌธ์ด ์—†์—ˆ๋‹ค.\n *\n * ## ใ€Œ์ž๋™ใ€์ด ๊ธฐ๋ณธ์ด๋‹ค\n *\n * ํ˜•์‹์—์„œ `anchor` ๋Š” ์ ์ง€ ์•Š์•„๋„ ๋œ๋‹ค. ์•ˆ ์ ์œผ๋ฉด **๊ฐ€๊นŒ์šด ๋ฉด**์„ ๋ถ™์žก๊ณ , ํ‘œ๋ณธ ์—ด๋„ท ์ค‘ ์–ด๋А\n * ๊ฒƒ๋„ ์ด ๊ฐ’์„ ์ ์ง€ ์•Š๊ณ  ์ œ๋Œ€๋กœ ์„ ๋‹ค. ๊ทธ๋ž˜์„œ ์ถ•๋งˆ๋‹ค ์ฒซ ํ•ญ๋ชฉ์ด ใ€Œ์ž๋™ใ€์ด๊ณ , ์ง€๊ธˆ ์ž๋™์ด ๋ฌด์—‡์œผ๋กœ\n * ์ฝํžˆ๋Š”์ง€๋ฅผ **ํ•จ๊ป˜ ๋ณด์—ฌ ์ค€๋‹ค** โ€” ๊ทธ๊ฒƒ์„ ๋ชจ๋ฅด๋ฉด ๋ฌด์—‡์„ ๋ฐ”๊พธ๋Š”์ง€ ๋ชจ๋ฅธ ์ฑ„ ๊ณ ๋ฅด๊ฒŒ ๋œ๋‹ค.\n *\n * ์ž๋™์ด ๋ฌด์—‡์ธ์ง€๋Š” ํ˜•์‹์—๊ฒŒ ๋ฌป๋Š”๋‹ค(`anchorOfPart`). ์—ฌ๊ธฐ์„œ ใ€Œ์œ„ ์ ˆ๋ฐ˜์ด๋ฉด maxใ€๋ฅผ ๋‹ค์‹œ ์„ธ๋ฉด\n * ํ™”๋ฉด์ด ๋งํ•˜๋Š” ๋ฉด๊ณผ ์‹ค์ œ๋กœ ๊ทธ๋ ค์ง€๋Š” ๋ฉด์ด ๊ฐˆ๋ฆฐ๋‹ค.\n *\n * ## `scale` ์ธ ๋ถ€ํ’ˆ์—๋„ ๋ณด์—ฌ ์ค€๋‹ค\n *\n * ์ฒ˜์Œ์—๋Š” ๊ฐ์ท„๋‹ค โ€” ํ˜•์‹ ์ฃผ์„์— ใ€Œ`sizing` ์ด `scale` ์ธ ๋ถ€ํ’ˆ์—๋Š” ๋œป์ด ์—†๋‹คใ€๊ณ  ์ ํ˜€ ์žˆ์–ด์„œ๋‹ค.\n * **๊ทธ ๋ฌธ์žฅ์€ ๊ธฐ๋ณธ๊ฐ’์— ๋Œ€ํ•œ ๊ฒƒ์ด๋‹ค.** `anchorOf` ๋Š” ์ ํžŒ ๊ฐ’์„ ๊ฐ€์žฅ ๋จผ์ € ๋ณด๊ณ (`if (said) return\n * said`), ๊ทธ ๋’ค์—์•ผ `sizing` ์„ ๋ณธ๋‹ค. ์ฆ‰ `scale` ๋ถ€ํ’ˆ์—๋„ ๋ฉด์„ ์ ์œผ๋ฉด ๊ทธ๊ฒƒ์ด ์ด๊ธด๋‹ค.\n *\n * ๊ฐ์ถฐ ๋‘๋ฉด ์–ด๊ธ‹๋‚จ์ด ๋‚œ๋‹ค: ๋ฐœํ–‰ ๊ฒŒ์ดํŠธ๊ฐ€ ๋ง‰๋Š” MIXER ์˜ `valve-wheel` ์ด `scale` ๋ถ€ํ’ˆ์ด๊ณ ,\n * ๊ฒŒ์ดํŠธ์˜ ์‚ฌ์œ ๋Š” ใ€Œ๊ทธ ๋ถ€ํ’ˆ์˜ anchor.z ๋ฅผ max ๋กœ ๋‘๋ผใ€๋‹ค. ๊ณ ์น˜๋ผ๋Š” ์ž๋ฆฌ์— ๋ฌธ์„ ๋‹ซ์•„ ๋‘” ์…ˆ์ด์—ˆ๋‹ค.\n *\n * ๋Œ€์‹  `scale` ์ผ ๋•Œ๋Š” ์ž๋™์ด ๋ฌด์—‡์ธ์ง€๊ฐ€ ใ€Œํ•จ๊ป˜ ์ปค์ง„๋‹คใ€๋กœ ๋ณด์ด๋ฏ€๋กœ, ์ €์ž‘์ž๊ฐ€ ๊ทธ๊ฒƒ์„ ๋ฐ”๊พธ๋Š”\n * ๊ฒƒ์ž„์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.\n */\n /**\n * โ”€โ”€ ๋„์›€๋ง์€ ์ž๋ฆฌ๋ฅผ ๋จน์ง€ ์•Š๋Š”๋‹ค โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n *\n * ์„ค๋ช… ๋ฌธ๋‹จ์ด ์—ด ์ค„ ์žˆ์—ˆ๊ณ  ๊ทธ ์ค„๋“ค์ด ํŒจ๋„ ๋†’์ด์˜ ์ƒ๋‹น ๋ถ€๋ถ„์ด์—ˆ๋‹ค. ์†์„ฑ์€ ์•ž์œผ๋กœ ๋” ๋Š˜์–ด๋‚œ๋‹ค\n * (๋Šฅ๋ ฅ ยท ํฌํŠธ ยท ์• ๋‹ˆ๋ฉ”์ด์…˜ ยท ๊ธฐ์ค€์ •๋ณด) โ€” ๋Š˜ ๋ณด์ด๋Š” ์„ค๋ช…์€ ๊ทธ ์ž๋ฆฌ๋ฅผ ๋จผ์ € ๋จน๋Š”๋‹ค.\n *\n * ๊ทธ๋ž˜์„œ ๋ฌผ์Œํ‘œ๋กœ ์ ‘๋Š”๋‹ค. **์ง€์šฐ์ง€ ์•Š๋Š”๋‹ค** โ€” ๊ทธ ๋ฌธ์žฅ๋“ค์€ ใ€Œ์ด๊ฑธ ๊ณ ๋ฅด๋ฉด ๋ฌด์—‡์ด ๋‹ฌ๋ผ์ง€๋‚˜ใ€๋ฅผ\n * ๋งํ•˜๋Š” ๊ฒƒ์ด๊ณ , ์—†์œผ๋ฉด ๋‹ซํžŒ ๋ชฉ๋ก์„ ๊ณ ๋ฅผ ์ˆ˜ ์—†๋‹ค. ํ•œ ๋ฒˆ ์ฝ์œผ๋ฉด ๋˜๋Š” ๊ฒƒ์ด๋ผ ์ ‘์–ด ๋‘๋Š” ๊ฒƒ์ด ๋งž๋‹ค.\n *\n * ํŽธ ๊ฒƒ์€ **๋ถ€ํ’ˆ์„ ๋ฐ”๊ฟ”๋„ ๊ทธ๋Œ€๋กœ ๋‘”๋‹ค**(`opened` ๋Š” ๋ถ€ํ’ˆ์— ๋”ธ๋ฆฐ ์ƒํƒœ๊ฐ€ ์•„๋‹ˆ๋‹ค). ๊ฐ™์€ ๊ฒƒ์„\n * ๊ณ„์† ๊ณ ์น˜๋Š” ์‚ฌ๋žŒ์ด ๋งค๋ฒˆ ๋‹ค์‹œ ํŽด์•ผ ํ•˜๋ฉด ์ ‘์€ ๊ฒƒ์ด ๋˜๋ ˆ ๋ฐฉํ•ด๊ฐ€ ๋œ๋‹ค.\n */\n private help(key: string) {\n return html`${this.helpButton(key)}${this.helpHint(key)}`\n }\n\n private helpButton(key: string) {\n const shown = this.opened.has(key)\n\n return html`\n <button\n help\n aria-label=${i18next.t('figure.label.help')}\n aria-expanded=${shown ? 'true' : 'false'}\n @click=${() => {\n shown ? this.opened.delete(key) : this.opened.add(key)\n this.requestUpdate()\n }}\n >\n <md-icon>${shown ? 'help' : 'help_outline'}</md-icon>\n </button>\n `\n }\n\n private helpHint(key: string) {\n return this.opened.has(key) ? html`<p hint>${i18next.t(key)}</p>` : nothing\n }\n\n private renderAnchors(part: FigurePart) {\n /*\n The scene draft stores the box height as depth, so format y is draft.depth and z is draft.height.\n This used to pass them swapped, and every automatic anchor still came out the same: the\n nearest-face rule reads the sign of a centred position, which does not depend on the box size.\n It is fixed so the next rule that does read the box does not inherit the mistake.\n */\n const base = this.draft\n ? { x: this.draft.width, y: this.draft.depth, z: this.draft.height }\n : { x: 0, y: 0, z: 0 }\n const nameOf = (rule: string, axis: Axis) =>\n `${i18next.t(rule === 'min' || rule === 'max' ? `figure.label.anchor-${rule}-${axis}` : `figure.label.anchor-${rule}`)} (${rule})`\n const setAnchor = (axis: Axis, rule?: AnchorRule) => {\n const anchor = { ...(part.anchor ?? {}) }\n /* ใ€Œ์ž๋™ใ€์€ ์นธ์„ ์ง€์šฐ๋Š” ๊ฒƒ์ด๋‹ค โ€” ๋นˆ ๊ฐ’์„ ๋„ฃ์–ด ๋‘๋ฉด ํ˜•์‹์ด ๊ทธ๊ฒƒ์„ ๊ฐ’์œผ๋กœ ์ฝ๋Š”๋‹ค. */\n if (rule) anchor[axis] = rule\n else delete anchor[axis]\n this.put({ anchor: Object.keys(anchor).length ? anchor : undefined })\n }\n const shortNameOf = (rule: AnchorRule | 'auto', axis: Axis) => {\n if (rule === 'auto') return i18next.t('figure.label.anchor-choice-auto')\n if (rule === 'min' || rule === 'max') return i18next.t(`figure.label.anchor-choice-${rule}-${axis}`)\n return i18next.t(`figure.label.anchor-choice-${rule}`)\n }\n\n return html`\n <div field>\n <!-- ์ €์žฅ ํ‚ค(anchor)๋Š” ๋‚จ๊ธฐ๋˜, ์‚ฌ์šฉ์ž๋Š” ์ถ•๋งˆ๋‹ค ์–ด๋А ๋ฉด์„ ๊ธฐ์ค€์œผ๋กœ ์‚ผ๋Š”์ง€ ์ฝ๋Š”๋‹ค. -->\n <label>${i18next.t('figure.label.anchor')} (anchor)${this.help('figure.text.anchor-explained')}</label>\n <div anchor-rows>\n ${(['x', 'y', 'z'] as const).map(axis => {\n const said = part.anchor?.[axis]\n const auto = anchorOfPart(part, base, axis)\n\n /*\n **๋ฉด ์ด๋ฆ„์€ ์ถ•๋งˆ๋‹ค ๋‹ค๋ฅด๋‹ค.** ์ฒ˜์Œ์—๋Š” min ์„ ใ€Œ์•„๋ž˜ยท์™ผ์ชฝยท๋’ค ๋ฉดใ€์œผ๋กœ ํ•œ ์ค„์— ๋‹ค ์ ์—ˆ๋Š”๋ฐ,\n x ์ค„์—์„œ ใ€Œ์•„๋ž˜ใ€์™€ ใ€Œ๋’คใ€๋Š” ๊ด€๊ณ„๊ฐ€ ์—†์–ด ์ฝ๋Š” ์‚ฌ๋žŒ์ด ๋ฌด์—‡์„ ๊ณ ๋ฅด๋Š”์ง€ ๋ชฐ๋ž๋‹ค.\n\n ๊ทธ๋ฆฌ๊ณ  ์ด๋ฆ„์”จ๊ฐ€ ์•„๋‹ˆ๋ผ **๋™์ž‘**์œผ๋กœ ์ ๋Š”๋‹ค โ€” ใ€Œ์˜ค๋ฅธ์ชฝ ๋ฉดใ€์ด ์•„๋‹ˆ๋ผ ใ€Œ์˜ค๋ฅธ์ชฝ ๋ฉด์— ๋ถ™์–ด\n ์žˆ๋Š”๋‹คใ€๋‹ค. ใ€Œanchor.x ๋ฅผ max ๋กœ ๋‘”๋‹คใ€๊ฐ€ ๋ฌด์Šจ ๋œป์ธ์ง€ ๋ชจ๋ฅด๊ฒ ๋‹ค๋Š” ๋ง์ด ๊ทธ ์ž๋ฆฌ์—์„œ ๋‚˜์™”๋‹ค.\n */\n /*\n **๊ฐ’ ์ด๋ฆ„์„ ํ•จ๊ป˜ ๋ณด์ธ๋‹ค.** ๋™์ž‘๋งŒ ์ ์—ˆ๋”๋‹ˆ(ใ€Œ์˜ค๋ฅธ์ชฝ ๋ฉด์— ๋ถ™์–ด ์žˆ๋Š”๋‹คยป) ๋ฐœํ–‰ ๊ฒŒ์ดํŠธ๊ฐ€\n ใ€Œanchor.x ๋ฅผ max ๋กœ ๋‘๋ผใ€๊ณ  ๋งํ•  ๋•Œ ํ™”๋ฉด์—์„œ ๊ทธ ๋‚ฑ๋ง์„ ์ฐพ์„ ์ˆ˜ ์—†์—ˆ๋‹ค โ€” ์‚ฌ์šฉ์ž๊ฐ€\n ๊ทธ ์ž๋ฆฌ์—์„œ ์ง€์ ํ–ˆ๋‹ค.\n\n `max` ๋Š” ์ •๋ณธ์— ์ €์žฅ๋˜๋Š” ์ด๋ฆ„์ด๊ณ  ์„œ๋ฒ„ ์˜ค๋ฅ˜ยทํ˜•์‹ ๋ฌธ์„œยท๊ฒŒ์ดํŠธ ์‚ฌ์œ ๊ฐ€ ๋‹ค ๊ทธ ์ด๋ฆ„์„ ์“ด๋‹ค.\n ์ˆจ๊ธฐ๋ฉด ์•ˆ ๋˜๋Š” ์ข…๋ฅ˜๋‹ค. ๋™์ž‘์ด ๋จผ์ €๊ณ  ์ด๋ฆ„์ด ๊ด„ํ˜ธ๋กœ ๋”ฐ๋ผ์˜จ๋‹ค.\n */\n return html`\n <div anchor-row>\n <label>${i18next.t('figure.label.axis-name', { axis: axis.toUpperCase() })}</label>\n <div anchor-options>\n ${(['auto', 'scale', 'min', 'center', 'max', 'span'] as const).map(rule => {\n const selected = rule === 'auto' ? !said : rule === said\n const fullName = rule === 'auto' ? i18next.t('figure.label.anchor-auto', { rule: nameOf(auto, axis) }) : nameOf(rule, axis)\n return html`\n <button\n anchor-choice\n ?on=${selected}\n aria-pressed=${selected ? 'true' : 'false'}\n title=${fullName}\n @click=${() => setAnchor(axis, rule === 'auto' ? undefined : rule)}\n >${shortNameOf(rule, axis)}</button>\n `\n })}\n </div>\n <details anchor-advanced>\n <summary>${i18next.t('figure.label.anchor-advanced')}</summary>\n <div anchor-options>\n ${ANCHOR_RULES.filter(rule => rule.startsWith('aspect-')).map(rule => html`\n <button\n anchor-choice\n ?on=${rule === said}\n aria-pressed=${rule === said ? 'true' : 'false'}\n title=${nameOf(rule, axis)}\n @click=${() => setAnchor(axis, rule)}\n >${i18next.t(`figure.label.anchor-choice-${rule}`)}</button>\n `)}\n </div>\n </details>\n </div>\n `\n })}\n </div>\n </div>\n `\n }\n\n /**\n * ์ˆซ์ž ์นธ.\n *\n * ๋นˆ ์นธ์ด๋‚˜ ๊ธ€์ž๋ฅผ ๋„ฃ์—ˆ์„ ๋•Œ 0 ์œผ๋กœ ๋ฐ”๊ฟ”์น˜์ง€ ์•Š๋Š”๋‹ค โ€” ์ €์ž‘์ž๊ฐ€ ์ง€์šฐ๋Š” ์ค‘์ผ ์ˆ˜ ์žˆ๊ณ ,\n * ์กฐ์šฉํžˆ 0 ์ด ๋˜๋ฉด ๋ถ€ํ’ˆ์ด ์‚ฌ๋ผ์ง„ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ธ๋‹ค. ์ˆซ์ž๊ฐ€ ์•„๋‹ˆ๋ฉด ๊ทธ๋ƒฅ ์•ˆ ๋ฐ›๋Š”๋‹ค.\n */\n private number(label: string, value: number, set: (value: number) => void, min?: number) {\n return html`\n <div cell>\n ${label ? html`<span axis>${label}</span>` : nothing}\n <input\n type=\"number\"\n .value=${String(value)}\n min=${min ?? nothing}\n @change=${(e: Event) => {\n const raw = (e.target as HTMLInputElement).value\n const parsed = Number(raw)\n if (raw === '' || !Number.isFinite(parsed)) {\n // ๋˜๋Œ๋ ค ๋†“๋Š”๋‹ค. ์•ˆ ๊ทธ๋Ÿฌ๋ฉด ํ™”๋ฉด๊ณผ ์ •๋ณธ์ด ๊ฐˆ๋ฆฐ๋‹ค.\n ;(e.target as HTMLInputElement).value = String(value)\n return\n }\n set(parsed)\n }}\n />\n </div>\n `\n }\n\n /**\n * ๋„ํ˜•์„ ๋ฐ”๊พผ๋‹ค.\n *\n * ๋„ํ˜•์ด ๋ฐ”๋€Œ๋ฉด ๊ทธ ๋„ํ˜•์— ๋œป ์—†๋Š” ๊ฐ’์ด ๋‚จ๋Š”๋‹ค. ๋‚จ๊ฒจ ๋‘๋ฉด ๊ฒ€์ฆ์ด ใ€Œ๋ฌด์‹œ๋จใ€ ์œ„๋ฐ˜์„\n * ๋‚ด๋ฏ€๋กœ ์—ฌ๊ธฐ์„œ ๊ฑท๋Š”๋‹ค.\n */\n private changePrimitive(primitive: PrimitiveKind) {\n this.change(part => {\n const next: FigurePart = { ...part, primitive }\n if (!SEGMENTED_PRIMITIVES.includes(primitive)) delete next.segments\n if (!EXTRUDE_PRIMITIVES.includes(primitive)) delete next.shape\n if (SEGMENTED_PRIMITIVES.includes(primitive) && next.segments === undefined) {\n next.segments = SEGMENT_PRESETS[1]\n }\n return next\n })\n }\n\n private put(patch: Partial<FigurePart>) {\n this.change(part => ({ ...part, ...patch }))\n }\n\n private putTransform(patch: Record<string, unknown>) {\n this.change(part => ({ ...part, transform: { ...part.transform, ...patch } as FigurePart['transform'] }))\n }\n\n /**\n * ๋ฐœ๊ด‘ ์„ธ๊ธฐ๋ฅผ ๊ณ ์นœ๋‹ค. **0 ์ด๋ฉด ๋ธ”๋ก์„ ํ†ต์งธ๋กœ ์ง€์šด๋‹ค.**\n *\n * ์„ธ๊ธฐ 0 ์ธ ๋ฐœ๊ด‘์„ ๋‚จ๊ฒจ ๋‘๋ฉด ใ€Œ์•ˆ ๋น›๋‚˜๋Š”๋ฐ ๋žจํ”„์ธ ๊ฒƒใ€์ด ๋˜์–ด, ์žฌ์งˆ ํ‚ค๊ฐ€ ๊ฐˆ๋ ค ๋ฌถ์Œ์ด\n * ํ—›๋˜์ด ํ•˜๋‚˜ ๋Š”๋‹ค. 0 ์€ ใ€Œ๋žจํ”„๊ฐ€ ์•„๋‹ˆ๋‹คใ€๋กœ ์ฝ๋Š” ๊ฒƒ์ด ๋งž๋‹ค.\n *\n * `Number(value) || undefined` ๋ฅผ ์“ฐ๋ฉด ์•ˆ ๋œ๋‹ค โ€” 0 ์ด falsy ๋ผ ๋ณ€๊ฒฝ์œผ๋กœ ์•ˆ ์žกํ˜€ ์˜›\n * ๊ฐ’์ด ๊ทธ๋Œ€๋กœ ๋‚จ๋Š”๋‹ค. ์‹ค์ œ๋กœ ๋žจํ”„๊ฐ€ ์•ˆ ๊บผ์กŒ๋‹ค.\n */\n private putEmissive(intensity: number) {\n // `chosen` ์€ ์”ฌ ๋ชจ๋ธ์ด๋‹ค. ํ˜•์‹์œผ๋กœ ์˜ฎ๊ธด ๊ฐ’์€ `partToFigure` ์ด ๋งŒ๋“  ๊ฒƒ์ด๋ผ ์—ฌ๊ธฐ์„œ ๋‹ค์‹œ ๊บผ๋‚ธ๋‹ค.\n const glow = this.draft && this.chosen ? partToFigure(this.chosen, this.draft).material?.emissive : undefined\n\n this.putMaterial({ emissive: intensity > 0 ? { ...glow, intensity } : undefined })\n }\n\n private putMaterial(patch: Record<string, unknown>) {\n this.change(part => ({\n ...part,\n material: { ...(part.material ?? {}), ...patch } as FigurePart['material']\n }))\n }\n\n /**\n * ์ˆ˜์ •ํ•œ ๊ฒƒ์„ ์”ฌ ๋ชจ๋ธ๋กœ ๋˜๋Œ๋ ค ์•Œ๋ฆฐ๋‹ค.\n *\n * ์‚ฌ์šฉ์ž๋Š” XยทYยทZ ๋กœ ์ˆ˜์ •ํ•˜๊ณ , ๋ชจ๋ธ๋Ÿฌ ํŽ˜์ด์ง€๋Š” ์”ฌ ๋ชจ๋ธ์„ ๊ฐ–๋Š”๋‹ค. ๊ทธ ์‚ฌ์ด๋ฅผ ์—ฌ๊ธฐ์„œ\n * ์ž‡๋Š”๋‹ค โ€” ๋ณ€ํ™˜ํ•ด์„œ ์ˆ˜์ •ํ•˜๊ณ  ๋‹ค์‹œ ๋˜๋Œ๋ฆฐ๋‹ค. **์™•๋ณต ๋ณ€ํ™˜์ด ๋ฌด์†์‹ค์ด๋ผ์•ผ** ์œ„์น˜ ํ•˜๋‚˜\n * ๊ณ ์ณค์„ ๋ฟ์ธ๋ฐ ํšŒ์ „๊ฐ’์ด ์กฐ๊ธˆ์”ฉ ๋ฐ€๋ฆฌ๋Š” ์ผ์ด ์—†๋‹ค(`fold.test.ts` ๊ฐ€ ์ด๋ฅผ ํ™•์ธํ•œ๋‹ค).\n */\n private change(edit: (part: FigurePart) => FigurePart) {\n const part = this.chosen\n const draft = this.draft\n if (!part || !draft) return\n\n this.emit(partFromFigure(edit(partToFigure(part, draft)), draft))\n }\n\n /** ์ •๋ฐ€ ๋„๊ตฌ๋ฅผ ์‹œํ‚จ๋‹ค. ์ •๋ณธ์€ ์ €์ž‘๋ฉด์ด ๊ฐ–๋Š”๋‹ค โ€” ์—ฌ๊ธฐ์„œ๋Š” ์•Œ๋ฆฌ๊ธฐ๋งŒ ํ•œ๋‹ค. */\n private ask(what: string, axis: string) {\n this.dispatchEvent(\n new CustomEvent('part-tool', {\n detail: { index: this.selected, tool: what, axis },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private emit(part: PartModel) {\n this.dispatchEvent(\n new CustomEvent('update-part', { detail: { index: this.selected, part }, bubbles: true, composed: true })\n )\n }\n}\n"]}