'use strict'; const {assert,functionSource,app,css,html,read,vm,buildMeta}=require('./helpers/app-source'); const packageVersion=JSON.parse(read('package.json')).version; assert(packageVersion===buildMeta.PACKAGE_VERSION&&buildMeta.APP_VERSION==='48.0','v47.84 canonical version marker is missing'); assert(html.includes('id="resetSettings"')&&html.includes('id="closeSettings"')&&!html.includes('id="saveSettings"'),'Settings actions must expose Initial reset and Close without a Save button'); assert(functionSource('closeSettings').includes('saveSettings(restoreFocus)')&&functionSource('saveSettings').includes('closeSettingsDialog(restoreFocus)')&&functionSource('resetSettingsForm').includes('lightweightRenderingToggle.checked=false'),'Close does not apply settings or Initial reset is incomplete'); assert(functionSource('applyUiSettings').includes("classList.toggle('lightweight-rendering',uiSettings.lightweightRendering)")&&functionSource('applyUiSettings').includes("classList.toggle('reduced-effects',uiSettings.lightweightRendering)")&&!app.includes('autoReducedEffects')&&!app.includes('interactionQualityDowngradePending'),'Panning/interaction still enables an automatic lightweight mode'); assert(!css.includes('#viewport.panning::after{display:none}')&&!css.includes('#world.camera-interacting')&&css.includes('body.lightweight-rendering #noiseCanvas'),'Pan-only lightweight CSS remains or the explicit setting was removed'); assert(html.includes('id="boardHudLayer"')&&functionSource('makeBoard').includes('boardHudLayer?.append(label)')&&functionSource('positionBoardLabel').includes('viewportRect.height-margin-labelHeight')&&css.includes('.board-label[hidden]{display:none!important}'),'Active board HUD is still board-clipped or not viewport-clamped'); assert(!functionSource('hudPlacementCandidates').includes('occupancy.get'),'HUD placement still rejects overlap with neighboring puzzles'); assert(functionSource('positionCachedWorldOverview').includes('cam.scale/Math.max')&&functionSource('positionCachedWorldOverview').includes('translate3d')&&functionSource('positionCachedWorldOverview').includes('scale(${ratio})')&&functionSource('applyCamera').includes('positionCachedWorldOverview()'),'Zoomed-out overview does not move/scale its cached camera layer during pan'); assert(functionSource('updateDrawingHandlePosition').includes('point[0],point[1]')&&functionSource('processBoardDragFrame').includes('else if(b.drawing?.pointerId===move.pointerId)renderDragFrame(b)'),'Dragged knob is not tied directly to the latest pointer position'); assert(functionSource('syncCursorAppearance').includes('dataset.cursorMode=presentation.mode')&&!functionSource('updateCustomCursorFromPointer').includes('customEmojiCursor.style.transform')&&functionSource('commitCustomCursorFrame').includes('customEmojiCursor.style.transform=`translate3d(')&&css.includes('body.is-drawing #customEmojiCursor{display:none!important}'),'Custom cursor coverage, capped tracking, or drag-time hiding regressed'); const overviewContext={overviewCanvas:{hidden:true,style:{}},overviewCache:{scale:.2,baseWidth:1000,baseHeight:800,anchorX:0,anchorY:0,unit:43},cam:{scale:.1},MIN_CAMERA_SCALE:.01,currentCenter:[2,3],getViewportRect:()=>({width:800,height:600}),inWorldOverview:()=>true,perfCount:()=>{}}; overviewContext.cameraCenterInChunks=()=>overviewContext.currentCenter;vm.createContext(overviewContext);vm.runInContext(`${functionSource('positionCachedWorldOverview')}this.positionCachedWorldOverview=positionCachedWorldOverview;`,overviewContext); overviewContext.positionCachedWorldOverview();const overviewTransformBefore=overviewContext.overviewCanvas.style.transform;overviewContext.currentCenter=[5,-1];overviewContext.positionCachedWorldOverview(); assert(overviewTransformBefore!==overviewContext.overviewCanvas.style.transform&&overviewTransformBefore.includes('scale(0.5)'),'Cached overview transform does not react to camera movement and scale'); const hudStyle={removeProperty(name){delete this[name]}},hudLabel={hidden:true,classList:{add(){}},style:hudStyle,offsetWidth:220,offsetHeight:44,dataset:{}},hudContext={boardHudLayer:{},MIN_CAMERA_SCALE:.01,cam:{scale:.6},CELL:43,PAD:26,UNIT:215,boardPlayHudVisible:()=>true,hudPlacementCandidates:()=>[{side:'N',dx:0,dy:0,priority:0}],getViewportRect:()=>({left:0,top:0,width:640,height:360}),boardScreenRect:()=>({left:140,top:-120,width:300,height:250})}; vm.createContext(hudContext);vm.runInContext(`${functionSource('positionBoardLabel')}this.positionBoardLabel=positionBoardLabel;`,hudContext);const hudBoard={label:hudLabel,meta:{},p:{bounds:{w:5,h:5}}}; assert(hudContext.positionBoardLabel(hudBoard)&&parseFloat(hudLabel.style.top)>=8&&parseFloat(hudLabel.style.top)<=308,'Detached HUD is not clamped inside the visible viewport'); console.log('v47.84 settings, pan rendering, detached HUD, cursor, and knob regression test passed');