§
    ¬	ÊjAÄ ã                  ó  — U d Z ddlmZ ddlZddlmZ ddlmZmZm	Z	m
Z
 ddlmZmZmZ ddlmZ dd	lmZ dd
lmZmZ ddlmZ eeeddœZded<   i dd“dd“dd“dd“dd“dd“dd“dd“dd “d!d"“d#d“d$d“d%d“d&d'“d(d“d)d“d*d“i d+d,“d-d.“d/d“d0d1“d2d3“d4d5“d6d7“d8d“d9d:“d;d“d<d=“d>d?“d@d“dAd“dBdC“dDd'“dEd“¥dFddGddHdd.ddIdJdKdLœ¥ZdedM<   dN                     g dO¢¦  «        ZdN                     g dP¢¦  «        Z edQ¦  «                             dRdSg¦  «        Z edQ¦  «                             g dT¢¦  «        Z dUZ!dVZ"dWZ#i dXdY“dZd[“d\d[“d]d[“d^d[“d_d[“d`d[“dadY“dbd[“dcd[“dddY“ded[“dfd[“dgdY“dhdY“didY“djd[“i dkd[“dld[“dmd[“dnd[“dodp“dqdr“dsdt“dud[“dvdY“dwdY“dxdy“dzdy“d{d[“d|d[“d}d[“d~d[“dd[“¥i d€d[“d�dY“d‚dY“dƒd[“d„d[“d…d“d†d“d‡dY“dˆd[“d‰d[“dŠdY“d‹dŒ“d�d“dŽd“d�e“d�e“d‘dy“¥dydydydYdYdYdYd[d’œ¥e¥Z$d“ed”<   d[dYdYd•œZ%d“ed–<   dd—d˜œZ&d“ed™<   dšZ'dÑdž„Z(dÒd¡„Z)d¢Z*dÓd£„Z+dÓd¤„Z,dÔd¦„Z-dÓd§„Z.dÓd¨„Z/dÓd©„Z0dÓdª„Z1dÓd«„Z2dÓd¬„Z3dÕd¯„Z4dÖd²„Z5dÓd³„Z6dÓd´„Z7dÑdµ„Z8d×d¸„Z9dØd»„Z:d¼dydd[d½œdÙd¿„Z;dÀZ< G dÁ„ dÂe	¦  «        Z=dÚdÆ„Z>dÇZ?dÛdÈ„Z@dYZAdÜdÊ„ZBdddd[dddd[dËœdÝdÐ„ZCdS )Þu  Translate an internal Profile into the Firefox prefs dict that the
patched Firefox binary expects.

The output dict keys map 1:1 to ``user.js`` preferences. Playwright passes
them via ``firefox_user_prefs=``. The patched binary propagates them to all
content processes over IPC; C++ patches read the ``zoom.stealth.*``
namespace.

The translation is split into:

  * ``_BASELINE`` - global stealth policy (RFP off, WebRTC leaks blocked,
    safebrowsing disabled, debugger detach, â€¦) plus Windows-canonical
    constants that don't depend on the Profile (system colors palette,
    WebGL extensions whitelist, speech voices, navigator identity).
  * ``translate_profile_to_prefs`` - overlays the Profile fields plus the
    user-supplied ``locale`` and ``timezone``.
é    )ÚannotationsN)ÚPath)ÚAnyÚDictÚ
NamedTupleÚOptionalé   )ÚOSCPU_OVERRIDEÚPLATFORM_OVERRIDEÚ
USER_AGENT)ÚProfile)ÚSessionLocale)Úpersona_forÚrender_noise_seed)Úconfigure_proxyz5.0 (Windows))zgeneral.useragent.overridezgeneral.platform.overridezgeneral.oscpu.overridezgeneral.appversion.overridezDict[str, str]Ú_NAVIGATOR_OVERRIDESzui.-moz-cellhighlightz#CECECEzui.-moz-dialogz#F0F0F0zui.-moz-dialogtextz#000000zui.-moz_menubarhovertextz#15141Azui.-moz_menuhoverz	#0000001Ezui.-moz_menuhovertextzui.-moz_oddtreerowz#FFFFFFzui.activeborderz#B4B4B4zui.activecaptionz#99B4D1zui.appworkspacez#ABABABzui.backgroundzui.buttonfacezui.buttonhighlightzui.buttonshadowz#A0A0A0zui.buttontextzui.buttonborderzui.captiontextzui.graytextz#6D6D6Dzui.highlightz#0078D7zui.highlighttextzui.inactiveborderz#F4F7FCzui.inactivecaptionz#BFCDDBzui.inactivecaptiontextz#434E54zui.infobackgroundz#FFFFE1zui.infotextzui.menuz#F9F9FBzui.menutextzui.scrollbarz#C8C8C8zui.threeddarkshadowz#696969zui.threedfacezui.threedhighlightzui.threedlightshadowz#E3E3E3zui.threedshadowz	ui.windowz#646464z#FFFF00z#0060DFz#0066CCz#EE0000z#551A8B)zui.windowframezui.windowtextzui.markzui.marktextzui.accentcolorzui.accentcolortextzui.selecteditemzui.selecteditemtextzui.-moz-hyperlinktextzui.-moz-activehyperlinktextzui.-moz-visitedhyperlinktextÚ_WIN_LIGHT_COLORSú,)ÚANGLE_instanced_arraysÚEXT_blend_minmaxÚEXT_color_buffer_half_floatÚEXT_float_blendÚEXT_frag_depthÚEXT_sRGBÚEXT_shader_texture_lodÚEXT_texture_compression_bptcÚEXT_texture_compression_rgtcÚEXT_texture_filter_anisotropicÚOES_element_index_uintÚOES_fbo_render_mipmapÚOES_standard_derivativesÚOES_texture_floatÚOES_texture_float_linearÚOES_texture_half_floatÚOES_texture_half_float_linearÚOES_vertex_array_objectÚWEBGL_color_buffer_floatÚWEBGL_compressed_texture_s3tcÚ"WEBGL_compressed_texture_s3tc_srgbÚWEBGL_debug_renderer_infoÚWEBGL_debug_shadersÚWEBGL_depth_textureÚWEBGL_draw_buffersÚWEBGL_lose_contextÚWEBGL_provoking_vertex)ÚEXT_color_buffer_floatr   r   r   r   r   ÚOES_draw_buffers_indexedr#   r%   ÚOVR_multiview2r(   r)   r*   r+   r.   r/   é
   zvideo/avc|swhwzvideo/hevc|swhw)
