forgecad 0.9.8 → 0.9.9

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.
@@ -4,7 +4,7 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
5
  var _a2;
6
6
  import { c as create, j as jsxRuntimeExports, r as reactExports, a as createWithEqualityFn, R as React, T as Tb, s as schedulerExports, b as clientExports, d as reactDomExports, u as useParams, e as useSearchParams, f as useNavigate, L as Link, B as BrowserRouter, g as Routes, h as Route, N as Navigate } from "./vendor-react-Da3A2QmU.js";
7
- import { _ as __vitePreload, z as zipSync, s as strToU8, W as WebGLRenderer, R as Raycaster, O as OrthographicCamera$1, P as PerspectiveCamera$1, S as Scene, a as PCFSoftShadowMap, V as VSMShadowMap, b as PCFShadowMap, B as BasicShadowMap, C as ColorManagement, L as LinearSRGBColorSpace, c as SRGBColorSpace, N as NoToneMapping, A as ACESFilmicToneMapping, d as Layers, e as Color, f as RGBAFormat, U as UnsignedByteType, g as Vector3, h as Vector2, i as Clock, T as THREE, D as DoubleSide, j as REVISION, M as Mesh, I as IcosahedronGeometry, k as ShaderMaterial, l as Spherical, Q as Quaternion, m as MOUSE, n as TOUCH, o as Ray, p as Plane, q as DataTextureLoader, H as HalfFloatType, F as FloatType, r as DataUtils, t as LinearFilter, u as RedFormat, v as InstancedBufferGeometry, w as Float32BufferAttribute, x as InstancedInterleavedBuffer, y as InterleavedBufferAttribute, E as WireframeGeometry, G as Box3, J as Sphere, K as UniformsUtils, X as UniformsLib, Y as Vector4, Z as Line3, $ as Matrix4, a0 as MathUtils, a1 as Uniform, a2 as WebGLRenderTarget, a3 as DepthTexture, a4 as BackSide, a5 as ClampToEdgeWrapping, a6 as PlaneGeometry, a7 as UVMapping, a8 as DataTexture, a9 as Texture, aa as MeshBasicMaterial, ab as IntType, ac as ShortType, ad as ByteType, ae as UnsignedIntType, af as Loader, ag as LoadingManager, ah as LinearMipMapLinearFilter, ai as FileLoader, aj as NoBlending, ak as CubeReflectionMapping, al as EquirectangularReflectionMapping, am as CubeTextureLoader, an as WebGLCubeRenderTarget, ao as ConstraintSketch, ap as setSketchPlacement3D, aq as Sketch, ar as PROFILE_BACKEND_MARKER, as as FrozenShape, at as setShapeCompilePlan, au as hasAnyPorts, av as setShapePortsInternal, aw as markShapePortsUsed, ax as setParamOverrides, ay as DEFAULT_ACTIVE_BACKEND, az as isConstraintSketch, aA as updateConstraintValue, aB as getShapeCompilePlan, aC as resolveForgeRenderStyle, aD as publishSolverWasmRunDebug, aE as resolveForgeQualityPreset, aF as resolveImportPath, aG as BufferGeometry, aH as LineBasicMaterial, aI as Line$1, aJ as LineDashedMaterial, aK as DepthStencilFormat, aL as UnsignedInt248Type, aM as MeshNormalMaterial, aN as NearestFilter, aO as BasicDepthPacking, aP as EventDispatcher$1, aQ as NoColorSpace, aR as FrontSide, aS as Material, aT as AlwaysDepth, aU as BufferAttribute, aV as CanvasTexture, aW as Object3D, aX as FogExp2, aY as Fog, aZ as AmbientLight, a_ as HemisphereLight, a$ as SpotLight, b0 as PointLight, b1 as DirectionalLight, b2 as analyzeCollisionIntersections, b3 as shapeToGeometry, b4 as buildShapeFromCompilePlan, b5 as sketchToSvg, b6 as sketchToDxf, b7 as runScript, b8 as MeshPhysicalMaterial, b9 as LineSegments, ba as geometryWithVisibleVertexColors, bb as getRenderStylePreset, bc as AdditiveBlending, bd as ZEBRA_STRIPE_SOFTNESS, be as ZEBRA_STRIPE_SCALE, bf as ZEBRA_LIGHT_COLOR, bg as ZEBRA_DARK_COLOR, bh as ZEBRA_ACCENT_COLOR, bi as ZEBRA_STRIPE_FRAGMENT_SHADER, bj as ZEBRA_STRIPE_VERTEX_SHADER, bk as SURFACE_FIELD_FRAGMENT_SHADER, bl as SURFACE_FIELD_VERTEX_SHADER, bm as CatmullRomCurve3, bn as TubeGeometry, bo as MeshStandardMaterial, bp as compileSdfNode3, bq as buildSdfRaymarchFragmentShader, br as SDF_RAYMARCH_PROXY_VERTEX_SHADER, bs as Shape, bt as ShapeGeometry, bu as ShaderLib, bv as CylinderGeometry, bw as parseViewportCameraState, bx as createResolvedExplodeConfig, by as explodeBoundsCenter, bz as explodeMergeBounds, bA as resolveExplodeDirective, bB as computeExplodeMotion, bC as getSketchWorldMatrix, bD as explodeAdd, bE as hasExplodeOverride, bF as resolveExplodeLocalFanDirection, bG as explodeMul, bH as explodeLeafFanStage, bI as normalizeCutPlane, bJ as toClippingPlane, bK as findJointAnimationClip, bL as resolveJointAnimation, bM as resolveJointViewValues, bN as getShapePorts, bO as getShapeUsedPorts, bP as DEFAULT_VIEW_CONFIG, bQ as getKernelFaceNameForTriangle, bR as resolveScalarSceneSampleBudget, bS as initKernel, bT as initSolverWasm } from "./scalar-sampling-budget-iBAeF8RM.js";
7
+ import { _ as __vitePreload, z as zipSync, s as strToU8, W as WebGLRenderer, R as Raycaster, O as OrthographicCamera$1, P as PerspectiveCamera$1, S as Scene, a as PCFSoftShadowMap, V as VSMShadowMap, b as PCFShadowMap, B as BasicShadowMap, C as ColorManagement, L as LinearSRGBColorSpace, c as SRGBColorSpace, N as NoToneMapping, A as ACESFilmicToneMapping, d as Layers, e as Color, f as RGBAFormat, U as UnsignedByteType, g as Vector3, h as Vector2, i as Clock, T as THREE, D as DoubleSide, j as REVISION, M as Mesh, I as IcosahedronGeometry, k as ShaderMaterial, l as Spherical, Q as Quaternion, m as MOUSE, n as TOUCH, o as Ray, p as Plane, q as DataTextureLoader, H as HalfFloatType, F as FloatType, r as DataUtils, t as LinearFilter, u as RedFormat, v as InstancedBufferGeometry, w as Float32BufferAttribute, x as InstancedInterleavedBuffer, y as InterleavedBufferAttribute, E as WireframeGeometry, G as Box3, J as Sphere, K as UniformsUtils, X as UniformsLib, Y as Vector4, Z as Line3, $ as Matrix4, a0 as MathUtils, a1 as Uniform, a2 as WebGLRenderTarget, a3 as DepthTexture, a4 as BackSide, a5 as ClampToEdgeWrapping, a6 as PlaneGeometry, a7 as UVMapping, a8 as DataTexture, a9 as Texture, aa as MeshBasicMaterial, ab as IntType, ac as ShortType, ad as ByteType, ae as UnsignedIntType, af as Loader, ag as LoadingManager, ah as LinearMipMapLinearFilter, ai as FileLoader, aj as NoBlending, ak as CubeReflectionMapping, al as EquirectangularReflectionMapping, am as CubeTextureLoader, an as WebGLCubeRenderTarget, ao as ConstraintSketch, ap as setSketchPlacement3D, aq as Sketch, ar as PROFILE_BACKEND_MARKER, as as FrozenShape, at as setShapeCompilePlan, au as hasAnyPorts, av as setShapePortsInternal, aw as markShapePortsUsed, ax as setParamOverrides, ay as DEFAULT_ACTIVE_BACKEND, az as isConstraintSketch, aA as updateConstraintValue, aB as getShapeCompilePlan, aC as resolveForgeRenderStyle, aD as publishSolverWasmRunDebug, aE as resolveForgeQualityPreset, aF as resolveImportPath, aG as BufferGeometry, aH as LineBasicMaterial, aI as Line$1, aJ as LineDashedMaterial, aK as DepthStencilFormat, aL as UnsignedInt248Type, aM as MeshNormalMaterial, aN as NearestFilter, aO as BasicDepthPacking, aP as EventDispatcher$1, aQ as NoColorSpace, aR as FrontSide, aS as Material, aT as AlwaysDepth, aU as BufferAttribute, aV as CanvasTexture, aW as Object3D, aX as FogExp2, aY as Fog, aZ as AmbientLight, a_ as HemisphereLight, a$ as SpotLight, b0 as PointLight, b1 as DirectionalLight, b2 as analyzeCollisionIntersections, b3 as shapeToGeometry, b4 as buildShapeFromCompilePlan, b5 as sketchToSvg, b6 as sketchToDxf, b7 as runScript, b8 as MeshPhysicalMaterial, b9 as LineSegments, ba as geometryWithVisibleVertexColors, bb as getRenderStylePreset, bc as AdditiveBlending, bd as ZEBRA_STRIPE_SOFTNESS, be as ZEBRA_STRIPE_SCALE, bf as ZEBRA_LIGHT_COLOR, bg as ZEBRA_DARK_COLOR, bh as ZEBRA_ACCENT_COLOR, bi as ZEBRA_STRIPE_FRAGMENT_SHADER, bj as ZEBRA_STRIPE_VERTEX_SHADER, bk as SURFACE_FIELD_FRAGMENT_SHADER, bl as SURFACE_FIELD_VERTEX_SHADER, bm as CatmullRomCurve3, bn as TubeGeometry, bo as ROUGHNESS_COLORS, bp as DEFAULT_ROUGHNESS_INSPECTION_OPTIONS, bq as DEFAULT_THICKNESS_INSPECTION_OPTIONS, br as THICKNESS_COLORS, bs as MeshStandardMaterial, bt as compileSdfNode3, bu as buildSdfRaymarchFragmentShader, bv as SDF_RAYMARCH_PROXY_VERTEX_SHADER, bw as Shape, bx as ShapeGeometry, by as ShaderLib, bz as CylinderGeometry, bA as parseViewportCameraState, bB as createResolvedExplodeConfig, bC as explodeBoundsCenter, bD as explodeMergeBounds, bE as resolveExplodeDirective, bF as computeExplodeMotion, bG as getSketchWorldMatrix, bH as explodeAdd, bI as hasExplodeOverride, bJ as resolveExplodeLocalFanDirection, bK as explodeMul, bL as explodeLeafFanStage, bM as normalizeCutPlane, bN as toClippingPlane, bO as findJointAnimationClip, bP as resolveJointAnimation, bQ as resolveJointViewValues, bR as getShapePorts, bS as getShapeUsedPorts, bT as DEFAULT_VIEW_CONFIG, bU as getKernelFaceNameForTriangle, bV as resolveScalarSceneSampleBudget, bW as initKernel, bX as initSolverWasm } from "./scalar-sampling-budget-Bmewod18.js";
8
8
  function getCsrfToken() {
9
9
  const match = document.cookie.match(/(?:^|;\s*)fc-csrf-token=([^;]+)/);
10
10
  return match == null ? void 0 : match[1];
@@ -14909,24 +14909,24 @@ const formatAnimationSpeed = (speed) => {
14909
14909
  const safeSpeed = clampAnimationSpeed(speed);
14910
14910
  return safeSpeed < 0.1 ? safeSpeed.toFixed(3) : safeSpeed.toFixed(2);
14911
14911
  };
14912
- const fmt$1 = (n) => (Math.round(n * 1e3) / 1e3).toString();
14912
+ const fmt$2 = (n) => (Math.round(n * 1e3) / 1e3).toString();
14913
14913
  function planLabel(plan) {
14914
14914
  var _a3;
14915
14915
  switch (plan.kind) {
14916
14916
  case "box":
14917
- return `Box ${fmt$1(plan.x)} × ${fmt$1(plan.y)} × ${fmt$1(plan.z)}`;
14917
+ return `Box ${fmt$2(plan.x)} × ${fmt$2(plan.y)} × ${fmt$2(plan.z)}`;
14918
14918
  case "cylinder": {
14919
- const rLabel = plan.radiusTop !== void 0 && plan.radiusTop !== plan.radius ? `r=${fmt$1(plan.radius)}→${fmt$1(plan.radiusTop)}` : `r=${fmt$1(plan.radius)}`;
14920
- return `Cylinder ${rLabel} h=${fmt$1(plan.height)}`;
14919
+ const rLabel = plan.radiusTop !== void 0 && plan.radiusTop !== plan.radius ? `r=${fmt$2(plan.radius)}→${fmt$2(plan.radiusTop)}` : `r=${fmt$2(plan.radius)}`;
14920
+ return `Cylinder ${rLabel} h=${fmt$2(plan.height)}`;
14921
14921
  }
14922
14922
  case "sphere":
14923
- return `Sphere r=${fmt$1(plan.radius)}`;
14923
+ return `Sphere r=${fmt$2(plan.radius)}`;
14924
14924
  case "torus":
14925
- return `Torus R=${fmt$1(plan.majorRadius)} r=${fmt$1(plan.minorRadius)}`;
14925
+ return `Torus R=${fmt$2(plan.majorRadius)} r=${fmt$2(plan.minorRadius)}`;
14926
14926
  case "extrude":
14927
- return `Extrude h=${fmt$1(plan.height)}`;
14927
+ return `Extrude h=${fmt$2(plan.height)}`;
14928
14928
  case "revolve":
14929
- return `Revolve ${fmt$1(plan.degrees)}°`;
14929
+ return `Revolve ${fmt$2(plan.degrees)}°`;
14930
14930
  case "loft":
14931
14931
  return `Loft (${plan.profiles.length} profiles)`;
14932
14932
  case "sweep":
@@ -14940,17 +14940,17 @@ function planLabel(plan) {
14940
14940
  case "queryOwner":
14941
14941
  return planLabel(plan.base);
14942
14942
  case "fillet":
14943
- return `Fillet r=${fmt$1(plan.radius)}`;
14943
+ return `Fillet r=${fmt$2(plan.radius)}`;
14944
14944
  case "filletEdges":
14945
- return `Fillet r=${fmt$1(plan.radius)}`;
14945
+ return `Fillet r=${fmt$2(plan.radius)}`;
14946
14946
  case "cornerYBlend":
14947
- return `Y-corner blend r=${fmt$1(plan.radius)}`;
14947
+ return `Y-corner blend r=${fmt$2(plan.radius)}`;
14948
14948
  case "chamfer":
14949
- return `Chamfer ${fmt$1(plan.size)}`;
14949
+ return `Chamfer ${fmt$2(plan.size)}`;
14950
14950
  case "chamferEdges":
14951
- return `Chamfer ${fmt$1(plan.size)}`;
14951
+ return `Chamfer ${fmt$2(plan.size)}`;
14952
14952
  case "shell":
14953
- return `Shell t=${fmt$1(plan.thickness)}`;
14953
+ return `Shell t=${fmt$2(plan.thickness)}`;
14954
14954
  case "hole":
14955
14955
  return "Hole";
14956
14956
  case "cut":
@@ -14960,9 +14960,9 @@ function planLabel(plan) {
14960
14960
  case "sheetMetal":
14961
14961
  return "Sheet Metal";
14962
14962
  case "draft":
14963
- return `Draft ${fmt$1(plan.angleDeg)}°`;
14963
+ return `Draft ${fmt$2(plan.angleDeg)}°`;
14964
14964
  case "offsetSolid":
14965
- return `Offset ${fmt$1(plan.thickness)}`;
14965
+ return `Offset ${fmt$2(plan.thickness)}`;
14966
14966
  case "importedMesh":
14967
14967
  return `Import ${plan.filePath.split("/").pop() ?? "mesh"}`;
14968
14968
  case "sdf":
@@ -14978,9 +14978,9 @@ function planLabel(plan) {
14978
14978
  case "surfaceSew":
14979
14979
  return `Surface Sew (${plan.shapes.length} sheets)`;
14980
14980
  case "surfaceExtend":
14981
- return `Surface Extend ${fmt$1(plan.length)}`;
14981
+ return `Surface Extend ${fmt$2(plan.length)}`;
14982
14982
  case "surfaceThicken":
14983
- return `Thicken ${fmt$1(plan.thickness)}`;
14983
+ return `Thicken ${fmt$2(plan.thickness)}`;
14984
14984
  case "importedStep":
14985
14985
  return `STEP Import (${plan.filePath})`;
14986
14986
  }
@@ -15846,8 +15846,6 @@ function triggerDownload(blob, filename) {
15846
15846
  URL.revokeObjectURL(url2);
15847
15847
  }
15848
15848
  const INIT_TIMEOUT_MS = 12e4;
15849
- const RUN_TIMEOUT_MS = 3e4;
15850
- const EXPORT_TIMEOUT_MS = 3e5;
15851
15849
  const CRASH_COOLDOWN_MS = 2e3;
15852
15850
  class EvalWorkerClient {
15853
15851
  constructor(workerFactory = () => new Worker(new URL(
@@ -15864,8 +15862,7 @@ class EvalWorkerClient {
15864
15862
  __publicField(this, "pendingFaceInfo", /* @__PURE__ */ new Map());
15865
15863
  __publicField(this, "pendingExportExact", /* @__PURE__ */ new Map());
15866
15864
  __publicField(this, "pendingExportMesh", /* @__PURE__ */ new Map());
15867
- __publicField(this, "runTimeoutId", null);
15868
- __publicField(this, "exportTimeoutId", null);
15865
+ __publicField(this, "initTimeoutId", null);
15869
15866
  /** Timestamp of the last worker crash — used to enforce a cooldown before respawning. */
15870
15867
  __publicField(this, "lastCrashTime", 0);
15871
15868
  __publicField(this, "activeRunSeq", null);
@@ -15891,16 +15888,12 @@ class EvalWorkerClient {
15891
15888
  const { data } = event;
15892
15889
  if (data.type === "progress") {
15893
15890
  if (data.payload.phase === "export-evaluating" || data.payload.phase === "export-writing") {
15894
- this.resetExportTimeout();
15895
15891
  return;
15896
15892
  }
15897
15893
  if (data.payload.seq !== this.activeRunSeq) return;
15898
15894
  (_a3 = this.onProgress) == null ? void 0 : _a3.call(this, data.payload.phase);
15899
15895
  if (data.payload.phase === "evaluating") {
15900
- this.clearRunTimeout();
15901
- this.runTimeoutId = setTimeout(() => {
15902
- this.killWorker(`Script execution timed out after ${RUN_TIMEOUT_MS / 1e3}s`);
15903
- }, RUN_TIMEOUT_MS);
15896
+ this.clearInitTimeout();
15904
15897
  }
15905
15898
  return;
15906
15899
  }
@@ -15912,7 +15905,7 @@ class EvalWorkerClient {
15912
15905
  if (data.type === "run-success" || data.type === "run-error") {
15913
15906
  const req = this.pendingRuns.get(data.payload.seq);
15914
15907
  if (!req) return;
15915
- this.clearRunTimeout();
15908
+ this.clearInitTimeout();
15916
15909
  this.clearActiveRun(data.payload.seq);
15917
15910
  this.pendingRuns.delete(data.payload.seq);
15918
15911
  if (data.type === "run-success") {
@@ -15939,7 +15932,6 @@ class EvalWorkerClient {
15939
15932
  return;
15940
15933
  }
15941
15934
  if (data.type === "export-exact-success" || data.type === "export-exact-error") {
15942
- this.clearExportTimeout();
15943
15935
  const req = this.pendingExportExact.get(data.payload.reqId);
15944
15936
  if (!req) return;
15945
15937
  this.pendingExportExact.delete(data.payload.reqId);
@@ -15951,7 +15943,6 @@ class EvalWorkerClient {
15951
15943
  return;
15952
15944
  }
15953
15945
  if (data.type === "export-mesh-success" || data.type === "export-mesh-error") {
15954
- this.clearExportTimeout();
15955
15946
  const req = this.pendingExportMesh.get(data.payload.reqId);
15956
15947
  if (!req) return;
15957
15948
  this.pendingExportMesh.delete(data.payload.reqId);
@@ -15963,8 +15954,7 @@ class EvalWorkerClient {
15963
15954
  }
15964
15955
  };
15965
15956
  this.worker.onerror = (event) => {
15966
- this.clearRunTimeout();
15967
- this.clearExportTimeout();
15957
+ this.clearInitTimeout();
15968
15958
  this.clearActiveRun();
15969
15959
  this.lastCrashTime = Date.now();
15970
15960
  const err = new Error(event.message || "Eval worker crashed");
@@ -15982,28 +15972,12 @@ class EvalWorkerClient {
15982
15972
  };
15983
15973
  return this.worker;
15984
15974
  }
15985
- clearRunTimeout() {
15986
- if (this.runTimeoutId !== null) {
15987
- clearTimeout(this.runTimeoutId);
15988
- this.runTimeoutId = null;
15975
+ clearInitTimeout() {
15976
+ if (this.initTimeoutId !== null) {
15977
+ clearTimeout(this.initTimeoutId);
15978
+ this.initTimeoutId = null;
15989
15979
  }
15990
15980
  }
15991
- clearExportTimeout() {
15992
- if (this.exportTimeoutId !== null) {
15993
- clearTimeout(this.exportTimeoutId);
15994
- this.exportTimeoutId = null;
15995
- }
15996
- }
15997
- resetExportTimeout() {
15998
- this.clearExportTimeout();
15999
- this.exportTimeoutId = setTimeout(() => {
16000
- const err = new Error(`Export timed out after ${EXPORT_TIMEOUT_MS / 1e3}s`);
16001
- for (const req of this.pendingExportExact.values()) req.reject(err);
16002
- for (const req of this.pendingExportMesh.values()) req.reject(err);
16003
- this.pendingExportExact.clear();
16004
- this.pendingExportMesh.clear();
16005
- }, EXPORT_TIMEOUT_MS);
16006
- }
16007
15981
  clearActiveRun(seq) {
16008
15982
  if (seq !== void 0 && this.activeRunSeq !== seq) return;
16009
15983
  this.activeRunSeq = null;
@@ -16017,8 +15991,7 @@ class EvalWorkerClient {
16017
15991
  */
16018
15992
  replaceWorkerForSupersedingRun() {
16019
15993
  console.info("[evalWorkerClient] Superseded eval run — replacing worker");
16020
- this.clearRunTimeout();
16021
- this.clearExportTimeout();
15994
+ this.clearInitTimeout();
16022
15995
  this.clearActiveRun();
16023
15996
  this.workerWasmHeap = null;
16024
15997
  if (this.worker) {
@@ -16042,8 +16015,7 @@ class EvalWorkerClient {
16042
16015
  */
16043
16016
  killWorker(reason, failureMessage = reason) {
16044
16017
  console.warn(`[evalWorkerClient] ${reason} — terminating worker`);
16045
- this.clearRunTimeout();
16046
- this.clearExportTimeout();
16018
+ this.clearInitTimeout();
16047
16019
  this.clearActiveRun();
16048
16020
  this.lastCrashTime = Date.now();
16049
16021
  this.workerWasmHeap = null;
@@ -16065,7 +16037,7 @@ class EvalWorkerClient {
16065
16037
  /** Post a run request to the worker and arm the init timeout. */
16066
16038
  startRun(seq, options) {
16067
16039
  this.activeRunSeq = seq;
16068
- this.runTimeoutId = setTimeout(() => {
16040
+ this.initTimeoutId = setTimeout(() => {
16069
16041
  this.killWorker(`Kernel initialization timed out after ${INIT_TIMEOUT_MS / 1e3}s`);
16070
16042
  }, INIT_TIMEOUT_MS);
16071
16043
  const request = { type: "run", payload: { seq, ...options } };
@@ -16077,7 +16049,7 @@ class EvalWorkerClient {
16077
16049
  * block the newer request. Only the latest run's result is resolved.
16078
16050
  *
16079
16051
  * A generous init timeout (120s) covers WASM loading. Once the worker signals
16080
- * 'evaluating', a shorter run timeout (30s) takes over.
16052
+ * 'evaluating', the run is allowed to continue until it completes or is superseded.
16081
16053
  */
16082
16054
  run(options) {
16083
16055
  if (this.shouldReplaceWorkerForSupersedingRun()) {
@@ -16085,7 +16057,7 @@ class EvalWorkerClient {
16085
16057
  } else {
16086
16058
  for (const req of this.pendingRuns.values()) req.reject(new Error("cancelled"));
16087
16059
  this.pendingRuns.clear();
16088
- this.clearRunTimeout();
16060
+ this.clearInitTimeout();
16089
16061
  }
16090
16062
  const seq = ++this.seq;
16091
16063
  const msSinceCrash = Date.now() - this.lastCrashTime;
@@ -16119,7 +16091,6 @@ class EvalWorkerClient {
16119
16091
  /**
16120
16092
  * Export exact geometry (STEP/BREP) using live OCCT shapes in the worker.
16121
16093
  * Includes script context so the worker can re-evaluate if needed.
16122
- * Uses a generous 5-minute timeout that resets on each progress phase.
16123
16094
  */
16124
16095
  exportExact(format, scriptContext) {
16125
16096
  const reqId = ++this.exportExactReqId;
@@ -16131,7 +16102,6 @@ class EvalWorkerClient {
16131
16102
  },
16132
16103
  reject
16133
16104
  });
16134
- this.resetExportTimeout();
16135
16105
  const request = {
16136
16106
  type: "export-exact",
16137
16107
  payload: { reqId, format, ...scriptContext }
@@ -16153,7 +16123,6 @@ class EvalWorkerClient {
16153
16123
  },
16154
16124
  reject
16155
16125
  });
16156
- this.resetExportTimeout();
16157
16126
  const request = {
16158
16127
  type: "export-mesh",
16159
16128
  payload: { reqId, format, ...scriptContext }
@@ -16167,8 +16136,7 @@ class EvalWorkerClient {
16167
16136
  this.worker.postMessage({ type: "set-project", payload: { projectId } });
16168
16137
  }
16169
16138
  terminate() {
16170
- this.clearRunTimeout();
16171
- this.clearExportTimeout();
16139
+ this.clearInitTimeout();
16172
16140
  this.clearActiveRun();
16173
16141
  this.workerWasmHeap = null;
16174
16142
  this.lastWorkerFailure = null;
@@ -19073,7 +19041,7 @@ useAuthStore.subscribe((state2) => {
19073
19041
  function roundCoord(v) {
19074
19042
  return Math.round(v * 10) / 10;
19075
19043
  }
19076
- function fmt(v) {
19044
+ function fmt$1(v) {
19077
19045
  const r2 = roundCoord(v);
19078
19046
  return Number.isInteger(r2) ? String(r2) : r2.toFixed(1);
19079
19047
  }
@@ -19092,13 +19060,13 @@ function generateSketchCode(session) {
19092
19060
  return lines.join("\n");
19093
19061
  }
19094
19062
  function pointStatement(varName, x, y) {
19095
- return `const ${varName} = sk.point(${fmt(x)}, ${fmt(y)});`;
19063
+ return `const ${varName} = sk.point(${fmt$1(x)}, ${fmt$1(y)});`;
19096
19064
  }
19097
19065
  function lineStatement(varName, startVar, endVar) {
19098
19066
  return `const ${varName} = sk.line(${startVar}, ${endVar});`;
19099
19067
  }
19100
19068
  function circleStatement(varName, centerVar, radius) {
19101
- return `const ${varName} = sk.circle(${centerVar}, ${fmt(radius)});`;
19069
+ return `const ${varName} = sk.circle(${centerVar}, ${fmt$1(radius)});`;
19102
19070
  }
19103
19071
  function arcStatement(varName, centerVar, startVar, endVar) {
19104
19072
  return `const ${varName} = sk.arcByCenter(${centerVar}, ${startVar}, ${endVar});`;
@@ -19108,7 +19076,7 @@ const CONSTRAINT_API_MAP = {
19108
19076
  };
19109
19077
  function constraintStatement(type, ...args) {
19110
19078
  const apiName = CONSTRAINT_API_MAP[type] ?? type;
19111
- const fmtArgs = args.map((a2) => typeof a2 === "number" ? fmt(a2) : a2).join(", ");
19079
+ const fmtArgs = args.map((a2) => typeof a2 === "number" ? fmt$1(a2) : a2).join(", ");
19112
19080
  return `sk.${apiName}(${fmtArgs});`;
19113
19081
  }
19114
19082
  function isConstraintTool(tool) {
@@ -26890,6 +26858,7 @@ function analyzeViewportCollisions(objects, objectSettings, objectMatrices) {
26890
26858
  const COLLISION_SOURCE_OPACITY = 0.22;
26891
26859
  const COLLISION_SOURCE_COLOR = [180, 200, 220];
26892
26860
  const COLLISION_HIGHLIGHT_COLOR = [255, 68, 16];
26861
+ const FLOATING_HIGHLIGHT_COLOR = [255, 68, 16];
26893
26862
  const FLOATING_CONTEXT_COLOR = [38, 49, 58];
26894
26863
  const COLLISION_PALETTE = [
26895
26864
  COLLISION_HIGHLIGHT_COLOR,
@@ -26927,6 +26896,10 @@ const MASK_PALETTE = [
26927
26896
  [0, 0, 128],
26928
26897
  [128, 128, 128]
26929
26898
  ];
26899
+ const DISTANCE_NEAR_COLOR = [66, 220, 120];
26900
+ const DISTANCE_MID_COLOR = [255, 214, 0];
26901
+ const DISTANCE_FAR_COLOR = [255, 68, 16];
26902
+ const DISTANCE_UNKNOWN_COLOR = [128, 128, 128];
26930
26903
  function rgbToHex(color2) {
26931
26904
  return `#${color2.map((value) => value.toString(16).padStart(2, "0")).join("")}`;
26932
26905
  }
@@ -33383,6 +33356,263 @@ function HoveredJointOverlay({ state: state2, config }) {
33383
33356
  ] })
33384
33357
  ] });
33385
33358
  }
33359
+ function colorToHex(color2) {
33360
+ return rgbToHex(color2);
33361
+ }
33362
+ function fmt(value) {
33363
+ return Number.isInteger(value) ? String(value) : value.toFixed(1);
33364
+ }
33365
+ function inspectionLegendDefinitionFor(channel) {
33366
+ switch (channel) {
33367
+ case "mask":
33368
+ return {
33369
+ title: "Mask Colors",
33370
+ summary: "Each color identifies a different top-level object for picking or image analysis.",
33371
+ swatches: [
33372
+ { label: "Object A", detail: "unique id", color: rgbToHex(maskRgbForIndex(0)) },
33373
+ { label: "Object B", detail: "unique id", color: rgbToHex(maskRgbForIndex(1)) },
33374
+ { label: "Object C", detail: "unique id", color: rgbToHex(maskRgbForIndex(2)) },
33375
+ { label: "Object D", detail: "unique id", color: rgbToHex(maskRgbForIndex(3)) }
33376
+ ]
33377
+ };
33378
+ case "normals":
33379
+ return {
33380
+ title: "Normal Colors",
33381
+ summary: "Color comes from surface direction in view space, so seams and flipped normals become visible."
33382
+ };
33383
+ case "zebra":
33384
+ return {
33385
+ title: "Zebra Stripes",
33386
+ summary: "Continuous stripes imply smooth surface flow; kinks or broken stripes reveal continuity changes."
33387
+ };
33388
+ case "connectivity":
33389
+ return {
33390
+ title: "Connected Bodies",
33391
+ summary: "Each color is one physically connected component. Different colors mean disconnected islands.",
33392
+ swatches: [
33393
+ { label: "Component 1", detail: "connected", color: rgbToHex(maskRgbForIndex(0)) },
33394
+ { label: "Component 2", detail: "separate", color: rgbToHex(maskRgbForIndex(1)) },
33395
+ { label: "Component 3", detail: "separate", color: rgbToHex(maskRgbForIndex(2)) }
33396
+ ]
33397
+ };
33398
+ case "floating":
33399
+ return {
33400
+ title: "Floating Bodies",
33401
+ summary: "Highlights bodies that are disconnected from grounded material above the build plane.",
33402
+ swatches: [
33403
+ { label: "Floating", detail: "unsupported", color: rgbToHex(FLOATING_HIGHLIGHT_COLOR) },
33404
+ { label: "Context", detail: "other geometry", color: rgbToHex(FLOATING_CONTEXT_COLOR) }
33405
+ ]
33406
+ };
33407
+ case "distance":
33408
+ return {
33409
+ title: "Root Distance",
33410
+ summary: "Shows how far each disconnected component is from the rooted component graph.",
33411
+ ramp: {
33412
+ colors: [rgbToHex(DISTANCE_NEAR_COLOR), rgbToHex(DISTANCE_MID_COLOR), rgbToHex(DISTANCE_FAR_COLOR)],
33413
+ leftLabel: "Near root",
33414
+ centerLabel: "Mid",
33415
+ rightLabel: "Far"
33416
+ },
33417
+ swatches: [{ label: "Unknown", detail: "not resolved", color: rgbToHex(DISTANCE_UNKNOWN_COLOR) }]
33418
+ };
33419
+ case "collisions":
33420
+ return {
33421
+ title: "Collision Overlaps",
33422
+ summary: "Bright solids are actual overlap volumes; source bodies are ghosted behind them.",
33423
+ swatches: [
33424
+ { label: "Overlap", detail: "intersecting volume", color: rgbToHex(COLLISION_HIGHLIGHT_COLOR) },
33425
+ { label: "Ghost body", detail: "source geometry", color: rgbToHex(COLLISION_SOURCE_COLOR) }
33426
+ ]
33427
+ };
33428
+ case "thickness": {
33429
+ const options = DEFAULT_THICKNESS_INSPECTION_OPTIONS;
33430
+ return {
33431
+ title: "Wall Thickness",
33432
+ summary: "Red/orange is thin material. Green/blue has more printable or machinable thickness.",
33433
+ ramp: {
33434
+ colors: [
33435
+ colorToHex(THICKNESS_COLORS.critical),
33436
+ colorToHex(THICKNESS_COLORS.warning),
33437
+ colorToHex(THICKNESS_COLORS.ok),
33438
+ colorToHex(THICKNESS_COLORS.thick)
33439
+ ],
33440
+ leftLabel: `<= ${fmt(options.minThickness)} mm`,
33441
+ centerLabel: `${fmt(options.warnThickness)} mm warn`,
33442
+ rightLabel: `>= ${fmt(options.maxThickness)} mm`
33443
+ }
33444
+ };
33445
+ }
33446
+ case "roughness": {
33447
+ const options = DEFAULT_ROUGHNESS_INSPECTION_OPTIONS;
33448
+ return {
33449
+ title: "Surface Roughness",
33450
+ summary: "Color follows local angle change. Dark is smooth; warmer colors mean sharper or harsher mesh transitions.",
33451
+ swatches: [
33452
+ { label: "Smooth", detail: `< ${fmt(options.smoothAngleDeg)} deg`, color: colorToHex(ROUGHNESS_COLORS.smooth) },
33453
+ {
33454
+ label: "Moderate",
33455
+ detail: `${fmt(options.smoothAngleDeg)}-${fmt(options.sharpAngleDeg)} deg`,
33456
+ color: colorToHex(ROUGHNESS_COLORS.moderate)
33457
+ },
33458
+ {
33459
+ label: "Sharp",
33460
+ detail: `${fmt(options.sharpAngleDeg)}-${fmt(options.harshAngleDeg)} deg`,
33461
+ color: colorToHex(ROUGHNESS_COLORS.sharp)
33462
+ },
33463
+ { label: "Harsh", detail: `>= ${fmt(options.harshAngleDeg)} deg`, color: colorToHex(ROUGHNESS_COLORS.harsh) }
33464
+ ]
33465
+ };
33466
+ }
33467
+ default:
33468
+ return null;
33469
+ }
33470
+ }
33471
+ const panelStyle = {
33472
+ position: "absolute",
33473
+ left: 12,
33474
+ bottom: 12,
33475
+ width: "min(300px, calc(100% - 24px))",
33476
+ padding: "9px 10px",
33477
+ borderRadius: 8,
33478
+ border: "1px solid color-mix(in srgb, var(--fc-border) 86%, transparent)",
33479
+ background: "color-mix(in srgb, var(--fc-bgPanel) 92%, transparent)",
33480
+ boxShadow: "0 10px 26px rgba(0, 0, 0, 0.22)",
33481
+ color: "var(--fc-text)",
33482
+ fontSize: 11,
33483
+ lineHeight: 1.35,
33484
+ pointerEvents: "none",
33485
+ zIndex: 9
33486
+ };
33487
+ const titleStyle = {
33488
+ display: "flex",
33489
+ alignItems: "center",
33490
+ justifyContent: "space-between",
33491
+ gap: 8,
33492
+ marginBottom: 5,
33493
+ color: "var(--fc-text)",
33494
+ fontSize: 11,
33495
+ fontWeight: 700,
33496
+ letterSpacing: 0
33497
+ };
33498
+ const summaryStyle = {
33499
+ marginBottom: 7,
33500
+ color: "var(--fc-textDim)",
33501
+ overflowWrap: "anywhere"
33502
+ };
33503
+ const swatchGridStyle = {
33504
+ display: "grid",
33505
+ gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
33506
+ gap: 6
33507
+ };
33508
+ function Ramp({ compact, ramp }) {
33509
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { minWidth: 0 }, children: [
33510
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
33511
+ "div",
33512
+ {
33513
+ style: {
33514
+ height: 9,
33515
+ borderRadius: 999,
33516
+ border: "1px solid rgba(255, 255, 255, 0.24)",
33517
+ background: `linear-gradient(90deg, ${ramp.colors.join(", ")})`
33518
+ }
33519
+ }
33520
+ ),
33521
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
33522
+ "div",
33523
+ {
33524
+ style: {
33525
+ display: "grid",
33526
+ gridTemplateColumns: ramp.centerLabel ? "repeat(3, minmax(0, 1fr))" : "repeat(2, minmax(0, 1fr))",
33527
+ gap: 6,
33528
+ marginTop: 4,
33529
+ color: "var(--fc-textDim)",
33530
+ fontSize: compact ? 9 : 10
33531
+ },
33532
+ children: [
33533
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: ramp.leftLabel }),
33534
+ ramp.centerLabel && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { textAlign: "center" }, children: ramp.centerLabel }),
33535
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { textAlign: "right" }, children: ramp.rightLabel })
33536
+ ]
33537
+ }
33538
+ )
33539
+ ] });
33540
+ }
33541
+ function Swatch({ item }) {
33542
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "grid", gridTemplateColumns: "12px minmax(0, 1fr)", alignItems: "center", gap: 6, minWidth: 0 }, children: [
33543
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
33544
+ "span",
33545
+ {
33546
+ style: {
33547
+ width: 12,
33548
+ height: 12,
33549
+ borderRadius: 3,
33550
+ border: "1px solid rgba(255, 255, 255, 0.28)",
33551
+ background: item.color
33552
+ }
33553
+ }
33554
+ ),
33555
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { style: { minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: [
33556
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "var(--fc-text)" }, children: item.label }),
33557
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { style: { color: "var(--fc-textDim)" }, children: [
33558
+ " - ",
33559
+ item.detail
33560
+ ] })
33561
+ ] })
33562
+ ] });
33563
+ }
33564
+ function InspectionLegend({ channel, warnings }) {
33565
+ const panelRef = reactExports.useRef(null);
33566
+ const [compact, setCompact] = reactExports.useState(false);
33567
+ const definition = inspectionLegendDefinitionFor(channel);
33568
+ reactExports.useEffect(() => {
33569
+ var _a3;
33570
+ const parent = (_a3 = panelRef.current) == null ? void 0 : _a3.parentElement;
33571
+ if (!parent || typeof ResizeObserver === "undefined") return;
33572
+ const updateCompact = () => setCompact(parent.clientWidth < 260);
33573
+ updateCompact();
33574
+ const observer = new ResizeObserver(updateCompact);
33575
+ observer.observe(parent);
33576
+ return () => observer.disconnect();
33577
+ }, [channel]);
33578
+ if (!definition) return null;
33579
+ const warning = warnings[0];
33580
+ const effectivePanelStyle = compact ? { ...panelStyle, padding: "7px 8px" } : panelStyle;
33581
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref: panelRef, className: "fc-inspection-legend", style: effectivePanelStyle, children: [
33582
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: titleStyle, children: [
33583
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: definition.title }),
33584
+ warning && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "var(--fc-warning)", fontSize: 10 }, children: "Warning" })
33585
+ ] }),
33586
+ !compact && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: summaryStyle, children: definition.summary }),
33587
+ definition.ramp && /* @__PURE__ */ jsxRuntimeExports.jsx(Ramp, { compact, ramp: definition.ramp }),
33588
+ definition.swatches && /* @__PURE__ */ jsxRuntimeExports.jsx(
33589
+ "div",
33590
+ {
33591
+ style: {
33592
+ ...swatchGridStyle,
33593
+ gridTemplateColumns: compact ? "minmax(0, 1fr)" : swatchGridStyle.gridTemplateColumns,
33594
+ marginTop: definition.ramp ? 8 : 0
33595
+ },
33596
+ children: definition.swatches.map((item) => /* @__PURE__ */ jsxRuntimeExports.jsx(Swatch, { item }, `${item.label}:${item.detail}`))
33597
+ }
33598
+ ),
33599
+ warning && /* @__PURE__ */ jsxRuntimeExports.jsx(
33600
+ "div",
33601
+ {
33602
+ style: {
33603
+ marginTop: 7,
33604
+ paddingTop: 7,
33605
+ borderTop: "1px solid color-mix(in srgb, var(--fc-border) 72%, transparent)",
33606
+ color: "var(--fc-warning)",
33607
+ overflow: "hidden",
33608
+ textOverflow: "ellipsis",
33609
+ whiteSpace: "nowrap"
33610
+ },
33611
+ children: warning
33612
+ }
33613
+ )
33614
+ ] });
33615
+ }
33386
33616
  function LabeledAxes({ size = 50 }) {
33387
33617
  const axesRef = reactExports.useRef(null);
33388
33618
  reactExports.useEffect(() => {
@@ -41433,6 +41663,7 @@ function Viewport() {
41433
41663
  }
41434
41664
  ),
41435
41665
  /* @__PURE__ */ jsxRuntimeExports.jsx(PerformanceInfoPanel, { enabled: showPerformanceInfo, stats: performanceInfo }),
41666
+ !viewportBusyPhase && /* @__PURE__ */ jsxRuntimeExports.jsx(InspectionLegend, { channel: inspectChannel, warnings: inspectAnalysis.warnings }),
41436
41667
  !viewportBusyPhase && /* @__PURE__ */ jsxRuntimeExports.jsx(ZoomIndicatorPanel, { mmPerPx: zoomMmPerPx }),
41437
41668
  isSketchOnly && /* @__PURE__ */ jsxRuntimeExports.jsx(
41438
41669
  SketchRulersOverlay,
@@ -41986,7 +42217,7 @@ function Viewport() {
41986
42217
  }
41987
42218
  );
41988
42219
  }
41989
- const EditorApp$1 = reactExports.lazy(() => __vitePreload(() => import("./EditorApp-DVMnXOmO.js"), true ? __vite__mapDeps([0]) : void 0).then((m2) => ({ default: m2.EditorApp })));
42220
+ const EditorApp$1 = reactExports.lazy(() => __vitePreload(() => import("./EditorApp-DnddQvBt.js"), true ? __vite__mapDeps([0]) : void 0).then((m2) => ({ default: m2.EditorApp })));
41990
42221
  const PENDING_SHARE_COPY_KEY = "fc-pending-share-copy";
41991
42222
  function storePendingShareCopy(shareId) {
41992
42223
  sessionStorage.setItem(PENDING_SHARE_COPY_KEY, shareId);
@@ -42173,15 +42404,15 @@ const PublishedModelPage$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Objec
42173
42404
  consumePendingShareCopy,
42174
42405
  storePendingShareCopy
42175
42406
  }, Symbol.toStringTag, { value: "Module" }));
42176
- reactExports.lazy(() => __vitePreload(() => import("./LandingPageProofDriven-2q2sn7aW.js"), true ? __vite__mapDeps([1]) : void 0).then((m2) => ({ default: m2.LandingPageProofDriven })));
42177
- const DocsPage = reactExports.lazy(() => __vitePreload(() => import("./DocsPage-CNBKuitP.js"), true ? [] : void 0).then((m2) => ({ default: m2.DocsPage })));
42178
- reactExports.lazy(() => __vitePreload(() => import("./BlogPage-Crpr3JjH.js"), true ? [] : void 0).then((m2) => ({ default: m2.BlogPage })));
42179
- reactExports.lazy(() => __vitePreload(() => import("./AdminPage-CXaVLMiV.js"), true ? [] : void 0).then((m2) => ({ default: m2.AdminPage })));
42407
+ reactExports.lazy(() => __vitePreload(() => import("./LandingPageProofDriven-CFet-l3o.js"), true ? __vite__mapDeps([1]) : void 0).then((m2) => ({ default: m2.LandingPageProofDriven })));
42408
+ const DocsPage = reactExports.lazy(() => __vitePreload(() => import("./DocsPage-9U1hGjrg.js"), true ? [] : void 0).then((m2) => ({ default: m2.DocsPage })));
42409
+ reactExports.lazy(() => __vitePreload(() => import("./BlogPage-Cc41PP4d.js"), true ? [] : void 0).then((m2) => ({ default: m2.BlogPage })));
42410
+ reactExports.lazy(() => __vitePreload(() => import("./AdminPage-CNEvQM7c.js"), true ? [] : void 0).then((m2) => ({ default: m2.AdminPage })));
42180
42411
  reactExports.lazy(() => __vitePreload(() => Promise.resolve().then(() => PublishedModelPage$1), true ? void 0 : void 0).then((m2) => ({ default: m2.PublishedModelPage })));
42181
- reactExports.lazy(() => __vitePreload(() => import("./SettingsPage-BVj1FtEv.js"), true ? [] : void 0).then((m2) => ({ default: m2.SettingsPage })));
42182
- reactExports.lazy(() => __vitePreload(() => import("./PricingPage-CVvgdv0i.js"), true ? __vite__mapDeps([2,1]) : void 0).then((m2) => ({ default: m2.PricingPage })));
42183
- const EditorApp = reactExports.lazy(() => __vitePreload(() => import("./EditorApp-DVMnXOmO.js"), true ? __vite__mapDeps([0]) : void 0).then((m2) => ({ default: m2.EditorApp })));
42184
- const EmbedViewer = reactExports.lazy(() => __vitePreload(() => import("./EmbedViewer-KXFLSnpo.js"), true ? [] : void 0).then((m2) => ({ default: m2.EmbedViewer })));
42412
+ reactExports.lazy(() => __vitePreload(() => import("./SettingsPage-BarZonVZ.js"), true ? [] : void 0).then((m2) => ({ default: m2.SettingsPage })));
42413
+ reactExports.lazy(() => __vitePreload(() => import("./PricingPage-CPm8mQx3.js"), true ? __vite__mapDeps([2,1]) : void 0).then((m2) => ({ default: m2.PricingPage })));
42414
+ const EditorApp = reactExports.lazy(() => __vitePreload(() => import("./EditorApp-DnddQvBt.js"), true ? __vite__mapDeps([0]) : void 0).then((m2) => ({ default: m2.EditorApp })));
42415
+ const EmbedViewer = reactExports.lazy(() => __vitePreload(() => import("./EmbedViewer-B2lhWTcd.js"), true ? [] : void 0).then((m2) => ({ default: m2.EmbedViewer })));
42185
42416
  const embedMode = isEmbedMode() && !window.location.pathname.startsWith("/m/");
42186
42417
  const EDITABLE_CRASH_FILE = /\.(?:forge\.js|[cm]?[jt]sx?|json|md|txt|svg)$/i;
42187
42418
  function firstMeaningfulLine(text) {