§
    …P¾j…=  ã                   óž  — d Z ddlZddlmc mZ ddlZddlZddl	m
Z
 ddlZ e
e¦  «                             ¦   «         j        j        j        Zedz  dz  Zedz  dz  dz  Zed	z  Zedz  d
z  dz  Zedz  dz  Zedz  d
z  dz  Zedz  dz  dz  ZdZdedefd„Z G d„ d¦  «        Z G d„ d¦  «        Z G d„ d¦  «        Z G d„ d¦  «        ZdS )aà  Unit Test Suite: Game Pause Mechanism & Overlay System (PoE2 Standard - Milestone 3).

Empirical verification of:
1. Initial pause state (window.isGamePaused === false, #overlay-pause hidden)
2. Direct state toggling (setGamePaused(true/false), toggleGamePause())
3. Settings modal integration (openSettingsModal pauses, closeSettingsModal unpauses)
4. Desktop Escape key integration (toggles pause when clean; unpauses when closing settings)
5. Pause overlay tap/click unpause handler
6. Skill bar and click input freeze (activation rejected, effectiveDt = 0)
7. Kinematics freeze (player position does not advance when paused)
8. Structural hygiene & line caps (canvas_renderer <= 350, index.html <= 400, no modal- prefix on overlay)
é    N)ÚPathÚclientÚwebappÚjsÚenginezcanvas_renderer.jsz
index.htmlÚuizfeedback.jszmain.jszskill_bar_controller.jszcombat_skills.jsa*  
import fs from 'fs';
const elements = new Map(), docListeners = new Map();
function makeElement(id, tagName = 'DIV') {
  const classes = new Set(['hidden']), styles = {}, handlers = new Map(), children = [];
  return {
    id, tagName, dataset: {}, offsetWidth: 44, offsetHeight: 44, children,
    classList: {
      add: c => classes.add(c), remove: c => classes.delete(c), contains: c => classes.has(c),
      toggle: (c, f) => { const h = classes.has(c); const s = f === undefined ? !h : Boolean(f); s ? classes.add(c) : classes.delete(c); return s; }
    },
    style: { setProperty: (k, v) => { styles[k] = v; }, getProperty: k => styles[k] },
    addEventListener: (t, fn) => { if (!handlers.has(t)) handlers.set(t, []); handlers.get(t).push(fn); },
    removeEventListener: (t, fn) => { if (handlers.has(t)) handlers.set(t, handlers.get(t).filter(h => h !== fn)); },
    dispatchEvent: function(evt) { evt.target = evt.target || this; evt.currentTarget = this; (handlers.get(evt.type) || []).forEach(fn => fn(evt)); },
    closest: function(sel) { return (sel === '#' + id || sel.includes(id)) ? this : null; },
    querySelectorAll: () => [], querySelector: sel => { const c = makeElement(id + '_' + sel); children.push(c); return c; }
  };
}
function getOrCreate(id) { if (!elements.has(id)) elements.set(id, makeElement(id)); return elements.get(id); }
['hud-skill-bar', 'skill-potion', 'skill-fire', 'skill-slot-w', 'skill-thunder', 'skill-frost', 'skill-primary', 'skill-dodge', 'overlay-pause', 'modal-settings', 'modal-item-link-tooltip', 'chat-expanded-panel'].forEach(id => getOrCreate(id));
const doc = {
  getElementById: id => getOrCreate(id), querySelector: sel => getOrCreate(sel.replace('#', '')),
  querySelectorAll: sel => sel.includes('[id^="modal-"]:not(.hidden)') ? Array.from(elements.entries()).filter(([id, el]) => id.startsWith('modal-') && !el.classList.contains('hidden')).map(([, el]) => el) : [],
  activeElement: { tagName: 'BODY' }, readyState: 'complete',
  addEventListener: (t, fn) => { if (!docListeners.has(t)) docListeners.set(t, []); docListeners.get(t).push(fn); },
  removeEventListener: (t, fn) => { if (docListeners.has(t)) docListeners.set(t, docListeners.get(t).filter(h => h !== fn)); },
  dispatchEvent: evt => (docListeners.get(evt.type) || []).forEach(fn => fn(evt))
};
const win = { isGamePaused: false, document: doc, performance: { now: () => 1000 }, requestAnimationFrame: () => 1, cancelAnimationFrame: () => {}, addEventListener: () => {}, removeEventListener: () => {}, resetJoystick: () => { win.resetJoystickCalled = true; }, resetJoystickCalled: false };
global.window = win; global.document = doc; global.resetJoystick = win.resetJoystick; global.performance = win.performance; global.requestAnimationFrame = win.requestAnimationFrame; global.cancelAnimationFrame = win.cancelAnimationFrame;
Úscript_bodyÚreturnc                 ó"  — t           › d| › d�}t          j        ddd|gddt          t          ¦  «        ¬¦  «        }|j        dk    rt          d	|j        › d
|j        › �¦  «        ‚t          j
        |j                             ¦   «         ¦  «        S )zQExecutes a JavaScript test harness in Node.js with simulated browser environment.z
(async () => {
  try {
zJ
  } catch (err) {
    console.error(err);
    process.exit(1);
  }
})();
Únodez--input-type=modulez-eT)Úcapture_outputÚtextÚcwdr   zNode execution failed:
ú
)ÚMOCK_DOM_PREAMBLEÚ
subprocessÚrunÚstrÚPROJECT_ROOTÚ
returncodeÚRuntimeErrorÚstderrÚstdoutÚjsonÚloadsÚstrip)r	   Ú	bootstrapÚress      ú:C:\Projects\FreeExile\tests\unit\test_game_pause_system.pyÚrun_node_harnessr    >   s´   € å$ð  eð  eÀ;ð  eð  eð  e€IÝ
Œ.˜&Ð"7¸¸yÐIÐZ^ÐeiÕorÕsñ  pAô  pAð  Bñ  Bô  B€CØ
„~˜ÒÐÝÐP°c´jÐPÐPÀCÄJÐPÐPÑQÔQÐQÝŒ:�c”j×&Ò&Ñ(Ô(Ñ)Ô)Ð)ó    c                   ó*   — e Zd ZdZdd„Zdd„Zdd„ZdS )ÚTestPauseStateAndControllerzDVerifies state management, overlay toggling, and controller exports.r
   Nc                 ó8  — d}t          |¦  «        }|d         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd|iz  }t	          t          j        |¦  «        ¦  «        ‚d	x}x}}|d
         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd|iz  }t	          t          j        |¦  «        ¦  «        ‚d	x}x}}|d         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd|iz  }t	          t          j        |¦  «        ¦  «        ‚d	x}x}}|d         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd|iz  }t	          t          j        |¦  «        ¦  «        ‚d	x}x}}d	S )zIInitial state must have isGamePaused === false and #overlay-pause hidden.a  
        const rendererCode = fs.readFileSync('./client/webapp/js/engine/canvas_renderer.js', 'utf8');
        eval(rendererCode);
        const overlay = document.getElementById('overlay-pause');
        console.log(JSON.stringify({
            isGamePaused: window.isGamePaused,
            overlayHidden: overlay.classList.contains('hidden'),
            hasSetGamePaused: typeof window.setGamePaused === 'function',
            hasToggleGamePause: typeof window.toggleGamePause === 'function'
        }));
        ÚisGamePausedF©Úis©z%(py1)s is %(py4)s©Úpy1Úpy4úassert %(py6)sÚpy6NÚoverlayHiddenTÚhasSetGamePausedÚhasToggleGamePause©r    Ú