zvideo/mp4|avc1|111zvideo/mp4|avc3|111zvideo/mp4|hev1|111zvideo/mp4|hvc1|111zvideo/mp4|av01|111zvideo/mp4|vp09|111zvideo/webm|av01|111zvideo/webm|vp09|111zvideo/webm|vp8|110zvideo/webm|vp9|110)
ÚcaptionÚiconÚmenuzmessage-boxzsmall-captionz
status-barz-moz-pull-down-menuz-moz-buttonz	-moz-listz
-moz-field)ÚarÚelÚhez
x-cyrillicz	x-unicodez	x-westernz_https://github.com/feder-cr/firefox_antidetect_patch/releases/download/usage-counter/launch.txtzlayout.css.field-sizing.enabledTzprivacy.resistFingerprintingFz)privacy.resistFingerprinting.letterboxingz privacy.fingerprintingProtectionz'privacy.fingerprintingProtection.pbmodez8privacy.fingerprintingProtection.remoteOverrides.enabledz(privacy.baselineFingerprintingProtectionzmedia.peerconnection.enabledz media.peerconnection.ice.no_hostz-media.peerconnection.ice.default_address_onlyz1media.peerconnection.ice.obfuscate_host_addressesz#media.peerconnection.ice.proxy_onlyz#media.peerconnection.ice.relay_onlyz,media.peerconnection.use_document_iceserversznetwork.proxy.socks_remote_dnsznetwork.proxy.socks5_remote_dnsznetwork.proxy.failover_directz%security.ssl3.ecdhe_ecdsa_aes_128_shaz!browser.shell.checkDefaultBrowserzbrowser.aboutwelcome.enabledz%browser.startup.upgradeDialog.enabledz+zoom.stealth.apikey.google_location_serviceÚ'AIzaSyB0mAay6Zu8JTU8XTQtXJLri9eY9wISq6oz'zoom.stealth.apikey.google_safebrowsingÚ'AIzaSyC7jsptDS3am4tPx4r3nxis7IMjBc5Dovozzoom.stealth.apikey.mozillaz$7e40f68c-7938-4c5d-9f95-e61647c213ebzbrowser.aboutConfig.showWarningzdom.push.enabledzgeo.enabledzgeo.provider.network.urlÚ zservices.settings.serverz"browser.search.geoSpecificDefaultsz/browser.contentblocking.report.lockwise.enabledz.browser.contentblocking.report.monitor.enabledz*dom.private-attribution.submission.enabledzbrowser.translations.enableznetwork.predictor.enabledznetwork.dns.disablePrefetchz$network.dns.disablePrefetchFromHTTPSzfission.autostartzfission.autostart.sessionz#fission.webContentIsolationStrategyz dom.ipc.processCount.webIsolatedzdom.file.createInChildz-browser.safebrowsing.downloads.remote.enabledzapp.update.autozmedia.webspeech.synth.enabledz)zoom.stealth.webgl.shader_output_languageÚesslz$zoom.stealth.text.freetype_hintstylez$zoom.stealth.text.freetype_antialiasúzoom.stealth.webgl.extensionsúzoom.stealth.webgl2.extensionszzoom.stealth.webgl.int_params)úzoom.stealth.webgl.int2_paramsz$zoom.stealth.webgl.shader_precisionsúzoom.stealth.webgl.float_paramsz"zoom.stealth.debugger.force_detachz%zoom.stealth.canvas.substitute_pixelsz$zoom.stealth.webgl.substitute_pixelszdom.webgpu.enabledzzoom.stealth.audio.fp_noiseúDict[str, Any]Ú	_BASELINE)zgfx.webrender.allzgfx.webrender.force-disabledzwebgl.force-enabledÚ_LINUX_XVFB_WORKAROUNDSé   )zsecurity.sandbox.gpu.levelzsecurity.sandbox.content.levelÚ_WIN_VIRT_DESKTOP_WORKAROUNDS)Ú2928Ú33901Ú33902ÚprefsÚreturnÚNonec                óÊ  — t          |                      dd¦  «        pd¦  «        }|sdS g g }}|                     d¦  «        D ]>}|                     dd¦  «        d         }|t          v r|n|                     |¦  «         Œ?|sdS d                     |¦  «        | d<   t          |                      dd¦  «        pd¦  «        }d                     |r|gng |z   ¦  «        | d<   dS )	a
  Move the spec-float pairs out of int2_params and into float_params.

    Done here rather than in the pool data so it holds for every persona and for
    any pool regenerated later, and so the reason travels with the code instead
    of with fourteen JSON rows.
    r@   r<   Nr   ú|r	   r   rA   )ÚstrÚgetÚsplitÚ_WEBGL_FLOAT_PAIR_ENUMSÚappendÚjoin)rJ   ÚsrcÚkeepÚmovedÚentryÚenumÚexistings          úDC:\Projects\Muse2API\.venv\Lib\site-packages\invisible_core/prefs.pyÚ_route_float_pairsr\   1  s	  € õ ˆe�iŠiÐ8¸"Ñ=Ô=ÐCÀÑ
