mw.loader.impl(function(){return["ext.quicksurveys.lib@",{"main":"resources/ext.quicksurveys.lib/init.js","files":{"resources/ext.quicksurveys.lib/init.js":function(require,module,exports){const QuickSurveyLib = require( './lib.js' );

mw.extQuickSurveys = QuickSurveyLib;

module.exports = QuickSurveyLib;
},"resources/ext.quicksurveys.lib/logEvent.js":function(require,module,exports){/**
 * Logs an event if possible.
 *
 * @param {string} schemaName
 * @param {Object} eventData
 */
module.exports = function ( schemaName, eventData ) {
	switch ( schemaName ) {
		case 'QuickSurveyInitiation':
		case 'QuickSurveysResponses':
			mw.track( 'event.' + schemaName, eventData );
			return;
		default:
			throw new Error( 'Unknown event logged' );
	}
};
},"resources/ext.quicksurveys.lib/lib.js":function(require,module,exports){const logEvent = require( './logEvent.js' );

/**
 * @typedef {Object} Audience
 * @property {string[]} [countries] that the survey should be targeted at
 * @property {number} [minEdits] a minimum number of edits the user must have
 *   if undefined there will be no lower bound
 * @property {number} [maxEdits] a maximum number of edits the user must have
 *   if undefined there will be no upper bound
 * @property {boolean} [anons] is the survey targetted to anons/logged in only?
 *   if undefined there will no limit
 * @property {string} [registrationStart] if the survey is targeted by registration
 * date, user had to join on or after this date. Date is in format YYYY-MM-DD
 * @property {string} [registrationEnd] if the survey is targeted by registration
 * date, user had to join on or before this date. Date is in format YYYY-MM-DD
 * @property {number[]} [pageIds]
 * @property {string[]} [userAgent]
 * @property {DateRange} [firstEdit]
 * @property {DateRange} [lastEdit]
 * @property {string[]} [userInGroup] list of any user groups to target
 */

/**
 * @typedef Answer
 * @property {string} label
 * @property {string|null|undefined} freeformTextLabel
 */

/**
 * @typedef QuestionDependency
 * @property {string} question
 * @property {string[]|null|undefined} answerIsOneOf
 */

/**
 * @typedef InternalQuestion
 * @property {string} name
 * @property {string} layout
 * @property {string} question
 * @property {string|null|undefined} description
 * @property {boolean|null|undefined} shuffleAnswersDisplay
 * @property {Answer[]} answers
 * @property {QuestionDependency[]|null|undefined} dependsOn
 */

/**
 * @typedef ExternalQuestion
 * @property {string} name
 * @property {string} question
 * @property {string|null|undefined} description
 * @property {string} link
 * @property {string|null|undefined} instanceTokenParameterName
 * @property {string|null|undefined} yesMsg
 * @property {string|null|undefined} noMsg
 */

/**
 * @typedef SurveyDefinition
 * @property {Audience} audience
 * @property {(InternalQuestion|ExternalQuestion)[]} questions
 * @property {number} coverage
 * @property {boolean} isInsecure
 * @property {string} module
 * @property {string} name
 * @property {Object} platforms
 * @property {string} privacyPolicy
 * @property {string|null} additionalInfo
 * @property {string|null} thankYouMessage
 * @property {string} type
 * @property {string|null} embedElementId Embedding location DOM element ID.
 */

/**
 * @typedef {Object} Geo
 * @property {string} country code of the user
 * @property {string} [region] code of the user
 * @property {string} [city] of the user
 * @property {number} [lat] of the user
 * @property {number} [lon] of the user
 */

/**
 * @typedef {Object} DateRange
 * @property {?string} [from]
 * @property {?string} [to]
 */

/**
 * Log impression when a survey is seen by the user
 *
 * @param {string} surveySessionToken
 * @param {string} pageviewToken
 * @param {string} surveyCodeName
 */
function logSurveyImpression( surveySessionToken, pageviewToken, surveyCodeName ) {
	const event = {
		surveySessionToken,
		pageviewToken,
		surveyCodeName,
		eventName: 'impression',
		performanceNow: Math.round( mw.now() )
	};

	const editCountBucket = mw.config.get( 'wgUserEditCountBucket' );

	if ( editCountBucket ) {
		event.editCountBucket = editCountBucket;
	}

	logEvent( 'QuickSurveyInitiation', event );
}

/**
 * Get a promise that resolves when half of the element has intersected with the device
 * viewport. If browser doesn't support IntersectionObserver the promise will be rejected.
 *
 * Note well that a promise can only resolve once.
 *
 * @param {HTMLElement} el The element
 * @return {jQuery.Promise}
 */
function getSeenObserver( el ) {
	const result = $.Deferred();

	if ( 'IntersectionObserver' in window ) {
		// Setup the area for observing.
		// By default the root is the viewport which is what we want.
		// See https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
		const observer = new IntersectionObserver(
			( ( entries ) => {
				const entry = entries && entries[ 0 ];
				if ( entry && entry.isIntersecting ) {
					// If intersecting resolve the promise,
					// and stop observing it to free up resources.
					observer.unobserve( el );
					result.resolve();
				}
			} ),
			{
				threshold: 1
			}
		);
		// This should only ever observe one element given the function returns a promise.
		observer.observe( el );
	} else {
		result.reject();
	}
	return result.promise();
}

/**
 * Insert the quick survey panel into the article either (in priority order)
 * (on small screens) after the first paragraph,
 * before the infobox,
 * before the first instance of a thumbnail,
 * before the first instance of a heading
 * or at the end of the article when no headings nor thumbnails exist.
 *
 * @param {jQuery.Object} $bodyContent to add the panel. If embedElementId is passed this will be ignored.
 * @param {jQuery.Object} $panel
 * @param {string|null} embedElementId Embedding location DOM element ID.
 * @param {boolean} isMobileLayout whether the screen is a mobile layout.
 */
function insertPanel( $bodyContent, $panel, embedElementId, isMobileLayout ) {
	let $place;
	let insertAfter = true;

	if ( embedElementId ) {
		$place = getEmbeddedElement( embedElementId );
		insertAfter = false;
	} else if ( isMobileLayout ) {
		// Find a paragraph in the first section to insert after
		$place = $bodyContent.find( '> div > div' ).eq( 0 ).find( ' > p' ).eq( 0 );
	}

	if ( $place && $place.length ) {
		if ( insertAfter ) {
			$panel.insertAfter( $place );
		} else {
			$place.append( $panel );
		}
	} else {
		$place = $bodyContent
			.find(
				[
					'.infobox',

					// Account for the Mobile Frontend section wrapper
					// around .thumb.
					'> div > div > .thumb',

					'> div > .thumb',
					'> .thumb',
					'.mw-heading'
				].join( ',' )
			)
			.filter( ':not(' + [
				// Minerva
				'.toc-mobile h2',
				// Vector
				'.toc h2'
			].join( ',' ) + ')' )
			.eq( 0 );
		if ( $place.length ) {
			$panel.insertBefore( $place );
		} else {
			// Insert this after the first paragraph (for pages with
			// just one paragraph) or the lead section/content
			// container when no suitable element can be found
			// (empty pages)
			$place = $bodyContent.find( 'p' ).eq( 0 );
			// Do this test separately for cases where no paragraph
			// elements are returned in document order so > div
			// would always come first. See
			// http://blog.jquery.com/2009/02/20/jquery-1-3-2-released/
			if ( !$place.length ) {
				// Note that this will only ever happen if you have
				// an article with no headings and only an empty
				// lead section. We only apply to the first one but
				// technically there should only ever be one.
				// eslint-disable-next-line no-jquery/no-global-selector
				$place = $( '> div' ).eq( 0 );
			}
			$panel.insertAfter( $place );
		}
	}
}

/**
 * Get the embedded survey target element by DOM id.
 *
 * @param {string} embedElementId Element to match for survey injection
 * @return {jQuery.Object}
 */
function getEmbeddedElement( embedElementId ) {
	const element = document.getElementById( embedElementId );
	return element ? $( element ) : $();
}

/**
 * Helper method that checks if a date is in a given range. The from and to
 * parameters are inclusive, and when set to null, extend to infinity.
 *
 * @param {string} date the date to range check
 * @param {?string} from start date (inclusive)
 * @param {?string} to end date (inclusive)
 * @return {boolean} return true when the provided date is in the specified range
 */
function dateInRange( date, from, to ) {
	const parsedDate = new Date( date + 'T00:00:00+00:00' );
	const parsedFrom = from ? new Date( from + 'T00:00:00+00:00' ) : new Date( false );
	const parsedTo = to ? new Date( to + 'T23:59:59+0000' ) : new Date();

	return parsedDate >= parsedFrom && parsedDate <= parsedTo;
}

/**
 * Helper method to verify that user registered in given time frame
 * Note: this check is inclusive
 *
 * @param {Object} user User object
 * @param {string} registrationStart date string in YYYY-MM-DD format
 * @param {string} registrationEnd date string in YYYY-MM-DD format
 * @return {boolean} return true when user between given time range
 */
function registrationDateNotInRange( user, registrationStart, registrationEnd ) {
	if ( user.getRegistration() === false ) {
		// we cannot detect user registration date, fail by default
		return true;
	}
	const from = registrationStart ? new Date( registrationStart + 'T00:00:00+00:00' ) : new Date( false );
	const to = registrationEnd ? new Date( registrationEnd + 'T23:59:59+0000' ) : new Date();

	return from > user.getRegistration() || user.getRegistration() > to;
}

/**
 * Check if audience user agent matches survey's target user agent.
 *
 * @param {Array} targetUserAgent
 * @return {boolean} true if user agent matches
 */
function isUsingTargetBrowser( targetUserAgent ) {
	const keywordToRegexMap = {
		KaiOS: /KaiOS[/\s](\d+\.\d+)/i,
		InternetExplorer: /MSIE (\d+\.\d+);/i,
		Chrome: /Chrome[/\s](\d+\.\d+)/i,
		Edge: /Edge\/\d+/i,
		Firefox: /Firefox[/\s](\d+\.\d+)/i,
		Opera: /OPR[/\s](\d+\.\d+)/i,
		Safari: /Safari[/\s](\d+\.\d+)/i
	};
	const targetChrome = targetUserAgent.includes( 'Chrome' );
	let uaMatch = 0;

	// Check each target user agent against the user's user agent.
	targetUserAgent.forEach( ( ua ) => {
		if ( Object.prototype.hasOwnProperty.call( keywordToRegexMap, ua ) &&
			keywordToRegexMap[ ua ].test( navigator.userAgent )
		) {
			++uaMatch;
			// User agent string for Chrome includes Safari, so the simple regex fails to prevent
			// showing a given survey to Chrome when Safari is targeted but Chrome is not.
			if ( ua === 'Safari' && !targetChrome && navigator.userAgent.includes( 'Chrome' ) ) {
				--uaMatch;
			}
		}
	} );
	return !!uaMatch;
}

/**
 * Check if a survey is suitable for the current user
 *
 * @param {Audience} audience
 * @param {Object} user object
 * @param {number|null} editCount of user (null if user is anon)
 * @param {Geo} [geo] geographical information of user (undefined if not known)
 * @param {number} pageId ID of the current page
 * @param {string} firstEdit date of the first edit the user made (YYYY-MM-DD)
 * @param {string} lastEdit date of the last edit the user made (YYYY-MM-DD)
 * @return {boolean}
 */
function isInAudience( audience, user, editCount, geo, pageId, firstEdit, lastEdit ) {
	const hasMinEditAudience = audience.minEdits !== undefined,
		hasMaxEditAudience = audience.maxEdits !== undefined,
		hasCountries = audience.countries !== undefined,
		hasPageIds = audience.pageIds !== undefined,
		hasTarget = audience.userAgent !== undefined && audience.userAgent.length > 0;

	if ( hasPageIds && !audience.pageIds.includes( pageId ) ) {
		return false;
	} else if ( ( audience.registrationStart || audience.registrationEnd ) &&
		registrationDateNotInRange( user, audience.registrationStart,
			audience.registrationEnd ) ) {
		return false;
	} else if (
		audience.firstEdit &&
		( !firstEdit || !dateInRange( firstEdit, audience.firstEdit.from, audience.firstEdit.to ) )
	) {
		return false;
	} else if (
		audience.lastEdit &&
		( !lastEdit || !dateInRange( lastEdit, audience.lastEdit.from, audience.lastEdit.to ) )
	) {
		return false;
	} else if ( audience.anons !== undefined && audience.anons !== user.isAnon() ) {
		return false;
	} else if ( editCount === null && hasMinEditAudience ) {
		return false;
	} else if (
		( hasMinEditAudience && editCount < audience.minEdits ) ||
		( hasMaxEditAudience && editCount > audience.maxEdits )
	) {
		return false;
	}
	geo = geo || { country: '??' };
	if ( hasCountries && !audience.countries.includes( geo.country ) ) {
		return false;
	} else if ( hasTarget && !isUsingTargetBrowser( audience.userAgent ) ) {
		return false;
	}
	if ( audience.userInGroup ) {
		const usersGroups = mw.config.get( 'wgUserGroups' );
		let inAnyTargetedGroup = audience.userInGroup.length === 0;
		for ( const group of audience.userInGroup ) {
			if ( usersGroups.includes( group ) ) {
				inAnyTargetedGroup = true;
				break;
			}
		}
		// If the user is not in any of the required groups, return false
		if ( !inAnyTargetedGroup ) {
			return false;
		}
	}
	return true;
}

/**
 * @param {string} queryString The survey's name or the string "true" to get a random survey
 * @param {Object[]} availableSurveys
 * @return {Object|undefined} Undefined if a survey with this name wasn't found
 */
function getSurveyFromQueryString( queryString, availableSurveys ) {
	if ( queryString === 'true' ) {
		return availableSurveys[ Math.floor( Math.random() * availableSurveys.length ) ];
	}

	// Backwards-compatibility: Drop now unused filter by survey type. Unnecessary because internal
	// and an external surveys with the same name can't exist anyway.
	queryString = queryString.replace( /^(in|ex)ternal-survey-/, '' );
	return availableSurveys.find( ( survey ) => survey.name === queryString );
}

/**
 * Get the storage key for the given survey.
 *
 * @param {Object} survey
 * @return {string} The survey localStorage key
 */
function getSurveyStorageKey( survey ) {
	return 'ext-quicksurvey-' + survey.name.replace( / /g, '-' );
}

/**
 * Get the survey token for the given survey.
 *
 * @param {Object} survey
 * @return {string} The survey token
 */
function getSurveyToken( survey ) {
	return mw.storage.get( getSurveyStorageKey( survey ) );
}

/**
 * Get the bucket for the given survey.
 * Initializes the survey storage with a token
 *
 * @param {Object} survey
 * @return {string} The bucket
 */
function getBucketForSurvey( survey ) {
	const a = survey.coverage;
	const control = 1 - survey.coverage;
	const storageId = getSurveyStorageKey( survey );
	let token = getSurveyToken( survey );

	if ( !token ) {
		// Generate a new token for each survey
		token = mw.user.generateRandomSessionId();
		mw.storage.set( storageId, token );
	}
	return mw.experiments.getBucket( {
		name: survey.name,
		enabled: true,
		buckets: {
			control: Number( control ),
			A: Number( a )
		}
	}, token );
}

/**
 * Check if the current platform matches one of the target platforms of a given survey.
 *
 * @param {Object} survey Options
 * @param {string|undefined} mobileMode The value of wgMFMode
 * @return {boolean}
 */
function surveyMatchesPlatform( survey, mobileMode ) {
	const platform = mobileMode ? 'mobile' : 'desktop';
	if ( Array.isArray( survey.platforms ) ) {
		return survey.platforms.includes( platform );
	} else {
		mw.log.warn( 'QuickSurvey: `platforms` as object is deprecated, use array instead' );
		return ( survey.platforms[ platform ] || [] ).includes( 'stable' );
	}
}

/**
 * Logs a survey impression when the survey is observed by user.
 * If the browser does not support IntersectionObserver it will log immediately.
 *
 * @param {HTMLElement} el
 * @param {string} surveySessionToken
 * @param {string} pageviewToken
 * @param {string} surveyName
 */
function reportWhenSeen( el, surveySessionToken, pageviewToken, surveyName ) {
	const done = function () {
		logSurveyImpression( surveySessionToken, pageviewToken, surveyName );
	};
	getSeenObserver( el ).then( done, done );
}

const makeSurveySessionToken = () => mw.user.sessionId() + '-quicksurveys';
const isTablet = () => window.innerWidth > 768;

/**
 * Inserts a survey into the page and logs a survey impression.
 * For older browsers, the survey impression will be logged, regardless
 * of whether it is seen.
 *
 * @param {SurveyDefinition} survey
 * @param {boolean} [includeSensitiveData] whether the survey responses can include
 *  sensitive data
 */
function insertSurvey( survey, includeSensitiveData ) {
	const $panel = $.createSpinner().addClass( 'ext-qs-loader-bar' ),
		// eslint-disable-next-line no-jquery/no-global-selector
		$bodyContent = $( '#bodyContent' ),
		surveySessionToken = makeSurveySessionToken(),
		dismissSurvey = function ( answers ) {
			mw.storage.set( getSurveyStorageKey( survey ), '~' );
			/**
			 * Fires when a portlet is successfully created.
			 *
			 * @event ~'ext.quicksurveys.dismiss'
			 * @memberof Hooks
			 * @param {Object} survey survey information
			 * @param {Object|string} [answers] answers for survey. String if user navigated to the external survey.
			 *  Undefined if the survey was exited without answering.
			 */
			mw.hook( 'ext.quicksurveys.dismiss' ).fire( survey, answers );
		},
		pageviewToken = mw.user.getPageviewToken(),
		isMobileLayout = !isTablet();

	insertPanel( $bodyContent, $panel, survey.embedElementId, isMobileLayout );
	const htmlDirection = document.getElementById( 'firstHeading' ).getAttribute( 'dir' );

	// survey.module contains i18n messages and code to render.
	// We load this asynchronously to avoid loading this all on page load for
	// pages where a survey will never be shown.
	// For example, some surveys are targetted at
	// users with certain edit counts, or certain browser.
	// See SurveyAudience for more information.
	mw.loader.using( [ survey.module ] ).then( ( require ) => {
		const module = require( 'ext.quicksurveys.lib.vue' );
		if ( module ) {
			module.render(
				require( 'vue' ),
				$panel[ 0 ],
				survey,
				dismissSurvey,
				surveySessionToken,
				pageviewToken,
				isMobileLayout,
				htmlDirection,
				logEvent,
				includeSensitiveData
			).then( ( el ) => {
				// Use the Vue element instead of $panel
				reportWhenSeen( el, surveySessionToken, pageviewToken, survey.name );
			} );
		}
	} );
}

/**
 * Check if a survey matches an element on the current page.
 *
 * @param {string} embedElementId Element to match for survey injection
 * @return {boolean}
 */
function isEmbeddedElementMatched( embedElementId ) {
	return getEmbeddedElement( embedElementId ).length > 0;
}

/**
 * Check if user preference has `displayquicksurveys` enabled.
 *
 * @return {boolean}
 */
function isQuickSurveysPrefEnabled() {
	return mw.user.options.get( 'displayquicksurveys' ) === 1;
}

/**
 * Choose and display a survey
 *
 * @param {string|null} surveyName Survey to force display of, if any. If value is
 *  `true` then the survey name will be attempted to be extracted from the query string.
 *   If surveyName is given then this disables platform checks and it is up to the developer
 *   to run these checks themselves.
 * @param {string} [embedElementId] optional ID of element in which to insert survey, when not defined
 *   the survey will be added to DOM based on survey definition and wiki default. You must defined surveyName
 *   when using this parameter.
 * @param {boolean} [forceDisplay] whether the survey should be displayed regardless of audience.
 * @param {boolean} [includeSensitiveInformation] defaults to false. When enabled this will collect
 *   information such as page. It is essential that this is only used where it is not possible for the
 *   page to contain the username. For example, if you are running a QuickSurvey on a user's page, do not
 *   enable this as the quick survey would no longer be anonymous.
 * @return {boolean} if the survey was successfully displayed. If `false` this indicates the user was not
 *  in the audience or the sample for the survey OR the survey doesn't exist.
 * @throws {Error} if invalid parameters
 */
function showSurvey( surveyName, embedElementId, forceDisplay, includeSensitiveData ) {
	if ( embedElementId && !surveyName ) {
		throw new Error( 'When using showSurvey with embedElementId, surveyName must be defined.' );
	}

	const embeddedSurveys = [];
	const availableSurveys = [];
	const enabledSurveys = require( './surveyData.json' );

	if ( forceDisplay ) {
		// Code path for when …?quicksurvey=… is used in the URL. Notes:
		// - This bypasses all bucket and audience checks.
		// - Only enabled surveys can be accessed like this.
		const enabledSurveyFromQueryString = getSurveyFromQueryString(
			surveyName,
			enabledSurveys
		);
		if ( enabledSurveyFromQueryString ) {
			mw.log.warn( `Sampling and audience for survey ${ enabledSurveyFromQueryString.name } has been disabled.
Do not run this in production setting.` );
			if ( embedElementId ) {
				enabledSurveyFromQueryString.embedElementId = embedElementId;
			}
			availableSurveys.push( enabledSurveyFromQueryString );
		}
	} else {
		// Find which surveys are available to the user
		enabledSurveys.forEach( ( survey ) => {
			// If a survey was named, restrict enabled surveys to the one requested
			// e.g. avoid showing all applicable surveys.
			if ( surveyName && surveyName !== survey.name ) {
				return;
			}
			// avoid overwriting default configuration
			const enabledSurvey = Object.assign( {}, survey );
			if (
				getSurveyToken( enabledSurvey ) !== '~' &&
				getBucketForSurvey( enabledSurvey ) === 'A' &&
				isInAudience(
					enabledSurvey.audience,
					mw.user,
					mw.config.get( 'wgUserEditCount' ),
					window.Geo,
					mw.config.get( 'wgArticleId' ),
					mw.config.get( 'wgQSUserFirstEditDate' ),
					mw.config.get( 'wgQSUserLastEditDate' )
				) &&
				surveyMatchesPlatform( enabledSurvey, mw.config.get( 'wgMFMode' ) )
			) {
				const targetId = embedElementId || enabledSurvey.embedElementId;
				if ( targetId ) {
					if ( isEmbeddedElementMatched( targetId ) ) {
						enabledSurvey.embedElementId = targetId;
						embeddedSurveys.push( enabledSurvey );
					}
				} else {
					availableSurveys.push( enabledSurvey );
				}
			}
		} );
	}
	if ( embeddedSurveys.length ) {
		// Inject all of the embedded surveys.
		embeddedSurveys.forEach( ( embeddedSurvey ) => {
			insertSurvey( embeddedSurvey, includeSensitiveData );
		} );
	} else if ( availableSurveys.length ) {
		// Get a random available survey
		const survey = availableSurveys[ Math.floor( Math.random() * availableSurveys.length ) ];
		insertSurvey( survey, includeSensitiveData );
	}
	return !!( embeddedSurveys.length || availableSurveys.length );
}

/**
 * API for custom survey UIs to record answers.
 *
 * @param {string} name
 * @param {string} question
 * @param {Object} answers
 * @param {boolean} [includeSensitiveInformation] defaults to false. When enabled this will collect
 *   information such as page. It is essential that this is only used where it is not possible for the
 *   page to contain the username. For example, if you are running a QuickSurvey on a user's page, do not
 *   enable this as the quick survey would no longer be anonymous.
 */
function logSurveyAnswer( name, question, answers, includeSensitiveInformation ) {
	mw.loader.using( 'ext.quicksurveys.lib.vue' ).then( ( req ) => {
		const logger = req( 'ext.quicksurveys.lib.vue' ).QuickSurveyLogger;
		const event = logger.logResponseData(
			name,
			question,
			answers,
			makeSurveySessionToken(),
			mw.user.getPageviewToken(),
			isTablet(),
			includeSensitiveInformation
		);
		logEvent( 'QuickSurveysResponses', event );
	} );
}
module.exports = {
	/**
	 * @stable for use
	 */
	showSurvey,
	/**
	 * @stable for use
	 */
	logSurveyAnswer
};

if ( window.QUnit ) {
	module.exports.test = {
		getSurveyFromQueryString,
		insertPanel,
		isInAudience,
		surveyMatchesPlatform,
		isQuickSurveysPrefEnabled
	};
}
},"resources/ext.quicksurveys.lib/surveyData.json":[
    {
        "audience": [],
        "name": "parsoid-migration-survey-2026",
        "question": null,
        "description": null,
        "module": "ext.quicksurveys.survey.parsoid-migration-survey-2026",
        "coverage": 1,
        "platforms": [
            "desktop",
            "mobile"
        ],
        "privacyPolicy": "parsermigration-survey-privacy-policy",
        "additionalInfo": null,
        "confirmMsg": "parsermigration-survey-confirm-msg",
        "questions": [
            {
                "name": "q1",
                "layout": "single-answer",
                "question": "parsermigration-survey-description",
                "description": "parsermigration-survey-question-1",
                "answers": [
                    {
                        "label": "parsermigration-survey-question-1-answer-1"
                    },
                    {
                        "label": "parsermigration-survey-question-1-answer-2"
                    },
                    {
                        "label": "parsermigration-survey-question-1-answer-3"
                    },
                    {
                        "label": "parsermigration-survey-question-1-answer-4"
                    },
                    {
                        "label": "parsermigration-survey-question-1-answer-5"
                    }
                ]
            },
            {
                "name": "q2",
                "layout": "single-answer",
                "question": "parsermigration-survey-question-2",
                "answers": [
                    {
                        "label": "parsermigration-survey-question-2-answer-1"
                    },
                    {
                        "label": "parsermigration-survey-question-2-answer-2"
                    },
                    {
                        "label": "parsermigration-survey-question-2-answer-3"
                    },
                    {
                        "label": "parsermigration-survey-question-2-answer-4"
                    },
                    {
                        "label": "parsermigration-survey-question-2-answer-5"
                    },
                    {
                        "label": "parsermigration-survey-question-2-answer-6",
                        "freeformTextLabel": "parsermigration-survey-question-2-freeformtext"
                    }
                ]
            },
            {
                "name": "q3",
                "layout": "multiple-answer",
                "question": "parsermigration-survey-question-3",
                "answers": [
                    {
                        "label": "parsermigration-survey-question-3-answer-1"
                    },
                    {
                        "label": "parsermigration-survey-question-3-answer-2"
                    },
                    {
                        "label": "parsermigration-survey-question-3-answer-3"
                    },
                    {
                        "label": "parsermigration-survey-question-3-answer-4"
                    },
                    {
                        "label": "parsermigration-survey-question-3-answer-5"
                    }
                ]
            },
            {
                "name": "q4",
                "layout": "single-answer",
                "question": "parsermigration-survey-question-4",
                "answers": [
                    {
                        "label": "parsermigration-survey-question-4-answer-1",
                        "freeformTextLabel": "parsermigration-survey-question-4-freeformtext"
                    },
                    {
                        "label": "parsermigration-survey-question-4-answer-2"
                    }
                ]
            }
        ],
        "confirmDescription": null,
        "type": "internal",
        "answers": null,
        "shuffleAnswersDisplay": null,
        "freeformTextLabel": null,
        "embedElementId": "-",
        "layout": null
    },
    {
        "audience": [],
        "name": "ReadingLists beta feature survey",
        "question": null,
        "description": null,
        "module": "ext.quicksurveys.survey.ReadingLists.beta.feature.survey",
        "coverage": 100,
        "platforms": [
            "desktop",
            "mobile"
        ],
        "privacyPolicy": "readinglists-betafeature-quicksurvey-privacy-policy",
        "additionalInfo": null,
        "confirmMsg": null,
        "questions": [
            {
                "name": "enjoyment",
                "layout": "single-answer",
                "question": "readinglists-betafeature-quicksurvey-question",
                "shuffleAnswersDisplay": false,
                "answers": [
                    {
                        "label": "readinglists-betafeature-quicksurvey-answer-positive"
                    },
                    {
                        "label": "readinglists-betafeature-quicksurvey-answer-negative"
                    }
                ]
            }
        ],
        "confirmDescription": null,
        "type": "internal",
        "answers": null,
        "shuffleAnswersDisplay": null,
        "freeformTextLabel": null,
        "embedElementId": "~",
        "layout": null
    },
    {
        "audience": {
            "namespaces": [
                0,
                -1
            ]
        },
        "name": "Empty search experiment survey",
        "question": null,
        "description": null,
        "module": "ext.quicksurveys.survey.Empty.search.experiment.survey",
        "coverage": 1,
        "platforms": [
            "desktop",
            "mobile"
        ],
        "privacyPolicy": "ext-quicksurveys-empty-search-experiment-privacy-policy",
        "additionalInfo": null,
        "confirmMsg": null,
        "questions": [
            {
                "name": "Empty search experiment question",
                "question": "ext-quicksurveys-empty-search-experiment-question",
                "link": "ext-quicksurveys-empty-search-experiment-link",
                "yesMsg": "ext-quicksurveys-empty-search-experiment-yes",
                "noMsg": "ext-quicksurveys-empty-search-experiment-no"
            }
        ],
        "confirmDescription": null,
        "type": "external",
        "link": null,
        "instanceTokenParameterName": null,
        "yesMsg": null,
        "noMsg": null,
        "embedElementId": "-"
    },
    {
        "audience": {
            "pageIds": [
                -1111
            ]
        },
        "name": "Automatic Translation Feedback",
        "question": null,
        "description": null,
        "module": "ext.quicksurveys.survey.Automatic.Translation.Feedback",
        "coverage": 0,
        "platforms": [
            "desktop",
            "mobile"
        ],
        "privacyPolicy": "ax-translation-view-feedback-privacy-statement",
        "additionalInfo": null,
        "confirmMsg": "ax-translation-view-feedback-confirm-title",
        "questions": [
            {
                "name": "question-1",
                "layout": "single-answer",
                "question": "ax-translation-view-feedback-title",
                "answers": [
                    {
                        "label": "ax-translation-view-feedback-positive"
                    },
                    {
                        "label": "ax-translation-view-feedback-negative"
                    }
                ]
            },
            {
                "name": "positive-question-2",
                "layout": "multiple-answer",
                "question": "ax-translation-view-feedback-details-question",
                "answers": [
                    {
                        "label": "ax-translation-view-feedback-positive-missing-information"
                    },
                    {
                        "label": "ax-translation-view-feedback-positive-translation-quality"
                    },
                    {
                        "label": "ax-translation-view-feedback-positive-quick-overview"
                    },
                    {
                        "label": "ax-translation-view-feedback-positive-technical-aspect"
                    }
                ],
                "dependsOn": [
                    {
                        "question": "question-1",
                        "answerIsOneOf": [
                            "ax-translation-view-feedback-positive"
                        ]
                    }
                ]
            },
            {
                "name": "negative-question-2",
                "layout": "multiple-answer",
                "question": "ax-translation-view-feedback-details-question",
                "answers": [
                    {
                        "label": "ax-translation-view-feedback-negative-missing-information"
                    },
                    {
                        "label": "ax-translation-view-feedback-negative-translation-quality"
                    },
                    {
                        "label": "ax-translation-view-feedback-negative-quick-overview"
                    },
                    {
                        "label": "ax-translation-view-feedback-negative-technical-aspect"
                    }
                ],
                "dependsOn": [
                    {
                        "question": "question-1",
                        "answerIsOneOf": [
                            "ax-translation-view-feedback-negative"
                        ]
                    }
                ]
            }
        ],
        "confirmDescription": "ax-translation-view-feedback-confirm-description",
        "type": "internal",
        "answers": null,
        "shuffleAnswersDisplay": null,
        "freeformTextLabel": null,
        "embedElementId": "ax-translation-viewer-section-container",
        "layout": null
    }
]}},{"css":["/* stylelint-disable @stylistic/indentation */\n/* stylelint-disable selector-class-pattern */\n/* stylelint-disable selector-no-vendor-prefix */\n/* stylelint-enable selector-no-vendor-prefix */\n/**\n * Compute the most transparent color that appears the same as @color\n * when overlaid on the given @background.\n *\n * @example\n *   background-color: .solid-to-minimum-opacity( #eaecf0 )[ @result ];\n *\n * @param {Color} @color The solid color to approximate with transparency\n * @param {Color} [@background=white] The background color to overlay on\n * @return {Color} @result\n */\n.ext-quick-survey-panel,\n.ext-qs-loader-bar {\n  width: auto;\n  background-color: #eaecf0;\n}\n/* FIXME: Should be an ajax loader to give impression something is happening */\n.ext-qs-loader-bar {\n  height: 100px;\n  margin-left: 1.4em;\n  clear: right;\n  float: right;\n  background-color: #eaecf0;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n}\n.ext-qs-loader-bar .mw-spinner-container {\n  transform: scale(0.5);\n  transform-origin: center;\n  width: 25%;\n  height: 75%;\n}\n.ext-quick-survey-panel {\n  overflow-wrap: anywhere;\n}\n@media all and (min-width: 640px) {\n  .ext-qs-loader-bar,\n  .ext-quick-survey-panel {\n    margin-left: 1.4em;\n    width: 300px;\n    clear: right;\n    float: right;\n  }\n}\n.mw-body \u003E .content .panel.ext-quick-survey-panel {\n  text-align: initial;\n}\n.mw-body \u003E .content .panel.ext-quick-survey-panel .image {\n  background-position: center 80%;\n  background-repeat: no-repeat;\n  background-size: auto 5em;\n}\n@media print {\n  .ext-quick-survey-panel {\n    display: none;\n  }\n}"]},{"ext-quicksurveys-external-survey-no-button":"(ext-quicksurveys-external-survey-no-button)","ext-quicksurveys-external-survey-yes-button":"(ext-quicksurveys-external-survey-yes-button)","ext-quicksurveys-internal-freeform-survey-back-button":"(ext-quicksurveys-internal-freeform-survey-back-button)","ext-quicksurveys-internal-freeform-survey-no-answer-alert":"(ext-quicksurveys-internal-freeform-survey-no-answer-alert)","ext-quicksurveys-internal-freeform-survey-submit-button":"(ext-quicksurveys-internal-freeform-survey-submit-button)","ext-quicksurveys-survey-change-preferences-disclaimer":"(ext-quicksurveys-survey-change-preferences-disclaimer)","ext-quicksurveys-survey-confirm-msg":"(ext-quicksurveys-survey-confirm-msg)","ext-quicksurveys-survey-negative":"(ext-quicksurveys-survey-negative)","ext-quicksurveys-survey-neutral":"(ext-quicksurveys-survey-neutral)","ext-quicksurveys-survey-positive":"(ext-quicksurveys-survey-positive)","ext-quicksurveys-survey-privacy-policy-default-text":"(ext-quicksurveys-survey-privacy-policy-default-text)"}];});