@pytest_arÚ_call_reprcompareÚ	_safereprÚAssertionErrorÚ_format_explanation©ÚselfÚjs_codeÚdataÚ@py_assert0Ú@py_assert3Ú@py_assert2Ú@py_format5Ú@py_format7s           r   Ú.test_initial_state_unpaused_and_overlay_hiddenzJTestPauseStateAndController.test_initial_state_unpaused_and_overlay_hiddenJ   sÄ  € ð
ˆõ   Ñ(Ô(ˆØ�NÔ#Ð, uÐ,Ð# uÐ,Ð,Ð,Ð,Õ,Ô,Ð,Ð,Ð,Ð,Ð# uÐ,Ñ,Ô,Õ,Ô,Ð#Ñ,Ô,Õ,Ô, uÑ,Ô,Ð,Ð,Ñ,Ð,Ð,Ð,Ð,Ð,Ñ,Ð,Õ,Õ,Ô,Ð,Ñ,Ô,Ñ,Ô,Ð,Ð,Ð,Ð,Ð,Ð,Ð,Ø�OÔ$Ð,¨Ð,Ð$¨Ð,Ð,Ð,Ð,Õ,Ô,Ð,Ð,Ð,Ð,Ð$¨Ð,Ñ,Ô,Õ,Ô,Ð$Ñ,Ô,Õ,Ô,¨Ñ,Ô,Ð,Ð,Ñ,Ð,Ð,Ð,Ð,Ð,Ñ,Ð,Õ,Õ,Ô,Ð,Ñ,Ô,Ñ,Ô,Ð,Ð,Ð,Ð,Ð,Ð,Ð,ØÐ&Ô'Ð/¨4Ð/Ð'¨4Ð/Ð/Ð/Ð/Õ/Ô/Ð/Ð/Ð/Ð/Ð'¨4Ð/Ñ/Ô/Õ/Ô/Ð'Ñ/Ô/Õ/Ô/¨4Ñ/Ô/Ð/Ð/Ñ/Ð/Ð/Ð/Ð/Ð/Ñ/Ð/Õ/Õ/Ô/Ð/Ñ/Ô/Ñ/Ô/Ð/Ð/Ð/Ð/Ð/Ð/Ð/ØÐ(Ô)Ð1¨TÐ1Ð)¨TÐ1Ð1Ð1Ð1Õ1Ô1Ð1Ð1Ð1Ð1Ð)¨TÐ1Ñ1Ô1Õ1Ô1Ð)Ñ1Ô1Õ1Ô1¨TÑ1Ô1Ð1Ð1Ñ1Ð1Ð1Ð1Ð1Ð1Ñ1Ð1Õ1Õ1Ô1Ð1Ñ1Ô1Ñ1Ô1Ð1Ð1Ð1Ð1Ð1Ð1Ð1Ð1Ð1r!   c                 óx  — d}t          |¦  «        }|d         d         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd	|iz  }t	          t          j        |¦  «        ¦  «        ‚d
x}x}}|d         d         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd	|iz  }t	          t          j        |¦  «        ¦  «        ‚d
x}x}}|d         d         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd	|iz  }t	          t          j        |¦  «        ¦  «        ‚d
x}x}}|d         d         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd	|iz  }t	          t          j        |¦  «        ¦  «        ‚d
x}x}}|d         d         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd	|iz  }t	          t          j        |¦  «        ¦  «        ‚d
x}x}}d
S )zZsetGamePaused(true) shows overlay and resets joystick; setGamePaused(false) hides overlay.a~  
        const rendererCode = fs.readFileSync('./client/webapp/js/engine/canvas_renderer.js', 'utf8');
        eval(rendererCode);
        const overlay = document.getElementById('overlay-pause');
        window.setGamePaused(true);
        const stateAfterPause = { isPaused: window.isGamePaused, overlayHidden: overlay.classList.contains('hidden'), joystickReset: window.resetJoystickCalled };
        window.setGamePaused(false);
        const stateAfterResume = { isPaused: window.isGamePaused, overlayHidden: overlay.classList.contains('hidden') };
        console.log(JSON.stringify({ stateAfterPause, stateAfterResume }));
        ÚstateAfterPauseÚisPausedTr&   r(   r)   r,   r-   Nr.   FÚjoystickResetÚstateAfterResumer1   r7   s           r   Ú2test_set_game_paused_controls_overlay_and_joystickzNTestPauseStateAndController.test_set_game_paused_controls_overlay_and_joystick]   s‰  € ð	ˆõ   Ñ(Ô(ˆØÐ%Ô& zÔ2Ð:°dÐ:Ð2°dÐ:Ð:Ð:Ð:Õ:Ô:Ð:Ð:Ð:Ð:Ð2°dÐ:Ñ:Ô:Õ:Ô:Ð2Ñ:Ô:Õ:Ô:°dÑ:Ô:Ð:Ð:Ñ:Ð:Ð:Ð:Ð:Ð:Ñ:Ð:Õ:Õ:Ô:Ð:Ñ:Ô:Ñ:Ô:Ð:Ð:Ð:Ð:Ð:Ð:Ð:ØÐ%Ô& Ô7Ð@¸5Ð@Ð7¸5Ð@Ð@Ð@Ð@Õ@Ô@Ð@Ð@Ð@Ð@Ð7¸5Ð@Ñ@Ô@Õ@Ô@Ð7Ñ@Ô@Õ@Ô@¸5Ñ@Ô@Ð@Ð@Ñ@Ð@Ð@Ð@Ð@Ð@Ñ@Ð@Õ@Õ@Ô@Ð@Ñ@Ô@Ñ@Ô@Ð@Ð@Ð@Ð@Ð@Ð@Ð@ØÐ%Ô& Ô7Ð?¸4Ð?Ð7¸4Ð?Ð?Ð?Ð?Õ?Ô?Ð?Ð?Ð?Ð?Ð7¸4Ð?Ñ?Ô?Õ?Ô?Ð7Ñ?Ô?Õ?Ô?¸4Ñ?Ô?Ð?Ð?Ñ?Ð?Ð?Ð?Ð?Ð?Ñ?Ð?Õ?Õ?Ô?Ð?Ñ?Ô?Ñ?Ô?Ð?Ð?Ð?Ð?Ð?Ð?Ð?ØÐ&Ô'¨
Ô3Ð<°uÐ<Ð3°uÐ<Ð<Ð<Ð<Õ<Ô<Ð<Ð<Ð<Ð<Ð3°uÐ<Ñ<Ô<Õ<Ô<Ð3Ñ<Ô<Õ<Ô<°uÑ<Ô<Ð<Ð<Ñ<Ð<Ð<Ð<Ð<Ð<Ñ<Ð<Õ<Õ<Ô<Ð<Ñ<Ô<Ñ<Ô<Ð<Ð<Ð<Ð<Ð<Ð<Ð<ØÐ&Ô'¨Ô8Ð@¸DÐ@Ð8¸DÐ@Ð@Ð@Ð@Õ@Ô@Ð@Ð@Ð@Ð@Ð8¸DÐ@Ñ@Ô@Õ@Ô@Ð8Ñ@Ô@Õ@Ô@¸DÑ@Ô@Ð@Ð@Ñ@Ð@Ð@Ð@Ð@Ð@Ñ@Ð@Õ@Õ@Ô@Ð@Ñ@Ô@Ñ@Ô@Ð@Ð@Ð@Ð@Ð@Ð@Ð@Ð@Ð@r!   c                 ó4  — d}t          |¦  «        }|d         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd|iz  }t	          t          j        |¦  «        ¦  «        ‚d	x}x}}|d
         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd|iz  }t	          t          j        |¦  «        ¦  «        ‚d	x}x}}|d         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd|iz  }t	          t          j        |¦  «        ¦  «        ‚d	x}x}}d	S )z7toggleGamePause() toggles state between true and false.a”  
        const rendererCode = fs.readFileSync('./client/webapp/js/engine/canvas_renderer.js', 'utf8');
        eval(rendererCode);
        const initial = window.isGamePaused;
        window.toggleGamePause();
        const first = window.isGamePaused;
        window.toggleGamePause();
        const second = window.isGamePaused;
        console.log(JSON.stringify({ initial, first, second }));
        ÚinitialFr&   r(   r)   r,   r-   NÚfirstTÚsecondr1   r7   s           r   Ú'test_toggle_game_pause_alternates_statezCTestPauseStateAndController.test_toggle_game_pause_alternates_statep   s  € ð	ˆõ   Ñ(Ô(ˆØ�IŒÐ' %Ð'ˆ %Ð'Ð'Ð'Ð'Õ'Ô'Ð'Ð'Ð'Ð'ˆ %Ð'Ñ'Ô'Õ'Ô'ˆÑ'Ô'Õ'Ô' %Ñ'Ô'Ð'Ð'Ñ'Ð'Ð'Ð'Ð'Ð'Ñ'Ð'Õ'Õ'Ô'Ð'Ñ'Ô'Ñ'Ô'Ð'Ð'Ð'Ð'Ð'Ð'Ð'Ø�GŒ}Ð$ Ð$ˆ} Ð$Ð$Ð$Ð$Õ$Ô$Ð$Ð$Ð$Ð$ˆ} Ð$Ñ$Ô$Õ$Ô$ˆ}Ñ$Ô$Õ$Ô$ Ñ$Ô$Ð$Ð$Ñ$Ð$Ð$Ð$Ð$Ð$Ñ$Ð$Õ$Õ$Ô$Ð$Ñ$Ô$Ñ$Ô$Ð$Ð$Ð$Ð$Ð$Ð$Ð$Ø�HŒ~Ð& Ð&ˆ~ Ð&Ð&Ð&Ð&Õ&Ô&Ð&Ð&Ð&Ð&ˆ~ Ð&Ñ&Ô&Õ&Ô&ˆ~Ñ&Ô&Õ&Ô& Ñ&Ô&Ð&Ð&Ñ&Ð&Ð&Ð&Ð&Ð&Ñ&Ð&Õ&Õ&Ô&Ð&Ñ&Ô&Ñ&Ô&Ð&Ð&Ð&Ð&Ð&Ð&Ð&Ð&Ð&r!   ©r
   N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r@   rF   rK   © r!   r   r#   r#   G   sZ   € € € € € ØNÐNð2ð 2ð 2ð 2ð&Að Að Að Að&'ð 'ð 'ð 'ð 'ð 'r!   r#   c                   ó2   — e Zd ZdZdd„Zdd„Zdd„Zdd„ZdS )	Ú%TestSettingsModalAndEscapeIntegrationzGVerifies pause integration with Settings modal and Escape key handling.r
   Nc                 ó8  — d}t          |¦  «        }|d         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd|iz  }t	          t          j        |¦  «        ¦  «        ‚d	x}x}}|d
         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd|iz  }t	          t          j        |¦  «        ¦  «        ‚d	x}x}}|d         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd|iz  }t	          t          j        |¦  «        ¦  «        ‚d	x}x}}|d         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd|iz  }t	          t          j        |¦  «        ¦  «        ‚d	x}x}}d	S )z>Opening settings modal pauses game; closing settings unpauses.a   
        const rendererCode = fs.readFileSync('./client/webapp/js/engine/canvas_renderer.js', 'utf8');
        eval(rendererCode);
        const { openSettingsModal, closeSettingsModal } = await import('./client/webapp/js/ui/feedback.js');
        const modal = document.getElementById('modal-settings');
        openSettingsModal();
        const pausedOnOpen = window.isGamePaused, modalVisible = !modal.classList.contains('hidden');
        closeSettingsModal();
        const pausedOnClose = window.isGamePaused, modalHidden = modal.classList.contains('hidden');
        console.log(JSON.stringify({ pausedOnOpen, modalVisible, pausedOnClose, modalHidden }));
        ÚpausedOnOpenTr&   r(   r)   r,   r-   NÚmodalVisibleÚpausedOnCloseFÚmodalHiddenr1   r7   s           r   Ú1test_settings_modal_open_and_close_triggers_pausezWTestSettingsModalAndEscapeIntegration.test_settings_modal_open_and_close_triggers_pause…   sÂ  € ð