DÔ
D€CØð ØˆØ�bˆ%€DØ—’˜3‘”ð Kð KˆØ�{Š{˜3 Ñ"Ô" 1Ô%ˆØÕ1Ð1Ð1ˆˆ°t×CÒCÀEÑJÔJÐJÐJØð ØˆØ.1¯hªh°t©n¬n€EÐ
*Ñ+Ý�5—9’9Ð>ÀÑCÔCÐIÀrÑJÔJ€HØ/2¯xªxØÐ	'ˆ(ˆˆ R¨5Ñ0ñ02ô 02€EÐ
+Ñ,Ð,Ð,ó    Úprofiler   c                ó  — t          |j        j        |j        j        ¦  «        }|rN|d                              ¦   «         D ]#\  }}|dk    rt          |¦  «        | d<   Œ|| |<   Œ$t          | ¦  «         n
d| d<   d| d<   |S )u¡  The validated WebGL persona, and the reason it is applied on every host.

    On Linux we spoof to a Windows ANGLE renderer string (profile.gpu.renderer)
    so cross-platform sessions report a consistent Windows GPU identity.
    On Windows/mac, spoofing a renderer string ALONE is unsafe - the ~81
    getParameter values stay real, so a name<->params hash mismatch FP Pro flags
    (setting GTX 980 over real Arc A750 params scored ~0.70). Instead we apply a
    VALIDATED PERSONA (see _webgl_personas): a {renderer, vendor} whose params are
    the shared ANGLE D3D11 caps (vendor-independent - identical on any host, per the
    ANGLE source) and whose extension list is FORCED below. That is a coherent fake
    GPU that passes FP Pro host-independently (the host's real GPU never leaks). If no
    validated persona exists for the sampled gpu_class yet, fall back to the host-real
    renderer (empty -> native ANGLE; SanitizeRenderer at ClientWebGLContext.cpp:2592).
    Apply the camoufox-derived real-Firefox GPU persona on EVERY host (Win/Linux/Mac).
    We must ALWAYS look Windows (rule), and the WebGL override is platform-independent:
    SanitizeRenderer (ClientWebGLContext.cpp) is pure string regex, and the param/extension
    overrides are pref-driven, so the C++ presents the SAME Windows ANGLE GPU regardless of
    the host's real GL backend (it never consults it when the pref is set). This is why a
    Windows GPU shows correctly even on a Linux/Mesa host (no more "Generic Renderer").

    Returns the persona, because `_apply_extension_lists` needs to know whether
    one was applied.

    â›” This READS the profile's persona, it does not choose one. It used to call
    `select_persona(profile.seed)`, which was a second answer to a question
    `generate_profile` had already answered, and the two diverged as soon as a
    `pin` arrived: the profile said one GPU and this function wrote another into
    the prefs, so `pin={"gpu.renderer": ...}` changed the label and never the
    browser. The choice lives in `_webgl_personas.choose_persona`, called once
    from `generate_profile`; here we look the chosen entry back up by the
    renderer+vendor the profile carries.
    rJ   zzoom.stealth.webgl2.enabledzwebgl.enable-webgl2r<   zzoom.stealth.webgl.rendererzzoom.stealth.webgl.vendor)r   ÚgpuÚrendererÚvendorÚitemsÚboolr\   )rJ   r^   ÚpersonaÚ_kÚ_vs        r[   Ú_apply_gpu_personarh   H  s£   € õB ˜'œ+Ô.°´Ô0BÑCÔC€GØð 2ð
 ˜gÔ&×,Ò,Ñ.Ô.ð 	ð 	‰FˆB�ØÐ2Ò2Ð2Ý/3°B©x¬x�Ð+Ñ,Ð,à��b‘	�	Ý˜5Ñ!Ô!Ð!Ð!à/1ˆÐ+Ñ,Ø/1ˆÐ)Ñ*Ø€Nr]   é   c                ó:   — d}|| d<   |dk    | d<   t           | d<   d S )NrE   zwebgl.msaa-samplesr   zwebgl.msaa-forcez#zoom.stealth.canvas.noise_skip_mask)Ú_CANVAS_NOISE_SKIP_MASK)rJ   r^   Ú_msaas      r[   Ú_apply_canvas_and_msaarm   �  s6   € ð. €Eð /4€EÐ
ÑØ.3°aªi€EÐ
ÑÝ3J€EÐ
/Ñ0Ð0Ð0r]   c                óZ  — |j         j        | d<   |j         j        | d<   |j         j        | d<   |j         j        | d<   |j         j        }|j        | d<   |j        | d<   |j        | d<   |j	        | d<   |j         j
        | d	<   |j         j        | d