ˆõ   Ñ(Ô(ˆØ�NÔ#Ð+ tÐ+Ð# tÐ+Ð+Ð+Ð+Õ+Ô+Ð+Ð+Ð+Ð+Ð# tÐ+Ñ+Ô+Õ+Ô+Ð#Ñ+Ô+Õ+Ô+ tÑ+Ô+Ð+Ð+Ñ+Ð+Ð+Ð+Ð+Ð+Ñ+Ð+Õ+Õ+Ô+Ð+Ñ+Ô+Ñ+Ô+Ð+Ð+Ð+Ð+Ð+Ð+Ð+Ø�NÔ#Ð+ tÐ+Ð# tÐ+Ð+Ð+Ð+Õ+Ô+Ð+Ð+Ð+Ð+Ð# tÐ+Ñ+Ô+Õ+Ô+Ð#Ñ+Ô+Õ+Ô+ tÑ+Ô+Ð+Ð+Ñ+Ð+Ð+Ð+Ð+Ð+Ñ+Ð+Õ+Õ+Ô+Ð+Ñ+Ô+Ñ+Ô+Ð+Ð+Ð+Ð+Ð+Ð+Ð+Ø�OÔ$Ð-¨Ð-Ð$¨Ð-Ð-Ð-Ð-Õ-Ô-Ð-Ð-Ð-Ð-Ð$¨Ð-Ñ-Ô-Õ-Ô-Ð$Ñ-Ô-Õ-Ô-¨Ñ-Ô-Ð-Ð-Ñ-Ð-Ð-Ð-Ð-Ð-Ñ-Ð-Õ-Õ-Ô-Ð-Ñ-Ô-Ñ-Ô-Ð-Ð-Ð-Ð-Ð-Ð-Ð-Ø�MÔ"Ð* dÐ*Ð" dÐ*Ð*Ð*Ð*Õ*Ô*Ð*Ð*Ð*Ð*Ð" dÐ*Ñ*Ô*Õ*Ô*Ð"Ñ*Ô*Õ*Ô* dÑ*Ô*Ð*Ð*Ñ*Ð*Ð*Ð*Ð*Ð*Ñ*Ð*Õ*Õ*Ô*Ð*Ñ*Ô*Ñ*Ô*Ð*Ð*Ð*Ð*Ð*Ð*Ð*Ð*Ð*r!   c                 ó0  — d}t          |¦  «        }|d         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd|iz  }t	          t          j        |¦  «        ¦  «        ‚d	x}x}}|d
         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd|iz  }t	          t          j        |¦  «        ¦  «        ‚d	x}x}}d	S )z9Pressing Escape when no modal is open toggles game pause.aî  
        const rendererCode = fs.readFileSync('./client/webapp/js/engine/canvas_renderer.js', 'utf8');
        eval(rendererCode);
        await import('./client/webapp/js/main.js');
        document.dispatchEvent({ type: 'keydown', key: 'Escape' });
        const pausedFirst = window.isGamePaused;
        document.dispatchEvent({ type: 'keydown', key: 'Escape' });
        const pausedSecond = window.isGamePaused;
        console.log(JSON.stringify({ pausedFirst, pausedSecond }));
        ÚpausedFirstTr&   r(   r)   r,   r-   NÚpausedSecondFr1   r7   s           r   Ú,test_escape_toggles_pause_when_no_modal_openzRTestSettingsModalAndEscapeIntegration.test_escape_toggles_pause_when_no_modal_open˜   sp  € ð	ˆõ   Ñ(Ô(ˆØ�MÔ"Ð* dÐ*Ð" dÐ*Ð*Ð*Ð*Õ*Ô*Ð*Ð*Ð*Ð*Ð" dÐ*Ñ*Ô*Õ*Ô*Ð"Ñ*Ô*Õ*Ô* dÑ*Ô*Ð*Ð*Ñ*Ð*Ð*Ð*Ð*Ð*Ñ*Ð*Õ*Õ*Ô*Ð*Ñ*Ô*Ñ*Ô*Ð*Ð*Ð*Ð*Ð*Ð*Ð*Ø�NÔ#Ð, uÐ,Ð# uÐ,Ð,Ð,Ð,Õ,Ô,Ð,Ð,Ð,Ð,Ð# uÐ,Ñ,Ô,Õ,Ô,Ð#Ñ,Ô,Õ,Ô, uÑ,Ô,Ð,Ð,Ñ,Ð,Ð,Ð,Ð,Ð,Ñ,Ð,Õ,Õ,Ô,Ð,Ñ,Ô,Ñ,Ô,Ð,Ð,Ð,Ð,Ð,Ð,Ð,Ð,Ð,r!   c                 óX  — d}t          |¦  «        }|d         d         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd	|iz  }t	          t          j        |¦  «        ¦  «        ‚d
x}x}}|d         d         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd	|iz  }t	          t          j        |¦  «        ¦  «        ‚d
x}x}}|d         d         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd	|iz  }t	          t          j        |¦  «        ¦  «        ‚d
x}x}}d
S )zDPressing Escape while settings modal is open closes it and unpauses.aº  
        const rendererCode = fs.readFileSync('./client/webapp/js/engine/canvas_renderer.js', 'utf8');
        eval(rendererCode);
        const { openSettingsModal } = await import('./client/webapp/js/ui/feedback.js');
        await import('./client/webapp/js/main.js');
        openSettingsModal();
        const stateBefore = { isPaused: window.isGamePaused };
        document.dispatchEvent({ type: 'keydown', key: 'Escape' });
        const modalSettings = document.getElementById('modal-settings');
        const stateAfter = { isPaused: window.isGamePaused, modalHidden: modalSettings.classList.contains('hidden') };
        console.log(JSON.stringify({ stateBefore, stateAfter }));
        ÚstateBeforerC   Tr&   r(   r)   r,   r-   NÚ
stateAfterFrX   r1   r7   s           r   Ú.test_escape_closes_settings_modal_and_unpauseszTTestSettingsModalAndEscapeIntegration.test_escape_closes_settings_modal_and_unpauses¨   s(  € ðˆõ   Ñ(Ô(ˆØ�MÔ" :Ô.Ð6°$Ð6Ð.°$Ð6Ð6Ð6Ð6Õ6Ô6Ð6Ð6Ð6Ð6Ð.°$Ð6Ñ6Ô6Õ6Ô6Ð.Ñ6Ô6Õ6Ô6°$Ñ6Ô6Ð6Ð6Ñ6Ð6Ð6Ð6Ð6Ð6Ñ6Ð6Õ6Õ6Ô6Ð6Ñ6Ô6Ñ6Ô6Ð6Ð6Ð6Ð6Ð6Ð6Ð6Ø�LÔ! *Ô-Ð6°Ð6Ð-°Ð6Ð6Ð6Ð6Õ6Ô6Ð6Ð6Ð6Ð6Ð-°Ð6Ñ6Ô6Õ6Ô6Ð-Ñ6Ô6Õ6Ô6°Ñ6Ô6Ð6Ð6Ñ6Ð6Ð6Ð6Ð6Ð6Ñ6Ð6Õ6Õ6Ô6Ð6Ñ6Ô6Ñ6Ô6Ð6Ð6Ð6Ð6Ð6Ð6Ð6Ø�LÔ! -Ô0Ð8°DÐ8Ð0°DÐ8Ð8Ð8Ð8Õ8Ô8Ð8Ð8Ð8Ð8Ð0°DÐ8Ñ8Ô8Õ8Ô8Ð0Ñ8Ô8Õ8Ô8°DÑ8Ô8Ð8Ð8Ñ8Ð8Ð8Ð8Ð8Ð8Ñ8Ð8Õ8Õ8Ô8Ð8Ñ8Ô8Ñ8Ô8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8r!   c                 ó0  — d}t          |¦  «        }|d         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd|iz  }t	          t          j        |¦  «        ¦  «        ‚d	x}x}}|d
         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd|iz  }t	          t          j        |¦  «        ¦  «        ‚d	x}x}}d	S )zGClicking on #overlay-pause calls setGamePaused(false) and resumes game.a  
        const rendererCode = fs.readFileSync('./client/webapp/js/engine/canvas_renderer.js', 'utf8');
        eval(rendererCode);
        await import('./client/webapp/js/main.js');
        window.setGamePaused(true);
        const statePaused = window.isGamePaused;
        const overlay = document.getElementById('overlay-pause');
        document.dispatchEvent({ type: 'click', target: overlay });
        const stateResumed = window.isGamePaused;
        console.log(JSON.stringify({ statePaused, stateResumed }));
        ÚstatePausedTr&   r(   r)   r,   r-   NÚstateResumedFr1   r7   s           r   Ú!test_overlay_pause_click_unpauseszGTestSettingsModalAndEscapeIntegration.test_overlay_pause_click_unpauses»   sp  € ð