<   t          |j         j        ¦  «        | d<   d S )Nzzoom.stealth.screen.widthzzoom.stealth.screen.heightzzoom.stealth.screen.color_depthzzoom.stealth.screen.taskbar_pxz zoom.stealth.screen.frame_borderz zoom.stealth.screen.maximized_uizzoom.stealth.screen.popup_uiz"zoom.stealth.screen.popup_positionz&zoom.stealth.screen.avail_device_widthz'zoom.stealth.screen.avail_device_heightzlayout.css.devPixelsPerPx)ÚscreenÚ	css_widthÚ
css_heightÚcolor_depthÚ
taskbar_pxÚframeÚborderÚmaximized_uiÚpopup_uiÚpopup_positionÚavail_device_widthÚavail_device_heightrO   Údpr)rJ   r^   rt   s      r[   Ú_apply_screenr|   ®  sÆ   € ð 18´Ô0H€EÐ
%Ñ&Ø07´Ô0I€EÐ
&Ñ'Ø07´Ô0J€EÐ
+Ñ,Ø07´Ô0I€EÐ
*Ñ+ð
 ŒNÔ €EØ49´L€EÐ
,Ñ-Ø49Ô4F€EÐ
,Ñ-Ø49´N€EÐ
(Ñ)Ø49Ô4H€EÐ
.Ñ/Ø7>´~Ô7X€EÐ
2Ñ3Ø7>´~Ô7Y€EÐ
3Ñ4õ 14°G´NÔ4FÑ0GÔ0G€EÐ
%Ñ&Ð&Ð&r]   úDict[str, Dict[str, int]]c                ó^   — | j         j        \  }}||dœ| j         j        | j         j        dœdœS )aÑ  The screen and viewport a browser context declares for this persona, in
    CSS pixels: ``{"viewport": {...}, "screen": {...}}``.

    The one derivation, read by every client for its default context. Until
    37.33.0 invisible_playwright, invisible_selenium and invisible_puppeteer
    each computed it from ``profile.screen`` with the same three lines - and
    all three took the PANEL's device pixels for CSS, which is
    ScreenProfile.css_width's story.
    )ÚwidthÚheight)Úviewportro   )ro   r�   rp   rq   )r^   r   r€   s      r[   Úcontext_geometryr‚   Ð  sF   € ð ”NÔ+�M€Eˆ6Ø"'°6Ð:Ð:Ø '¤Ô 8Ø!(¤Ô!:ð<ð <ð=ð =ð =r]   c                ó¸  — |j         j        | d<   |j         j        | d<   |j         j        dk    }|j         j        | d<   |rdnd| d<   d| d<   |rd	nd| d
<   |j         j        | d<   t          |j         j        ¦  «        | d<   t          |j         j        ¦  «        }|rdnd| d<   || d<   |j         j        | d<   |j         j	        rdnd}|| d<   || d<   || d<   || d<   d S )Nzzoom.stealth.hw_concurrencyzzoom.stealth.storage.quota_mbr   zzoom.stealth.max_touch_pointsr	   zdom.w3c_touch_events.enabledé   zzoom.stealth.pointer.primaryé   zzoom.stealth.pointer.allzzoom.stealth.voices.listzmedia.navigator.streams.fakeé   é   znetwork.cookie.cookieBehaviorzdom.storage.enabledzzoom.stealth.fonts.genericszui.prefersReducedMotionzui.prefersReducedTransparencyzui.invertedColorszui.useAccessibilityTheme)
ÚhardwareÚconcurrencyÚstorage_quota_mbÚmax_touch_pointsÚvoicesrd   Úfake_media_devicesÚstorage_enabledÚgenericsÚaccessibility_overrides)rJ   r^   ÚtouchÚ_storageÚ_a11ys        r[   Ú_apply_hardwarer”   à  s9  € ð 18Ô0@Ô0L€EÐ
'Ñ(Ø07Ô0@Ô0Q€EÐ
)Ñ*ð. ÔÔ-°Ò1€EØ07Ô0@Ô0Q€EÐ
)Ñ*ð 6;Ð0A°°À€EÐ
(Ñ)ð
 16€EÐ
(Ñ)Ø?DÐ0Q°°È5€EÐ
$Ñ%Ø07Ô0@Ô0G€EÐ
$Ñ%Ý04°WÔ5EÔ5XÑ0YÔ0Y€EÐ
(Ñ)õ: �GÔ$Ô4Ñ5Ô5€HØ5=Ð0D°°À1€EÐ
)Ñ*Ø08€EÐ
Ñ Ø07Ô0@Ô0I€EÐ
'Ñ(ð
 Ô!Ô9Ð@ˆAˆA¸q€EØ05€EÐ