ˆõ   Ñ(Ô(ˆØ�MÔ"Ð* dÐ*Ð" dÐ*Ð*Ð*Ð*Õ*Ô*Ð*Ð*Ð*Ð*Ð" dÐ*Ñ*Ô*Õ*Ô*Ð"Ñ*Ô*Õ*Ô* dÑ*Ô*Ð*Ð*Ñ*Ð*Ð*Ð*Ð*Ð*Ñ*Ð*Õ*Õ*Ô*Ð*Ñ*Ô*Ñ*Ô*Ð*Ð*Ð*Ð*Ð*Ð*Ð*Ø�NÔ#Ð, uÐ,Ð# uÐ,Ð,Ð,Ð,Õ,Ô,Ð,Ð,Ð,Ð,Ð# uÐ,Ñ,Ô,Õ,Ô,Ð#Ñ,Ô,Õ,Ô, uÑ,Ô,Ð,Ð,Ñ,Ð,Ð,Ð,Ð,Ð,Ñ,Ð,Õ,Õ,Ô,Ð,Ñ,Ô,Ñ,Ô,Ð,Ð,Ð,Ð,Ð,Ð,Ð,Ð,Ð,r!   rL   )rM   rN   rO   rP   rY   r]   ra   re   rQ   r!   r   rS   rS   ‚   sj   € € € € € ØQÐQð+ð +ð +ð +ð&-ð -ð -ð -ð 9ð 9ð 9ð 9ð&-ð -ð -ð -ð -ð -r!   rS   c                   ó*   — e Zd ZdZdd„Zdd„Zdd„ZdS )Ú"TestSimulationGatingAndInputFreezezaVerifies that player input, skill activations, and kinematics are completely frozen during pause.r
   Nc                 ó0  — d}t          |¦  «        }|d         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd|iz  }t	          t          j        |¦  «        ¦  «        ‚d	x}x}}|d
         }d}||u }|slt          j        d|fd||f¦  «        t          j        |¦  «        t          j        |¦  «        dœz  }dd|iz  }t	          t          j        |¦  «        ¦  «        ‚d	x}x}}d	S )zJactivateSlot() returns false immediately when window.isGamePaused is true.a˜  
        const { SkillBarController } = await import('./client/webapp/js/ui/skill_bar_controller.js');
        const controller = new SkillBarController();
        controller.slots.set('fire', {
            slotId: 'fire', skillId: 'fire_slash', charges: null, maxCharges: null,
            cooldownRemaining: 0, cooldownTotal: 5.0, onActivate: () => {}
        });
        window.isGamePaused = false;
        const successWhenUnpaused = controller.activateSlot('fire');
        window.isGamePaused = true;
        const successWhenPaused = controller.activateSlot('fire');
        console.log(JSON.stringify({ successWhenUnpaused, successWhenPaused }));
        ÚsuccessWhenUnpausedTr&   r(   r)   r,   r-   NÚsuccessWhenPausedFr1   r7   s           r   Ú*test_skill_activation_rejected_when_pausedzMTestSimulationGatingAndInputFreeze.test_skill_activation_rejected_when_pausedÐ   sr  € ðˆõ   Ñ(Ô(ˆØÐ)Ô*Ð2¨dÐ2Ð*¨dÐ2Ð2Ð2Ð2Õ2Ô2Ð2Ð2Ð2Ð2Ð*¨dÐ2Ñ2Ô2Õ2Ô2Ð*Ñ2Ô2Õ2Ô2¨dÑ2Ô2Ð2Ð2Ñ2Ð2Ð2Ð2Ð2Ð2Ñ2Ð2Õ2Õ2Ô2Ð2Ñ2Ô2Ñ2Ô2Ð2Ð2Ð2Ð2Ð2Ð2Ð2ØÐ'Ô(Ð1¨EÐ1Ð(¨EÐ1Ð1Ð1Ð1Õ1Ô1Ð1Ð1Ð1Ð1Ð(¨EÐ1Ñ1Ô1Õ1Ô1Ð(Ñ1Ô1Õ1Ô1¨EÑ1Ô1Ð1Ð1Ñ1Ð1Ð1Ð1Ð1Ð1Ñ1Ð1Õ1Õ1Ô1Ð1Ñ1Ô1Ñ1Ô1Ð1Ð1Ð1Ð1Ð1Ð1Ð1Ð1Ð1r!   c                 óT  — t                                d¬¦  «        }d}||v }|s—t          j        d|fd||f¦  «        t          j        |¦  «        dt          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        nddœz  }dd	|iz  }t          t          j	        |¦  «        ¦  «        ‚d
x}}d}||v }|s—t          j        d|fd||f¦  «        t          j        |¦  «        dt          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        nddœz  }dd	|iz  }t          t          j	        |¦  «        ¦  «        ‚d
x}}d}||v }|s—t          j        d|fd||f¦  «        t          j        |¦  «        dt          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        nddœz  }dd	|iz  }t          t          j	        |¦  «        ¦  «        ‚d
x}}d}||v }|s—t          j        d|fd||f¦  «        t          j        |¦  «        dt          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        nddœz  }dd	|iz  }t          t          j	        |¦  «        ¦  «        ‚d
x}}d
S )zRCanvas renderer code contains strict !isPaused gate around kinematics and updates.úutf-8©Úencodingz.const isPaused = Boolean(window.isGamePaused);©Úin©z%(py1)s in %(py3)sÚcontent©r*   Úpy3úassert %(py5)sÚpy5Nzif (!isPaused) {zrenderDt = isPaused ? 0 : dtz"!isPaused && screenShake.timer > 0)
ÚCANVAS_RENDERER_JSÚ	read_textr2   r3   r4   Ú@py_builtinsÚlocalsÚ_should_repr_global_namer5   r6   ©r8   rs   r;   r=   Ú@py_format4Ú@py_format6s         r   Ú)test_kinematics_frozen_in_canvas_rendererzLTestSimulationGatingAndInputFreeze.test_kinematics_frozen_in_canvas_rendererã   s2  € å$×.Ò.¸Ð.Ñ@Ô@ˆØ?ÐJÐ?À7ÐJÐJÐJÐJÕJÔJÐJÐJÐJÐJÐ?À7ÐJÑJÔJÕJÔJÐ?ÑJÔJÐJÕJÔJÑJÔJÐJÐJÕJÔJÀ7ÑJÔJÐJÕJÔJÀ7ÑJÔJÐJÐJÐJÐJÑJÐJÐJÐJÐJÐJÑJÐJÕJÕJÔJÐJÑJÔJÑJÔJÐJÐJÐJÐJÐJØ!Ð,Ð! WÐ,Ð,Ð,Ð,Õ,Ô,Ð,Ð,Ð,Ð,Ð! WÐ,Ñ,Ô,Õ,Ô,Ð!Ñ,Ô,Ð,Õ,Ô,Ñ,Ô,Ð,Ð,Õ,Ô, WÑ,Ô,Ð,Õ,Ô, WÑ,Ô,Ð,Ð,Ð,Ð,Ñ,Ð,Ð,Ð,Ð,Ð,Ñ,Ð,Õ,Õ,Ô,Ð,Ñ,Ô,Ñ,Ô,Ð,Ð,Ð,Ð,Ð,Ø-Ð8Ð-°Ð8Ð8Ð8Ð8Õ8Ô8Ð8Ð8Ð8Ð8Ð-°Ð8Ñ8Ô8Õ8Ô8Ð-Ñ8Ô8Ð8Õ8Ô8Ñ8Ô8Ð8Ð8Õ8Ô8°Ñ8Ô8Ð8Õ8Ô8°Ñ8Ô8Ð8Ð8Ð8Ð8Ñ8Ð8Ð8Ð8Ð8Ð8Ñ8Ð8Õ8Õ8Ô8Ð8Ñ8Ô8Ñ8Ô8Ð8Ð8Ð8Ð8Ð8Ø3Ð>Ð3°wÐ>Ð>Ð>Ð>Õ>Ô>Ð>Ð>Ð>Ð>Ð3°wÐ>Ñ>Ô>Õ>Ô>Ð3Ñ>Ô>Ð>Õ>Ô>Ñ>Ô>Ð>Ð>Õ>Ô>°wÑ>Ô>Ð>Õ>Ô>°wÑ>Ô>Ð>Ð>Ð>Ð>Ñ>Ð>Ð>Ð>Ð>Ð>Ñ>Ð>Õ>Õ>Ô>Ð>Ñ>Ô>Ñ>Ô>Ð>Ð>Ð>Ð>Ð>Ð>Ð>r!   c                 ó‚  — t                                d¬¦  «        }d}||v }|s—t          j        d|fd||f¦  «        t          j        |¦  «        dt          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        nddœz  }dd	|iz  }t          t          j	        |¦  «        ¦  «        ‚d
x}}d
S )zIcombat_skills.js canvas click handler contains isGamePaused early return.rm   rn   zAif (typeof window !== 'undefined' && window.isGamePaused) return;rp   rr   rs   rt   rv   rw   N)
ÚCOMBAT_SKILLS_JSry   r2   r3   r4   rz   r{   r|   r5   r6   r}   s         r   Ú-test_combat_skills_click_rejected_when_pausedzPTestSimulationGatingAndInputFreeze.test_combat_skills_click_rejected_when_pausedë   sç   € å"×,Ò,°gÐ,Ñ>Ô>ˆØRÐ]ÐRÐV]Ð]Ð]Ð]Ð]Õ]Ô]Ð]Ð]Ð]Ð]ÐRÐV]Ð]Ñ]Ô]Õ]Ô]ÐRÑ]Ô]Ð]Õ]Ô]Ñ]Ô]Ð]Ð]Õ]Ô]ÐV]Ñ]Ô]Ð]Õ]Ô]ÐV]Ñ]Ô]Ð]Ð]Ð]Ð]Ñ]Ð]Ð]Ð]Ð]Ð]Ñ]Ð]Õ]Õ]Ô]Ð]Ñ]Ô]Ñ]Ô]Ð]Ð]Ð]Ð]Ð]Ð]Ð]r!   rL   )rM   rN   rO   rP   rk   r€   rƒ   rQ   r!   r   rg   rg   Í   s\   € € € € € ØkÐkð2ð 2ð 2ð 2ð&?ð ?ð ?ð ?ð^ð ^ð ^ð ^ð ^ð ^r!   rg   c                   ó:   — e Zd ZdZd	d„Zd	d„Zd	d„Zd	d„Zd	d„ZdS )
Ú"TestCodeHygieneAndLayoutCompliancezWEnforces quantitative line caps, structural requirements, and no dummy implementations.r
   Nc                 óö  — t          t                               d¬¦  «                             ¦   «         ¦  «        }d}||k    }|s°t	          j        d|fd||f¦  «        dt          j        ¦   «         v st	          j        |¦  «        rt	          j	        |¦  «        ndt	          j	        |¦  «        dœz  }t	          j
        d|› d	�¦  «        d