#Ñ$Ø05€EÐ
)Ñ*Ø05€EÐ
Ñð 16€EÐ
$Ñ%Ð%Ð%r]   c                ó`   — |j         j        | d<   |j         j        | d<   |j         j        | d<   d S )Nzzoom.stealth.audio.sample_ratez$zoom.stealth.audio.output_latency_msz$zoom.stealth.audio.max_channel_count)ÚaudioÚsample_rateÚoutput_latency_msÚmax_channel_count©rJ   r^   s     r[   Ú_apply_audior›   ?  s8   € Ø4;´MÔ4M€EÐ
*Ñ+Ø4;´MÔ4S€EÐ
0Ñ1Ø4;´MÔ4S€EÐ
0Ñ1Ð1Ð1r]   c                ó°   — d| d<   |j         j        | d<   |j         j        | d<   |j         j        | d<   |j         j        | d<   t
          | d<   t          | d<   d S )	NTzmedia.eme.enabledzmedia.av1.enabledzmedia.encoder.webm.enabledzmedia.webm.enabledzmedia.mp4.enabledz!zoom.stealth.media.decode_supportz zoom.stealth.media.decoding_info)ÚcodecÚav1_enabledÚwebm_encoder_enabledÚmediasource_webmÚmediasource_mp4Ú_WIN_DECODE_SUPPORTÚ_WIN_DECODING_INFOrš   s     r[   Ú_apply_codecsr¤   E  sp   € ð( 15€EÐ
ÑØ07´Ô0I€EÐ
ÑØ07´Ô0R€EÐ
&Ñ'ð 18´Ô0N€EÐ
ÑØ07´Ô0M€EÐ
Ñõ 2E€EÐ
-Ñ.Ý0B€EÐ
,Ñ-Ð-Ð-r]   c                ó    — |j         }|j        | d<   |j        | d<   |j        | d<   |j        | d<   |j        | d<   |j        | d<   |j        | d<   dS )	a  The glyph rasterisation parameters, declared instead of asked for.

    Six values that the engine reads once at startup and then keeps for the
    whole process. Before this they came from the machine:
    `gfxDWriteFonts::UpdateClearTypeVars` ran defaults -> SYSTEM -> prefs, so
    the user's own ClearType tuning survived wherever a pref was absent, and on
    a development machine that produces the answer you wanted anyway. The
    binary now skips the system query entirely when stealth is on, so these
    prefs are the only source.

    The FreeType pair is not a mirror for its own sake. Skia's glyph mask gamma
    defaults to LINEAR on Linux against DWrite's 2.2, which is two different
    coverage curves over the same outlines, and no amount of matching fonts
    closes that. Measured 2026-08-08: setting it moves the canvas text hash on
    every value, so the lever reaches the rasteriser, but it does not converge
    on its own - the residual is the alpha quantisation, which is a separate
    fix on Skia's A8 mask path.
    z)gfx.font_rendering.cleartype_params.gammaz5gfx.font_rendering.cleartype_params.enhanced_contrastz3gfx.font_rendering.cleartype_params.cleartype_levelz3gfx.font_rendering.cleartype_params.pixel_structurez2gfx.font_rendering.cleartype_params.rendering_modez!gfx.font_rendering.freetype.gammaz-gfx.font_rendering.freetype.enhanced_contrastN)ÚfontÚcleartype_gammaÚcleartype_contrastÚcleartype_levelÚcleartype_pixel_structureÚcleartype_rendering_modeÚfreetype_gammaÚfreetype_contrast)rJ   r^   Úfs      r[   Ú_apply_rasterisationr¯   o  ss   € ð& 	Œ€AØEFÔEV€EÐ
5Ñ6ØEFÔEY€EÐ
AÑBØEFÔEV€EÐ
?Ñ@ØEFÔE`€EÐ
?Ñ@ØEFÔE_€EÐ
>Ñ?ØEFÔEU€EÐ
-Ñ.ØEFÔEX€EÐ
9Ñ:Ð:Ð:r]   c                ó8  — t           D ]'}|j        j        | d|› �<   |j        j        | d|› d�<   Œ(t          D ]}|j        j        | d|› �<   Œd| d<   d                     d„ |j        j        D ¦   «         ¦  «        | d<   |j        j        r|j        j        | d	<   d
S d
S )a.  The Windows system-font surface, from `profile.font`.

    This used to be a comment saying there was nothing to configure (below),
    and that was true only of the FONT LIST. The system-font surface is a
    different thing and it was not covered: with these prefs absent, Gecko
    answers `font: menu` from its own per-OS defaults, which on Linux name
    "Sans" at 13.3333px - a family that does not exist on Windows, on a build
    whose every other signal says Windows. Measured 2026-08-07, that single
    disagreement is what drove FpJS Pro to tampering=True on Linux with
    Windows clean, same seed and same IP.

    The 26 prefs also ship compiled into the binary's all.js. The duplication
    is deliberate: the binary has to stay right when launched WITHOUT this
    package, and the failure mode is not a subtle drift but a family name no
    Windows machine has. all.js is the floor; this layer is the source of
    truth that can move without a Firefox rebuild, and being a layer it can be
    overridden by `extra_prefs` like every other surface.
    zui.font.z.sizezfont.size.monospace.r3   zfont.minimum-size.thr   c              3  óN   K  — | ] }t          t          |¦  «        ¦  «        V — Œ!d S )N)rO   Úint)Ú.0Úvs     r[   ú	<genexpr>z_apply_fonts.<locals>.<genexpr>º  s?   è è € ð :8ð :8Ø��C�‰FŒF‰Œð:8ð :8ð :8ð :8ð :8ð :8r]   z!zoom.stealth.text.coverage_ladderzzoom.stealth.fonts.manifestN)	Ú_UI_FONT_ELEMENTSr¦   Ú	ui_familyÚui_sizeÚ_MONOSPACE_LANG_GROUPSÚmonospace_sizerT   Úalpha_ladderÚmanifest)rJ   r^   ÚelementÚlangs       r[   Ú_apply_fontsr¿   Œ  sô   € õ& %ð @ð @ˆØ&-¤lÔ&<ˆÐ"˜Ð"Ð"Ñ#ð ,3¬<Ô+?ˆÐ'˜Ð'Ð'Ð'Ñ(Ð(Ý&ð Kð KˆØ/6¬|Ô/JˆÐ+ TÐ+Ð+Ñ,Ð,ð %'€EÐ
 Ñ!ð 25·²ð :8ð :8Ø$œ\Ô6ð:8ñ :8ô :8ñ 28ô 28€EÐ
-Ñ.ð „|Ôð EØ/6¬|Ô/DˆÐ+Ñ,Ð,Ð,ðEð Er]   c                ó´   — t          |j        ¦  «        | d<   |j        rdnd| d<   d| d<   d| d<   d| d<   |j        s|                      t          ¦  «         d	S d	S )
zDDark mode, plus the Windows colours palette when the theme is light.zui.systemUsesDarkThemer   r	   z0layout.css.prefers-color-scheme.content-overridez1.0zui.textScaleFactorzui.hourCyclezui.selectTextfieldsOnKeyFocusN)r²   Ú
dark_themeÚupdater   rš   s     r[   Ú_apply_themerÃ   ×  s‰   € å&)¨'Ô*<Ñ&=Ô&=€EÐ
"Ñ#ð ÔÐ&ˆˆ Qð 
Ð
<Ñ=ðN #(€EÐ
Ñð €Eˆ.Ñð
 ./€EÐ
)Ñ*ØÔð (Ø�ŠÕ&Ñ'Ô'Ð'Ð'Ð'ð(ð (r]   Úlocaler   c                ó`   — |j         | d<   |j        | d<   |j        | d<   d| d<   |j         | d<   d S )Nzintl.accept_languageszgeneral.useragent.localezintl.locale.requestedr   zprivacy.spoof_englishzjuggler.locale.override)Úaccept_languagesÚprimary)rJ   rÄ   s     r[   Ú_apply_localerÈ     sO   € ð *0Ô)@€EÐ
!Ñ"ð *0¬€EÐ
$Ñ%Ø)/¬€EÐ
!Ñ"Ø)*€EÐ
!Ñ"ð6 *0Ô)@€EÐ
#Ñ$Ð$Ð$r]   ÚtimezonerO   c                ó   — |r|| d<   d S d S )Nzjuggler.timezone.override© )rJ   rÉ   s     r[   Ú_apply_timezonerÌ   L  s'   € Øð 6ð
 .6ˆÐ)Ñ*Ð*Ð*ð6ð 6r]   c                ó4   — t          |j        ¦  «        | d<   d S )Nzzoom.stealth.fpp.hw_seed)r   Úseedrš   s     r[   Ú_apply_render_seedrÏ   U  s   € õ ):¸'¼,Ñ(GÔ(G€EÐ