z   d|iz  }t          t	          j        |¦  «        ¦  «        ‚dx}}dS )z6canvas_renderer.js must strictly not exceed 350 lines.rm   rn   é^  ©ú<=©z%(py0)s <= %(py3)sÚlines©Úpy0ru   zcanvas_renderer.js has z lines (exceeds 350 cap)ú
>assert %(py5)srw   N)Úlenrx   ry   Ú
splitlinesr2   r3   rz   r{   r|   r4   Ú_format_assertmsgr5   r6   ©r8   r‹   r=   Ú@py_assert1r~   r   s         r   Ú!test_canvas_renderer_line_cap_350zDTestCodeHygieneAndLayoutCompliance.test_canvas_renderer_line_cap_350ô   s  € åÕ&×0Ò0¸'Ð0ÑBÔB×MÒMÑOÔOÑPÔPˆØÐVˆu˜Š|ÐVÐVÐVÕVÔVÐVÐVÐVÐVˆu˜ÐVÑVÔVÐVÕVÔVÑVÔVÐVÐVÕVÔVˆuÑVÔVÐVÕVÔVˆuÑVÔVÐVÐVÕVÔV˜ÑVÔVÐVÐVÑVÐVÕVÔVÐV°uÐVÐVÐVÑVÔVÐVÑVÐVÐVÐVÑVÐVÕVÕVÔVÐVÑVÔVÑVÔVÐVÐVÐVÐVÐVÐVÐVr!   c                 óö  — t          t                               d¬¦  «                             ¦   «         ¦  «        }d}||k    }|s°t	          j        d|fd||f¦  «        dt          j        ¦   «         v st	          j        |¦  «        rt	          j	        |¦  «        ndt	          j	        |¦  «        dœz  }t	          j
        d|› d	�¦  «        d
z   d|iz  }t          t	          j        |¦  «        ¦  «        ‚dx}}dS )z.index.html must strictly not exceed 400 lines.rm   rn   i�  rˆ   rŠ   r‹   rŒ   zindex.html has z lines (exceeds 400 cap)rŽ   rw   N)r�   Ú
INDEX_HTMLry   r�   r2   r3   rz   r{   r|   r4   r‘   r5   r6   r’   s         r   Útest_index_html_line_cap_400z?TestCodeHygieneAndLayoutCompliance.test_index_html_line_cap_400ù   s  € å•J×(Ò(°'Ð(Ñ:Ô:×EÒEÑGÔGÑHÔHˆØÐNˆu˜Š|ÐNÐNÐNÕNÔNÐNÐNÐNÐNˆu˜ÐNÑNÔNÐNÕNÔNÑNÔNÐNÐNÕNÔNˆuÑNÔNÐNÕNÔNˆuÑNÔNÐNÐNÕNÔN˜ÑNÔNÐNÐNÑNÐNÕNÔNÐN¨uÐNÐNÐNÑNÔNÐNÑNÐNÐNÐNÑNÐNÕNÕNÔNÐNÑNÔNÑNÔNÐNÐNÐNÐNÐNÐNÐNr!   c                 ó|
  — t                                d¬¦  «        }d}||v }|s—t          j        d|fd||f¦  «        t          j        |¦  «        dt          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        nddœz  }dd	|iz  }t          t          j	        |¦  «        ¦  «        ‚d
x}}d}||v }|s—t          j        d|fd||f¦  «        t          j        |¦  «        dt          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        nddœz  }dd	|iz  }t          t          j	        |¦  «        ¦  «        ‚d
x}}d}||v }|s—t          j        d|fd||f¦  «        t          j        |¦  «        dt          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        nddœz  }dd	|iz  }t          t          j	        |¦  «        ¦  «        ‚d
x}}d}||v}|s—t          j        d|fd||f¦  «        t          j        |¦  «        dt          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        nddœz  }dd	|iz  }t          t          j	        |¦  «        ¦  «        ‚d
x}}| 
                    d¦  «        }| 
                    d¦  «        }g }d}	|	 }
||
k    }|}|rd}| }||k    }|}|�sXt          j        d|fd||
f¦  «        dt          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        ndt          j        |	¦  «        dœz  }dd|iz  }|                     |¦  «         |r‹t          j        d|fd||f¦  «        dt          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        ndt          j        |¦  «        dœz  }dd|iz  }|                     |¦  «         t          j        |d¦  «        i z  }dd|iz  }t          t          j	        |¦  «        ¦  «        ‚d
x}x}x}x}	x}
x}x}}||k     }|s×t          j        d |fd!||f¦  «        dt          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        nddt          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        ndd"œz  }t          j        d#¦  «        d$z   d%|iz  }t          t          j	        |¦  «        ¦  «        ‚d
}d
S )&zT#overlay-pause must exist inside #app-viewport, above #modal-container, with z-[35].rm   rn   zid="overlay-pause"rp   rr   rs   rt   rv   rw   Nzz-[35]u   Táº M Dá»ªNG / PAUSEDzid="modal-pause")únot in)z%(py1)s not in %(py3)szid="modal-container"é   )ú!=)z%(py2)s != -%(py5)sÚoverlay_idx)Úpy2rw   z%(py8)sÚpy8)z%(py10)s != -%(py13)sÚmodal_container_idx)Úpy10Úpy13z%(py16)sÚpy16r   zassert %(py19)sÚpy19)ú<)z%(py0)s < %(py2)s)r�   r�   z4#overlay-pause must be placed above #modal-containerz
>assert %(py4)sr+   )r–   ry   r2   r3   r4   rz   r{   r|   r5   r6   ÚfindÚappendÚ_format_boolopr‘   )r8   rs   r;   r=   r~   r   rœ   rŸ   r“   Ú@py_assert4Ú@py_assert6r<   Ú@py_assert12Ú@py_assert14Ú@py_assert11r?   Ú@py_format9Ú@py_format15Ú@py_format17Ú@py_format18Ú@py_format20Ú@py_format3r>   s                          r   Ú'test_index_html_pause_overlay_structurezJTestCodeHygieneAndLayoutCompliance.test_index_html_pause_overlay_structureþ   sM  € å×&Ò&°Ð&Ñ8Ô8ˆØ#Ð.Ð# wÐ.Ð.Ð.Ð.Õ.Ô.Ð.Ð.Ð.Ð.Ð# wÐ.Ñ.Ô.Õ.Ô.Ð#Ñ.Ô.Ð.Õ.Ô.Ñ.Ô.Ð.Ð.Õ.Ô. wÑ.Ô.Ð.Õ.Ô. wÑ.Ô.Ð.Ð.Ð.Ð.Ñ.Ð.Ð.Ð.Ð.Ð.Ñ.Ð.Õ.Õ.Ô.Ð.Ñ.Ô.Ñ.Ô.Ð.Ð.Ð.Ð.Ð.ØÐ"ˆx˜7Ð"Ð"Ð"Ð"Õ"Ô"Ð"Ð"Ð"Ð"ˆx˜7Ð"Ñ"Ô"Õ"Ô"ˆxÑ"Ô"Ð"Õ"Ô"Ñ"Ô"Ð"Ð"Õ"Ô"˜7Ñ"Ô"Ð"Õ"Ô"˜7Ñ"Ô"Ð"Ð"Ð"Ð"Ñ"Ð"Ð"Ð"Ð"Ð"Ñ"Ð"Õ"Õ"Ô"Ð"Ñ"Ô"Ñ"Ô"Ð"Ð"Ð"Ð"Ð"Ø&Ð1Ð&¨'Ð1Ð1Ð1Ð1Õ1Ô1Ð1Ð1Ð1Ð1Ð&¨'Ð1Ñ1Ô1Õ1Ô1Ð&Ñ1Ô1Ð1Õ1Ô1Ñ1Ô1Ð1Ð1Õ1Ô1¨'Ñ1Ô1Ð1Õ1Ô1¨'Ñ1Ô1Ð1Ð1Ð1Ð1Ñ1Ð1Ð1Ð1Ð1Ð1Ñ1Ð1Õ1Õ1Ô1Ð1Ñ1Ô1Ñ1Ô1Ð1Ð1Ð1Ð1Ð1Ø!Ð0Ð!¨Ð0Ð0Ð0Ð0Õ0Ô0Ð0Ð0Ð0Ð0Ð!¨Ð0Ñ0Ô0Õ0Ô0Ð!Ñ0Ô0Ð0Õ0Ô0Ñ0Ô0Ð0Ð0Õ0Ô0¨Ñ0Ô0Ð0Õ0Ô0¨Ñ0Ô0Ð0Ð0Ð0Ð0Ñ0Ð0Ð0Ð0Ð0Ð0Ñ0Ð0Õ0Õ0Ô0Ð0Ñ0Ô0Ñ0Ô0Ð0Ð0Ð0Ð0Ð0Ø—l’lÐ#7Ñ8Ô8ˆØ%ŸlšlÐ+AÑBÔBÐØ>Ð>˜qÐ>˜q˜bÐ>ˆ{˜bÒ Ð>Ð>Ð>Ð>Ð>¸QÐ>¸Q¸BÐ>Ð%8¸BÒ%>Ð>Ð>Ð>Ð>Ñ>Õ>Ô>Ð>Ð>Ð>Ð>ˆ{˜bÐ>Ñ>Ô>Ð>Õ>Ô>Ñ>Ô>Ð>Ð>Õ>Ô>ˆ{Ñ>Ô>Ð>Õ>Ô>ˆ{Ñ>Ô>Ð>Ð>Õ>Ô>˜qÑ>Ô>Ð>Ð>Ñ>Ð>Ð>Ð>Ð>Ð>Ñ>Ð>Ð>×>Ò>Ð>Ñ>Ô>Ð>Ð>Ð>Õ>Ô>Ð>Ð>Ð>Ð>Ð%8¸BÐ>Ñ>Ô>Ð>Õ>Ô>Ñ>Ô>Ð>Ð>Õ>Ô>Ð%8Ñ>Ô>Ð>Õ>Ô>Ð%8Ñ>Ô>Ð>Ð>Õ>Ô>¸QÑ>Ô>Ð>Ð>Ñ>Ð>Ð>Ð>Ð>Ð>Ñ>Ð>Ð>×>Ò>Ð>Ñ>Ô>Ð>Õ>Ô>Ð>Ð>Ñ>Ô>Ð>Ñ>Ð>Ð>Ð>Ð>Ð>Ñ>Ð>Õ>Õ>Ô>Ð>Ñ>Ô>Ñ>Ô>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ð>ØÐ0Ò0ÐhÐhÐhÕhÔhÐhÐhÐhÐhˆ{Ð0ÐhÑhÔhÐhÕhÔhÑhÔhÐhÐhÕhÔhˆ{ÑhÔhÐhÕhÔhˆ{ÑhÔhÐhÐhÐhÕhÔhÑhÔhÐhÐhÕhÔhÐ0ÑhÔhÐhÕhÔhÐ0ÑhÔhÐhÐhÐhÐhÑhÐhÕhÔhÐ2hÑhÔhÐhÑhÐhÐhÐhÑhÐhÕhÕhÔhÐhÑhÔhÑhÔhÐhÐhÐhÐhÐhr!   c                 ór  — t          t                               d¬¦  «                             ¦   «         ¦  «        }d}||k    }|s°t	          j        d|fd||f¦  «        dt          j        ¦   «         v st	          j        |¦  «        rt	          j	        |¦  «        ndt	          j	        |¦  «        dœz  }t	          j
        d|› d	�¦  «        d