$Ñ%Ð%Ð%r]   c                óH   — |j         }d|dz	  dz  dz   › d|dz  dz   › �| d<   d S )Nz192.168.é   éþ   r	   ú.zzoom.stealth.webrtc.host_ip)rÎ   )rJ   r^   Ú_ss      r[   Ú_apply_webrtc_host_iprÕ   a  sC   € ð
 
Œ€BØ+Z°r¸Q±wÀ#±oÈÑ6IÐ+ZÐ+ZÈBÐQTÉHÐWXÉLÐ+ZÐ+Z€EÐ
'Ñ(Ð(Ð(r]   c                ód   — t           j                             d¦  «        s|sd| d<   d| d<   dS dS dS )aµ  Windows/mac extension list.

      - persona active -> the coherent webgl1/webgl2 extension lists (in the GPU's real
        native order) were ALREADY applied above from the GPU pool's `prefs`, alongside the
        matching renderer + params + shader-precisions. Nothing to do here.
      - no persona -> clear so the host-real renderer reports its native extension set
        (matches real vanilla captures for that host's GPU).
    Úlinuxr<   r>   r?   N)ÚsysÚplatformÚ
startswith)rJ   re   s     r[   Ú_apply_extension_listsrÛ   j  sS   € õ Œ<×"Ò" 7Ñ+Ô+ð 5°Gð 5Ø24ˆÐ-Ñ.Ø24ˆÐ.Ñ/Ð/Ð/ð5ð 5ð 5ð 5r]   Úvirtual_displayrd   c               óD  — t           j                             d¦  «        r5t                               ¦   «         D ]\  }}|                      ||¦  «         Œ|rEt           j        dk    r7t                               ¦   «         D ]\  }}|                      ||¦  «         ŒdS dS dS )zH`setdefault`, deliberately: anything a section above chose already wins.r×   Úwin32N)rØ   rÙ   rÚ   rD   rc   Ú
setdefaultrF   )rJ   rÜ   Úkr´   s       r[   Ú_apply_platform_workaroundsrá   x  s¼   € õ „|×Ò˜wÑ'Ô'ð #Ý+×1Ò1Ñ3Ô3ð 	#ð 	#‰DˆAˆqØ×Ò˜Q Ñ"Ô"Ð"Ð"ð ð #�3œ<¨7Ò2Ð2Ý1×7Ò7Ñ9Ô9ð 	#ð 	#‰DˆAˆqØ×Ò˜Q Ñ"Ô"Ð"Ð"ð#ð #Ð2Ð2ð	#ð 	#r]   Úextra_prefsúOptional[Dict[str, Any]]c                ó~   — |r8|                      ¦   «         D ]%\  }}|€|                      |d¦  «         Œ|| |<   Œ$dS dS )aU  LAST, so users can override anything we set.

    A value of None is a sentinel meaning "delete this pref entirely from the
    final dict" - useful for A/B harnesses that need to test what happens when
    an override is unset (vs set to empty string, which for some prefs like
    general.useragent.override means literally empty UA).
    N)rc   Úpop)rJ   râ   rà   r´   s       r[   Ú_apply_caller_overlayræ   …  sf   € ð ð Ø×%Ò%Ñ'Ô'ð 	ð 	‰DˆAˆqØˆyØ—	’	˜!˜TÑ"Ô"Ð"Ð"à��a‘�ðð ð	ð 	r]   zen-US©rÄ   rÉ   râ   rÜ   ú'SessionLocale | str | None'c               óT  — t          t          ¦  «        }t          || ¦  «        }t          || ¦  «         t	          || ¦  «         t          || ¦  «         t          || ¦  «         t          || ¦  «         t          || ¦  «         t          || ¦  «         t          || ¦  «         t          |t          j        |¦  «        ¦  «         t          ||¦  «         t          || ¦  «         t!          || ¦  «         t#          ||¦  «         t%          ||¬¦  «         t'          ||¦  «         |S )a  Return a complete prefs dict ready for Playwright's firefox_user_prefs=.

    Args:
        profile:         Bayesian-sampled fingerprint (from ``generate_profile``).
        locale:          The session language: the ``SessionLocale`` a launch
                         decided (``prepare_session_geo(...).locale``), or a
                         BCP-47 tag such as ``"en-US"``, which is decided
                         through ``decide_session_locale`` - the same
                         derivation, so both give identical prefs. None or ""
                         is en-US; "auto" is refused, since resolving it needs
                         the egress.
        timezone:        IANA timezone name, e.g. ``"America/New_York"``.
        extra_prefs:     Optional overlay applied LAST.
        virtual_display: When True on Windows, apply GPU-disabling workarounds
                         to prevent the GPU process from crashing on virtual
                         desktops that have no D3D11 backend.

    The body is the ORDER, and the order is the contract: the caller overlay
    runs last so it can override or delete anything, and the platform
    workarounds `setdefault` so they never take a choice away from a section
    above them. Each step keeps the reasoning it was written with.
    )rÜ   )ÚdictrC   rh   rm   r|   r”   r›   r¿   r¯   r¤   rÃ   rÈ   r   ÚofrÌ   rÏ   rÕ   rÛ   rá   ræ   )r^   rÄ   rÉ   râ   rÜ   rJ   re   s          r[   Útranslate_profile_to_prefsrì   –  s!  € õ< !¥™OœO€Eå  ¨Ñ0Ô0€GÝ˜5 'Ñ*Ô*Ð*Ý�%˜Ñ!Ô!Ð!Ý�E˜7Ñ#Ô#Ð#Ý�˜Ñ Ô Ð Ý�˜Ñ Ô Ð Ý˜ Ñ(Ô(Ð(Ý�%˜Ñ!Ô!Ð!Ý�˜Ñ Ô Ð Ý�%�Ô)¨&Ñ1Ô1Ñ2Ô2Ð2Ý�E˜8Ñ$Ô$Ð$Ý�u˜gÑ&Ô&Ð&Ý˜% Ñ)Ô)Ð)Ý˜5 'Ñ*Ô*Ð*Ý °ÐGÑGÔGÐGÝ˜% Ñ-Ô-Ð-à€Lr]   g      ø?c                  ó(   — e Zd ZU dZded<   ded<   dS )ÚComposedPrefsa|  The prefs, and the proxy Playwright still has to be told about.

    Two returns because `configure_proxy` has two outputs: it writes the SOCKS
    auth prefs (which the binary reads) and hands back the HTTP/HTTPS dict
    (which only Playwright can act on). A composer that returned prefs alone
    would force every caller to run the proxy step a second time to recover it.
    rB   rJ   úOptional[Dict[str, str]]Úplaywright_proxyN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú__annotations__rË   r]   r[   rî   rî   î  s6   € € € € € € ðð ð ÐÐÑØ.Ð.Ð.Ñ.Ð.Ð.r]   rî   Úhumanizer   Úfloatc                ó”   — | du rt           S 	 t          | ¦  «        }n# t          t          f$ r
 t           cY S w xY w|dk    r|nt           S )aý  The motion cap implied by a `humanize=` value, for any value.

    Anything unusable falls back to the default rather than raising or being
    written through. `get_default_stealth_prefs` used to do `float(humanize)`
    bare: `humanize="fast"` raised ValueError out of a pref builder, and
    `humanize=-1` wrote `stealthfox.humanize.maxTime = "-1.0"` into the profile.
    The wrapper's own copy of this function had been robust since 0.4.0; this is
    that behaviour, in the one place both now read.
    Tr   )ÚHUMANIZE_MAX_SECONDSr÷   Ú	TypeErrorÚ