z   d|iz  }t          t	          j        |¦  «        ¦  «        ‚dx}}d}||k    }|s°t	          j        d|fd||f¦  «        dt          j        ¦   «         v st	          j        |¦  «        rt	          j	        |¦  «        ndt	          j	        |¦  «        dœz  }t	          j
        d|› d�¦  «        d
z   d|iz  }t          t	          j        |¦  «        ¦  «        ‚dx}}dS )zGfeedback.js line count must remain <= 350 soft cap and <= 500 hard cap.rm   rn   r‡   rˆ   rŠ   r‹   rŒ   zfeedback.js has ú lines (exceeds 350 soft cap)rŽ   rw   Néô  ú lines (exceeds 500 hard cap))r�   ÚFEEDBACK_JSry   r�   r2   r3   rz   r{   r|   r4   r‘   r5   r6   r’   s         r   Útest_feedback_js_line_capsz=TestCodeHygieneAndLayoutCompliance.test_feedback_js_line_caps
  sî  € å•K×)Ò)°7Ð)Ñ;Ô;×FÒFÑHÔHÑIÔIˆØÐTˆu˜Š|ÐTÐTÐTÕTÔTÐTÐTÐTÐTˆu˜ÐTÑTÔTÐTÕTÔTÑTÔTÐTÐTÕTÔTˆuÑTÔTÐTÕTÔTˆuÑTÔTÐTÐTÕTÔT˜ÑTÔTÐTÐTÑTÐTÕTÔTÐT°ÐTÐTÐTÑTÔTÐTÑTÐTÐTÐTÑTÐTÕTÕTÔTÐTÑTÔTÑTÔTÐTÐTÐTÐTÐTØÐTˆu˜Š|ÐTÐTÐTÕTÔTÐTÐTÐTÐTˆu˜ÐTÑTÔTÐTÕTÔTÑTÔTÐTÐTÕTÔTˆuÑTÔTÐTÕTÔTˆuÑTÔTÐTÐTÕTÔT˜ÑTÔTÐTÐTÑTÐTÕTÔTÐT°ÐTÐTÐTÑTÔTÐTÑTÐTÐTÐTÑTÐTÕTÕTÔTÐTÑTÔTÑTÔTÐTÐTÐTÐTÐTÐTÐTr!   c                 ór  — t          t                               d¬¦  «                             ¦   «         ¦  «        }d}||k    }|s°t	          j        d|fd||f¦  «        dt          j        ¦   «         v st	          j        |¦  «        rt	          j	        |¦  «        ndt	          j	        |¦  «        dœz  }t	          j
        d|› d	�¦  «        d
z   d|iz  }t          t	          j        |¦  «        ¦  «        ‚dx}}d}||k    }|s°t	          j        d|fd||f¦  «        dt          j        ¦   «         v st	          j        |¦  «        rt	          j	        |¦  «        ndt	          j	        |¦  «        dœz  }t	          j
        d|› d�¦  «        d
z   d|iz  }t          t	          j        |¦  «        ¦  «        ‚dx}}dS )zSskill_bar_controller.js line count must remain <= 350 soft cap and <= 500 hard cap.rm   rn   r‡   rˆ   rŠ   r‹   rŒ   zskill_bar_controller.js has rµ   rŽ   rw   Nr¶   r·   )r�   ÚSKILL_BAR_JSry   r�   r2   r3   rz   r{   r|   r4   r‘   r5   r6   r’   s         r   Ú#test_skill_bar_controller_line_capszFTestCodeHygieneAndLayoutCompliance.test_skill_bar_controller_line_caps  sî  € å•L×*Ò*°GÐ*Ñ<Ô<×GÒGÑIÔIÑJÔJˆØÐ`ˆu˜Š|Ð`Ð`Ð`Õ`Ô`Ð`Ð`Ð`Ð`ˆu˜Ð`Ñ`Ô`Ð`Õ`Ô`Ñ`Ô`Ð`Ð`Õ`Ô`ˆuÑ`Ô`Ð`Õ`Ô`ˆuÑ`Ô`Ð`Ð`Õ`Ô`˜Ñ`Ô`Ð`Ð`Ñ`Ð`Õ`Ô`Ð`¸EÐ`Ð`Ð`Ñ`Ô`Ð`Ñ`Ð`Ð`Ð`Ñ`Ð`Õ`Õ`Ô`Ð`Ñ`Ô`Ñ`Ô`Ð`Ð`Ð`Ð`Ð`ØÐ`ˆu˜Š|Ð`Ð`Ð`Õ`Ô`Ð`Ð`Ð`Ð`ˆu˜Ð`Ñ`Ô`Ð`Õ`Ô`Ñ`Ô`Ð`Ð`Õ`Ô`ˆuÑ`Ô`Ð`Õ`Ô`ˆuÑ`Ô`Ð`Ð`Õ`Ô`˜Ñ`Ô`Ð`Ð`Ñ`Ð`Õ`Ô`Ð`¸EÐ`Ð`Ð`Ñ`Ô`Ð`Ñ`Ð`Ð`Ð`Ñ`Ð`Õ`Õ`Ô`Ð`Ñ`Ô`Ñ`Ô`Ð`Ð`Ð`Ð`Ð`Ð`Ð`r!   rL   )	rM   rN   rO   rP   r”   r—   r³   r¹   r¼   rQ   r!   r   r…   r…   ñ   s”   € € € € € ØaÐaðWð Wð Wð Wð
Oð Oð Oð Oð

ið 
ið 
ið 
iðUð Uð Uð Uðað að að að að ar!   r…   )rP   Úbuiltinsrz   Ú_pytest.assertion.rewriteÚ	assertionÚrewriter2   r   r   Úpathlibr   ÚpytestÚ__file__ÚresolveÚparentr   ÚCLIENT_WEBAPPrx   r–   r¸   ÚMAIN_JSr»   r‚   r   r   Údictr    r#   rS   rg   r…   rQ   r!   r   ú<module>rÉ      sì  ððð ð € € € € € € € € € € € € €€€€Ø Ð Ð Ð Ø Ð Ð Ð Ð Ð Ø €€€àˆt�H‰~Œ~×%Ò%Ñ'Ô'Ô.Ô5Ô<€Ø˜xÑ'¨(Ñ2€Ø" TÑ)¨HÑ4Ð7KÑKÐ Ø˜\Ñ)€
Ø˜dÑ" TÑ)¨MÑ9€Ø
˜$Ñ
 Ñ
*€Ø˜tÑ# dÑ*Ð-FÑF€Ø  4Ñ'¨(Ñ2Ð5GÑGÐ ðÐ ðD* #ð *¨$ð *ð *ð *ð *ð8'ð 8'ð 8'ð 8'ð 8'ñ 8'ô 8'ð 8'ðvH-ð H-ð H-ð H-ð H-ñ H-ô H-ð H-ðV!^ð !^ð !^ð !^ð !^ñ !^ô !^ð !^ðH#að #að #að #að #añ #aô #að #að #að #ar!   