ValueError)rö   Úvalues     r[   Úhumanize_max_secondsrý   ú  sf   € ð �4ÐÐÝ#Ð#ð$Ý�h‘”ˆˆøÝ•zÐ"ð $ð $ð $Ý#Ð#Ð#Ð#ð$øøøà˜A’I�Iˆ5ˆ5Õ#7Ð7s   � �8·8é    c                óX   — | sddiS dt          t          | ¦  «        ¦  «        t          dœS )a*  The `stealthfox.*` prefs implied by a `humanize=` value.

    Falsy turns the binary's own path expansion OFF and writes no cap, which is
    what a caller drawing its own trajectories needs: with both generators live
    the browser expands a path between each pair of the caller's waypoints.
    ústealthfox.humanizeFT)r   zstealthfox.humanize.maxTimezstealthfox.humanize.stepMs)rO   rý   ÚHUMANIZE_STEP_MS)rö   s    r[   Úhumanize_prefsr  !  sB   € ð ð .Ø% uÐ-Ð-à#Ý'*Õ+?ÀÑ+IÔ+IÑ'JÔ'Jõ '7ðð ð r]   Úshow_cursorc                ó$   — dt          | ¦  «        iS )uÏ  The `stealthfox.*` prefs implied by a `show_cursor=` value.

    â›” IT IS A DEMO SWITCH, NOT A STEALTH ONE, and the default does not change
    that: the overlay draws in the browser's own chrome document, which the
    page cannot reach, so a site learns nothing either way. What it changes is
    what a PERSON watching the monitor sees - a pointer gliding across a window
    with nobody touching the mouse reads as "this is a bot" to anyone glancing
    at the screen. That was the argument for shipping it off, it is still the
    argument, and the owner decided on 2026-08-28 to ship it ON anyway, the way
    Camoufox does. A caller who wants the old behaviour passes
    `show_cursor=False` and gets it.

    â›” AND IT IS DECLARED HERE, like every other engine switch, so the browser
    reads and never decides. The pref is written into the profile before the
    browser starts, so it is in force from the first window rather than from
    the second launch.
    zstealthfox.showcursor)rd   )r  s    r[   Úshow_cursor_prefsr  H  s   € ð$ $¥T¨+Ñ%6Ô%6Ð7Ð7r]   )rÄ   rÉ   râ   rÜ   Úproxyrö   r  Úsurvive_hard_killúOptional[str]r  rï   r  c               óÎ  — t          | ||||¬¦  «        }	|rt          ||	¦  «        nd}
|	                     dd¦  «         |	                     dt          ¦  «         |�"|	                     t          |¦  «        ¦  «         |	                     t          |€t          n|¦  «        ¦  «         |r,|	                     dd¦  «         |	                     dd¦  «         t          |	|
¦  «        S )	a=  Every pref a session runs with, in one place.

    Each layer above the fingerprint is a flag, and a flag left at its default
    means that layer is not applied - so a caller that wants only the
    fingerprint gets exactly what `translate_profile_to_prefs` returns.

    `humanize=None` is not the same as `humanize=False`: None leaves the two
    `stealthfox.humanize*` prefs untouched, which is what the direct-launch path
    has always done, and False writes the pref off. The distinction matters
    because the pref has a default compiled into the binary, and never writing
    it is not the same as writing it false.

    What each caller still owns is DELIVERY, which is the part that genuinely
    differs: the direct-launch path writes a `user.js`, the Playwright path
    passes a dict to `firefox_user_prefs=`.
    rç   Nz0widget.windows.window_occlusion_tracking.enabledFz invisible_firefox.usage_ping.urlz#toolkit.startup.max_resumed_crasheséÿÿÿÿz&browser.sessionstore.resume_from_crash)	rì   r   rß   ÚUSAGE_PING_URLrÂ   r  r  ÚDEFAULT_SHOW_CURSORrî   )r^   rÄ   rÉ   râ   rÜ   r  rö   r  r  rJ   rð   s              r[   Úcompose_session_prefsr  ]  s  € õ8 'ØØØØØ'ðñ ô €Eð 9>ÐG• u¨eÑ4Ô4Ð4À4Ðð> 
×ÒÐGÈÑOÔOÐOð 
×ÒÐ7½ÑHÔHÐHàÐØ�Š•^ HÑ-Ô-Ñ.Ô.Ð.ð 
‡L‚LÕ"Ø*Ð2ÕÐ¸ñEô Eñ Fô Fð Fàð Jð
 	×ÒÐ>ÀÑCÔCÐCØ×ÒÐAÀ5ÑIÔIÐIÝ˜Ð 0Ñ1Ô1Ð1r]   )rJ   rB   rK   rL   )rJ   rB   r^   r   )rJ   rB   r^   r   rK   rL   )r^   r   rK   r}   )rJ   rB   rÄ   r   rK   rL   )rJ   rB   rÉ   rO   rK   rL   )rJ   rB   rÜ   rd   rK   rL   )rJ   rB   râ   rã   rK   rL   )r^   r   rÄ   rè   rÉ   rO   râ   rã   rÜ   rd   rK   rB   )rö   r   rK   r÷   )rö   r   rK   rB   )r  r   rK   rB   )r^   r   rÄ   rè   rÉ   r  râ   rã   rÜ   rd   r  rï   rö   r   r  r   r  rd   rK   rî   )Drô   Ú
__future__r   rØ   Úpathlibr   Útypingr   r   r   r   Ú	constantsr
   r   r   Ú_fpforger   Ú_localer   Ú_webgl_personasr   r   Ú_proxyr   r   rõ   r   rT   Ú_WEBGL1_EXTENSIONSÚ_WEBGL2_EXTENSIONSÚchrr¢   r£   r¶   r¹   r  rC   rD   rF   rR   r\   rh   rk   rm   r|   r‚   r”   r›   r¤   r¯   r¿   rÃ   rÈ   rÌ   rÏ   rÕ   rÛ   rá   ræ   rì   rù   rî   rý   r  r  r  r  r  rË   r]   r[   ú<module>r     s�
  ððð ð ð" #Ð "Ð "Ð "Ð "Ð "à 
€
€
€
Ø Ð Ð Ð Ð Ð Ø 2Ð 2Ð 2Ð 2Ð 2Ð 2Ð 2Ð 2Ð 2Ð 2Ð 2Ð 2à DÐ DÐ DÐ DÐ DÐ DÐ DÐ DÐ DÐ DØ Ð Ð Ð Ð Ð Ø "Ð "Ð "Ð "Ð "Ð "Ø ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ø #Ð #Ð #Ð #Ð #Ð #ð #-Ø#4Ø#1ð $3ð!(ð (Ð ð ð ð ñ ð:[%ð  yð[%ð^  yð_[%ð`  yða[%ðb  yðc[%ðd  {ðe[%ðf  yðg[%ðh  yði[%ðj  Iðk[%ðl  Iðm[%ðn  Iðo[%ðp  Iðq[%ðr  Iðs[%ðt  Iðu[%ðv  Iðw[%ðx  Iðy[%ðz  Ið{[%ð|  Ið}[%ð [%ð~  Ið[%ð@  IðA[%ðB  IðC[%ðD  IðE[%ðF  IðG[%ðH  IðI[%ðJ  IðK[%ðL  IðM[%ðN  IðO[%ðP  IðQ[%ðR  IðS[%ðT  IðU[%ðV  IðW[%ðX  IðY[%ðZ  Ið[[%ð\  Ið][%ð^  Ið_[%ð [%ð` %.Ø$-Ø$-Ø$-Ø'0Ø$-Ø$-Ø$-Ø$-Ø$-Ø$-ðu[%ð [%ð [%Ð ð [ð [ð [ñ [ðH —X’Xð ð ð ñ ô Ð ð< —X’Xð ð ð ñ ô Ð ðl �c˜"‘g”g—l’lØØð$ñ ô Ð ð0 �S˜‘W”W—\’\ð #ð #ð #ñ ô Ð ðHÐ ðÐ ð@€ðP	ð( &¸$ð)P	ð, # Eð-P	ð. 0°ð/P	ð: 'ÀUð;P	ð< .ÀUð=P	ð> ?ÀUð?P	ðZ /ÀUð[P	ð| #¸$ð}P	ð~ '¸%ðP	ð@ 4¸%ðAP	ðB 8¸$ðCP	ðD *¸%ðEP	ðF *¸%ðGP	ðH 3¸$ðIP	ðh %¸$ðiP	ðj &¸$ðkP	ðl $¸%ðmP	ð P	ðB ,¸%ðCP	ð^ (¸%ð_P	ð` #¸%ðaP	ðb ,¸%ðcP	ðp 2Ð3\ðqP	ðr .Ð3\ðsP	ðt "Ð3YðuP	ðB &¸%ðCP	ð` ¸$ðaP	ðb ¸$ðcP	ð@ ¸"ðAP	ðJ	 ¸"ðK	P	ðL	 )¸%ðM	P	ðN	 6¸%ðO	P	ðP	 5¸%ðQ	P	ðR	 1¸%ðS	P	ðV	 "¸%ðW	P	ð P	ð P	ðl
  ¸%ðm
P	ðn
 "¸$ðo
P	ðp
 +¸$ðq
P	ð\ ¸%ð]P	ð^  ¸%ð_P	ð` *¸!ðaP	ðb '¸!ðcP	ðV ¸$ðWP	ðb 4¸%ðcP	ðj ¸%ðkP	ðP $¸$ðQP	ðx 0¸&ðyP	ðz +¸!ð{P	ð| +¸!ð}P	ðB $Ð:LðCP	ðD %Ð:LðEP	ðL $¸"ðMP	ð P	ðN ;=Ø:<Ø:<ð ;?ð ;?ð :>ð ;?ð ;@ðYP	ð P	ð P	ð^ ð_P	€	ð P	ð P	ð P	ñ P	ðv 05Ø/3Ø/3ð+ð +Ð ð ð ð ñ ðR #$ð '(ð71ð 1Ð ð ð ð ñ ðV 5Ð ð2ð 2ð 2ð 2ð.0ð 0ð 0ð 0ðH Ð ðKð Kð Kð Kð>Hð Hð Hð HðD=ð =ð =ð =ð \6ð \6ð \6ð \6ð~Tð Tð Tð Tð'Cð 'Cð 'Cð 'CðTYð Yð Yð Yð:>Eð >Eð >Eð >EðVC(ð C(ð C(ð C(ðL,Að ,Að ,Að ,Að^6ð 6ð 6ð 6ð	Hð 	Hð 	Hð 	Hð[ð [ð [ð [ð5ð 5ð 5ð 5ð
#ð 
#ð 
#ð 
#ðð ð ð ð( ,3ØØ,0Ø!ð1ð 1ð 1ð 1ð 1ð 1ðj Ð ð	/ð 	/ð 	/ð 	/ð 	/�Jñ 	/ô 	/ð 	/ð8ð 8ð 8ð 8ðH Ð ðð ð ð ðH Ð ð8ð 8ð 8ð 8ð0 ,0Ø"Ø,0Ø!Ø&*ØØØ#ðj2ð j2ð j2ð j2ð j2ð j2ð j2ð j2r]   