{"version":3,"sources":["../src/components/Quiz/QuizContent.tsx","../src/utils/stringUtils.ts"],"sourcesContent":["import {\n  Fragment,\n  forwardRef,\n  MouseEvent,\n  ReactNode,\n  useCallback,\n  useEffect,\n  useId,\n  useMemo,\n  useRef,\n  useState,\n} from 'react';\nimport { ANSWER_STATUS, useQuizStore } from './useQuizStore';\nimport { QuizVariant } from './Quiz.types';\nimport { TrueFalseEnum } from '../../enums/Quiz';\nimport {\n  prependLetterToHtml,\n  getTrueOrFalseOptionState,\n  shuffleWithSeed,\n} from './Quiz.utils';\nimport { cn } from '../../utils/utils';\nimport { stripHtmlTags } from '../../utils/stringUtils';\nimport Select, {\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '../Select/Select';\nimport TextArea from '../TextArea/TextArea';\nimport { AlternativesList } from '../Alternative/Alternative';\nimport { OptionStatus } from '../../enums/Options';\nimport { MultipleChoiceList } from '../MultipleChoice/MultipleChoice';\nimport Badge from '../Badge/Badge';\nimport { CheckCircleIcon } from '@phosphor-icons/react/dist/csr/CheckCircle';\nimport { XCircleIcon } from '@phosphor-icons/react/dist/csr/XCircle';\nimport ImageQuestion from '../../assets/img/mock-image-question.png';\nimport Text from '../Text/Text';\nimport { HtmlMathRenderer } from '../HtmlMathRenderer';\nexport const getStatusBadge = (status?: OptionStatus) => {\n  switch (status) {\n    case OptionStatus.CORRECT:\n      return (\n        <Badge variant=\"solid\" action=\"success\" iconLeft={<CheckCircleIcon />}>\n          Resposta correta\n        </Badge>\n      );\n    case OptionStatus.INCORRECT:\n      return (\n        <Badge variant=\"solid\" action=\"error\" iconLeft={<XCircleIcon />}>\n          Resposta incorreta\n        </Badge>\n      );\n    default:\n      return null;\n  }\n};\n\nexport const getStatusStyles = (variantCorrect?: OptionStatus) => {\n  switch (variantCorrect) {\n    case OptionStatus.CORRECT:\n      return 'bg-success-background border-success-300';\n    case OptionStatus.INCORRECT:\n      return 'bg-error-background border-error-300';\n    default:\n      return '';\n  }\n};\n\n/**\n * Normalizes parsed answer data to Record<string, string> format.\n * Handles legacy array format [{ optionId, selectedValue }] by converting to { [optionId]: selectedValue }.\n */\nconst normalizeAnswerData = (parsed: unknown): Record<string, string> => {\n  // Handle legacy array format: [{ optionId: string, selectedValue: string }]\n  if (Array.isArray(parsed)) {\n    const result: Record<string, string> = {};\n    for (const item of parsed) {\n      if (\n        item &&\n        typeof item === 'object' &&\n        'optionId' in item &&\n        'selectedValue' in item\n      ) {\n        result[item.optionId as string] = item.selectedValue as string;\n      }\n    }\n    return result;\n  }\n\n  // Handle expected object format: { [optionId]: selectedValue }\n  if (parsed && typeof parsed === 'object') {\n    return parsed as Record<string, string>;\n  }\n\n  return {};\n};\n\n/**\n * Parses JSON answers from stored answer string.\n * In result mode, uses persisted results. Otherwise, uses current draft answers.\n * Normalizes legacy array format to expected Record<string, string> map.\n */\nconst parseStoredAnswers = (\n  variant: QuizVariant,\n  resultAnswer: string | null | undefined,\n  currentAnswer: string | null | undefined\n): Record<string, string> => {\n  if (variant === QuizVariant.RESULT) {\n    if (!resultAnswer) return {};\n    try {\n      const parsed = JSON.parse(resultAnswer);\n      return normalizeAnswerData(parsed);\n    } catch {\n      return {};\n    }\n  }\n  if (currentAnswer) {\n    try {\n      const parsed = JSON.parse(currentAnswer);\n      return normalizeAnswerData(parsed);\n    } catch {\n      return {};\n    }\n  }\n  return {};\n};\n\n/**\n * Converts isCorrect boolean to status variant string.\n * Returns undefined for null/unanswered to keep neutral styling.\n */\nconst getAnswerStatus = (\n  isCorrect: boolean | null\n): OptionStatus | undefined => {\n  if (isCorrect === true) return OptionStatus.CORRECT;\n  if (isCorrect === false) return OptionStatus.INCORRECT;\n  return undefined;\n};\n\ninterface QuizVariantInterface {\n  paddingBottom?: string;\n}\n\nconst QuizSubTitle = forwardRef<HTMLDivElement, { subTitle: string }>(\n  ({ subTitle, ...props }, ref) => {\n    return (\n      <div className=\"px-4 pb-2 pt-6\" {...props} ref={ref}>\n        <p className=\"font-bold text-lg text-text-950\">{subTitle}</p>\n      </div>\n    );\n  }\n);\n\nconst QuizContainer = forwardRef<\n  HTMLDivElement,\n  { children: ReactNode; className?: string }\n>(({ children, className, ...props }, ref) => {\n  return (\n    <div\n      ref={ref}\n      className={cn(\n        'bg-background rounded-t-xl px-4 pt-4 pb-[80px] h-auto flex flex-col gap-4 mb-auto',\n        className\n      )}\n      {...props}\n    >\n      {children}\n    </div>\n  );\n});\n\nconst QuizAlternative = ({ paddingBottom }: QuizVariantInterface) => {\n  const {\n    getCurrentQuestion,\n    selectAnswer,\n    getQuestionResultByQuestionId,\n    getCurrentAnswer,\n    variant,\n  } = useQuizStore();\n  const currentQuestion = getCurrentQuestion();\n  const currentQuestionResult = getQuestionResultByQuestionId(\n    currentQuestion?.id || ''\n  );\n\n  const currentAnswer = getCurrentAnswer();\n  const alternatives = currentQuestion?.options?.map((option) => {\n    let status: OptionStatus = OptionStatus.NEUTRAL;\n    if (variant === QuizVariant.RESULT) {\n      const isCorrectOption =\n        currentQuestionResult?.options?.find((op) => op.id === option.id)\n          ?.isCorrect || false;\n\n      const isSelected = currentQuestionResult?.selectedOptions.some(\n        (selectedOption) => selectedOption.optionId === option.id\n      );\n\n      // Only show correct/incorrect status if answer is not pending evaluation\n      const shouldShowCorrectAnswers =\n        currentQuestionResult?.answerStatus !==\n          ANSWER_STATUS.PENDENTE_AVALIACAO &&\n        currentQuestionResult?.answerStatus !== ANSWER_STATUS.NAO_RESPONDIDO;\n\n      if (shouldShowCorrectAnswers) {\n        if (isCorrectOption) {\n          status = OptionStatus.CORRECT;\n        } else if (isSelected && !isCorrectOption) {\n          status = OptionStatus.INCORRECT;\n        } else {\n          status = OptionStatus.NEUTRAL;\n        }\n      } else {\n        // When pending evaluation, show all options as neutral\n        status = OptionStatus.NEUTRAL;\n      }\n    }\n\n    return {\n      label: option.option,\n      value: option.id,\n      status: status,\n    };\n  });\n\n  if (!alternatives)\n    return (\n      <div>\n        <p>Não há Alternativas</p>\n      </div>\n    );\n\n  return (\n    <>\n      <QuizSubTitle subTitle=\"Alternativas\" />\n\n      <QuizContainer className={cn('', paddingBottom)}>\n        <div className=\"space-y-4\">\n          <AlternativesList\n            mode={variant === QuizVariant.DEFAULT ? 'interactive' : 'readonly'}\n            key={`question-${currentQuestion?.id || '1'}`}\n            name={`question-${currentQuestion?.id || '1'}`}\n            layout=\"compact\"\n            alternatives={alternatives}\n            value={\n              variant === QuizVariant.RESULT\n                ? currentQuestionResult?.selectedOptions[0]?.optionId || ''\n                : currentAnswer?.optionId || ''\n            }\n            selectedValue={\n              variant === QuizVariant.RESULT\n                ? currentQuestionResult?.selectedOptions[0]?.optionId || ''\n                : currentAnswer?.optionId || ''\n            }\n            onValueChange={(value) => {\n              if (currentQuestion) {\n                selectAnswer(currentQuestion.id, value);\n              }\n            }}\n          />\n        </div>\n      </QuizContainer>\n    </>\n  );\n};\n\nconst QuizMultipleChoice = ({ paddingBottom }: QuizVariantInterface) => {\n  const {\n    getCurrentQuestion,\n    selectMultipleAnswer,\n    getQuestionResultByQuestionId,\n    variant,\n  } = useQuizStore();\n  const currentQuestion = getCurrentQuestion();\n  // Derive the current question's answers from the stable `userAnswers` slice\n  // instead of calling getAllCurrentAnswer(), which allocates a fresh array on\n  // every render. That fresh identity propagated through the memos below and,\n  // combined with the store→prop→local-state mirror in MultipleChoiceList,\n  // caused a \"Maximum update depth exceeded\" loop on /questionario.\n  const userAnswers = useQuizStore((state) => state.userAnswers);\n  const allCurrentAnswers = useMemo(\n    () =>\n      currentQuestion\n        ? userAnswers.filter(\n            (answer) => answer.questionId === currentQuestion.id\n          )\n        : [],\n    [userAnswers, currentQuestion]\n  );\n  const currentQuestionResult = getQuestionResultByQuestionId(\n    currentQuestion?.id || ''\n  );\n  // Use ref to track previous values and prevent unnecessary updates\n  const prevSelectedValuesRef = useRef<string[]>([]);\n  const prevQuestionIdRef = useRef<string>('');\n\n  // Memoize the answer IDs to prevent unnecessary re-renders\n  // For MULTIPLA_ESCOLHA, we now have a single answer entry with selectedOptionIds array\n  const allCurrentAnswerIds = useMemo(() => {\n    if (allCurrentAnswers && allCurrentAnswers.length > 0) {\n      // Prefer any row already using the new format\n      const answerWithSelectedOptionIds = allCurrentAnswers.find((answer) =>\n        Array.isArray(answer.selectedOptionIds)\n      );\n      if (answerWithSelectedOptionIds) {\n        return answerWithSelectedOptionIds.selectedOptionIds ?? [];\n      }\n      // Fallback to old format (multiple entries with optionId)\n      return allCurrentAnswers.map((answer) => answer.optionId);\n    }\n    return [];\n  }, [allCurrentAnswers]);\n\n  // Memoize the selected values to prevent infinite loops\n  const selectedValues = useMemo(() => {\n    return allCurrentAnswerIds?.filter((id): id is string => id !== null) || [];\n  }, [allCurrentAnswerIds]);\n\n  // Only update selectedValues if they actually changed or question changed\n  const stableSelectedValues = useMemo(() => {\n    // In result mode, always use selectedOptions from the question result\n    if (variant === QuizVariant.RESULT) {\n      return (\n        currentQuestionResult?.selectedOptions?.map((op) => op.optionId) || []\n      );\n    }\n\n    const currentQuestionId = currentQuestion?.id || '';\n    const hasQuestionChanged = prevQuestionIdRef.current !== currentQuestionId;\n\n    if (hasQuestionChanged) {\n      prevQuestionIdRef.current = currentQuestionId;\n      prevSelectedValuesRef.current = selectedValues;\n      return selectedValues;\n    }\n\n    // Only update if values actually changed\n    const hasValuesChanged =\n      JSON.stringify(prevSelectedValuesRef.current) !==\n      JSON.stringify(selectedValues);\n    if (hasValuesChanged) {\n      prevSelectedValuesRef.current = selectedValues;\n      return selectedValues;\n    }\n\n    return prevSelectedValuesRef.current;\n  }, [\n    selectedValues,\n    currentQuestion?.id,\n    variant,\n    currentQuestionResult?.selectedOptions,\n  ]);\n\n  // Memoize the callback to prevent unnecessary re-renders\n  const handleSelectedValues = useCallback(\n    (values: string[]) => {\n      if (currentQuestion) {\n        selectMultipleAnswer(currentQuestion.id, values);\n      }\n    },\n    [currentQuestion, selectMultipleAnswer]\n  );\n\n  // Create a stable key to force re-mount when question changes\n  const questionKey = useMemo(\n    () => `question-${currentQuestion?.id || '1'}`,\n    [currentQuestion?.id]\n  );\n  const choices = currentQuestion?.options?.map((option) => {\n    let status: OptionStatus = OptionStatus.NEUTRAL;\n\n    if (variant === QuizVariant.RESULT) {\n      const isCorrectOption =\n        currentQuestionResult?.options?.find((op) => op.id === option.id)\n          ?.isCorrect || false;\n\n      const isSelected = currentQuestionResult?.selectedOptions?.some(\n        (op) => op.optionId === option.id\n      );\n\n      // Only show correct/incorrect status if answer is not pending evaluation\n      const shouldShowCorrectAnswers =\n        currentQuestionResult?.answerStatus !==\n          ANSWER_STATUS.PENDENTE_AVALIACAO &&\n        currentQuestionResult?.answerStatus !== ANSWER_STATUS.NAO_RESPONDIDO;\n\n      if (shouldShowCorrectAnswers) {\n        if (isCorrectOption) {\n          status = OptionStatus.CORRECT;\n        } else if (isSelected && !isCorrectOption) {\n          status = OptionStatus.INCORRECT;\n        } else {\n          status = OptionStatus.NEUTRAL;\n        }\n      } else {\n        // When pending evaluation, show all options as neutral\n        status = OptionStatus.NEUTRAL;\n      }\n    }\n\n    return {\n      label: option.option,\n      value: option.id,\n      status: status,\n    };\n  });\n\n  if (!choices)\n    return (\n      <div>\n        <p>Não há Escolhas Multiplas</p>\n      </div>\n    );\n  return (\n    <>\n      <QuizSubTitle subTitle=\"Alternativas\" />\n\n      <QuizContainer className={cn('', paddingBottom)}>\n        <div className=\"space-y-4\">\n          <MultipleChoiceList\n            choices={choices}\n            key={questionKey}\n            name={questionKey}\n            selectedValues={stableSelectedValues}\n            onHandleSelectedValues={handleSelectedValues}\n            mode={variant === QuizVariant.DEFAULT ? 'interactive' : 'readonly'}\n          />\n        </div>\n      </QuizContainer>\n    </>\n  );\n};\n\nconst QuizDissertative = ({ paddingBottom }: QuizVariantInterface) => {\n  const {\n    getCurrentQuestion,\n    getCurrentAnswer,\n    selectDissertativeAnswer,\n    getQuestionResultByQuestionId,\n    variant,\n    getDissertativeCharLimit,\n  } = useQuizStore();\n\n  const currentQuestion = getCurrentQuestion();\n  const currentQuestionResult = getQuestionResultByQuestionId(\n    currentQuestion?.id || ''\n  );\n\n  const currentAnswer = getCurrentAnswer();\n  const textareaRef = useRef<HTMLTextAreaElement>(null);\n  const charLimit = getDissertativeCharLimit();\n\n  const handleAnswerChange = (value: string) => {\n    if (currentQuestion) {\n      selectDissertativeAnswer(currentQuestion.id, value);\n    }\n  };\n\n  // Auto-resize function\n  const adjustTextareaHeight = useCallback(() => {\n    if (textareaRef.current) {\n      textareaRef.current.style.height = 'auto';\n      const scrollHeight = textareaRef.current.scrollHeight;\n      const minHeight = 120; // 120px minimum height\n      const maxHeight = 400; // 400px maximum height\n      const newHeight = Math.min(Math.max(scrollHeight, minHeight), maxHeight);\n      textareaRef.current.style.height = `${newHeight}px`;\n    }\n  }, []);\n\n  // Adjust height when currentAnswer changes\n  useEffect(() => {\n    adjustTextareaHeight();\n  }, [currentAnswer, adjustTextareaHeight]);\n\n  if (!currentQuestion) {\n    return (\n      <div className=\"space-y-4\">\n        <p className=\"text-text-600 text-md\">Nenhuma questão disponível</p>\n      </div>\n    );\n  }\n\n  const localAnswer =\n    (variant == 'result'\n      ? currentQuestionResult?.answer\n      : currentAnswer?.answer) || '';\n  return (\n    <>\n      <QuizSubTitle subTitle=\"Resposta\" />\n\n      <QuizContainer className={cn(variant != 'result' && paddingBottom)}>\n        <div className=\"space-y-4 max-h-[600px] overflow-y-auto\">\n          {variant === QuizVariant.DEFAULT ? (\n            <div className=\"space-y-4\">\n              <TextArea\n                ref={textareaRef}\n                placeholder=\"Escreva sua resposta\"\n                value={localAnswer}\n                onChange={(e) => handleAnswerChange(e.target.value)}\n                rows={4}\n                className=\"min-h-[120px] max-h-[400px] resize-none overflow-y-auto\"\n                maxLength={charLimit}\n                showCharacterCount={!!charLimit}\n              />\n            </div>\n          ) : (\n            <div className=\"space-y-4\">\n              <p className=\"text-text-600 text-md whitespace-pre-wrap\">\n                {localAnswer || 'Nenhuma resposta fornecida'}\n              </p>\n            </div>\n          )}\n        </div>\n      </QuizContainer>\n\n      {variant === QuizVariant.RESULT &&\n        currentQuestionResult?.teacherFeedback && (\n          <>\n            <QuizSubTitle subTitle=\"Observação do professor\" />\n\n            <QuizContainer className={cn('', paddingBottom)}>\n              <p className=\"text-text-600 text-md whitespace-pre-wrap\">\n                {currentQuestionResult?.teacherFeedback}\n              </p>\n            </QuizContainer>\n          </>\n        )}\n    </>\n  );\n};\n\nconst QuizTrueOrFalse = ({ paddingBottom }: QuizVariantInterface) => {\n  const {\n    variant,\n    getCurrentQuestion,\n    getCurrentAnswer,\n    selectDissertativeAnswer,\n    getQuestionResultByQuestionId,\n    getUserAnswerByQuestionId,\n  } = useQuizStore();\n\n  const currentQuestion = getCurrentQuestion();\n  const currentAnswer = getCurrentAnswer();\n  const currentQuestionResult = getQuestionResultByQuestionId(\n    currentQuestion?.id || ''\n  );\n\n  // Get the options - prefer persisted result options in result mode, fallback to live question\n  const options = useMemo(() => {\n    if (variant === QuizVariant.RESULT && currentQuestionResult?.options) {\n      return currentQuestionResult.options;\n    }\n    return currentQuestion?.options || [];\n  }, [variant, currentQuestionResult?.options, currentQuestion?.options]);\n\n  // Parse stored answers from JSON string, handling both object and legacy array formats\n  const parsedAnswers: Record<string, string> = useMemo(() => {\n    return parseStoredAnswers(\n      variant,\n      currentQuestionResult?.answer,\n      currentAnswer?.answer\n    );\n  }, [variant, currentQuestionResult?.answer, currentAnswer?.answer]);\n\n  // Local state to track answers: { \"optionId\": \"V\" | \"F\" }\n  const [localAnswers, setLocalAnswers] =\n    useState<Record<string, string>>(parsedAnswers);\n\n  // Sync local answers when question changes or parsed answers update\n  useEffect(() => {\n    setLocalAnswers(parsedAnswers);\n  }, [parsedAnswers, currentQuestion?.id]);\n\n  // Handle select change for an option\n  const handleSelectChange = (optionId: string, value: string) => {\n    if (!currentQuestion) return;\n\n    // Get the LATEST answers directly from the store (not from closure)\n    // This is critical to avoid stale closure issues when user selects options quickly\n    const latestStoreAnswer = getUserAnswerByQuestionId(currentQuestion.id);\n    let baseAnswers: Record<string, string> = {};\n    if (latestStoreAnswer?.answer) {\n      try {\n        const parsed = JSON.parse(latestStoreAnswer.answer);\n        baseAnswers = normalizeAnswerData(parsed);\n      } catch {\n        // Invalid JSON, start fresh\n      }\n    }\n\n    // Merge: store answers + local state + new selection\n    const mergedAnswers = {\n      ...baseAnswers,\n      ...localAnswers,\n      [optionId]: value,\n    };\n    setLocalAnswers(mergedAnswers);\n\n    // Save to store as JSON string\n    selectDissertativeAnswer(currentQuestion.id, JSON.stringify(mergedAnswers));\n  };\n\n  // Get the current selection for an option\n  const getOptionSelection = (optionId: string): string | undefined => {\n    return localAnswers[optionId];\n  };\n\n  const getLetterByIndex = (index: number) => String.fromCodePoint(97 + index); // 97 = 'a' in ASCII\n\n  const isDefaultVariant = variant === QuizVariant.DEFAULT;\n\n  // Check if we should show correct/incorrect status\n  const shouldShowStatus =\n    currentQuestionResult?.answerStatus !== ANSWER_STATUS.PENDENTE_AVALIACAO &&\n    currentQuestionResult?.answerStatus !== ANSWER_STATUS.NAO_RESPONDIDO;\n\n  if (options.length === 0) {\n    return (\n      <QuizContainer className={cn('', paddingBottom)}>\n        <Text size=\"sm\" className=\"text-text-500 italic\">\n          Nenhuma opção disponível para esta questão\n        </Text>\n      </QuizContainer>\n    );\n  }\n\n  return (\n    <>\n      <QuizSubTitle subTitle=\"Alternativas\" />\n\n      <QuizContainer className={cn('', paddingBottom)}>\n        <div className=\"flex flex-col gap-3.5\">\n          {options.map((option, index) => {\n            // Use helper to compute all option state\n            const {\n              hasAnswered,\n              studentAnswer,\n              correctAnswer,\n              isStudentCorrect,\n              variantCorrect,\n            } = getTrueOrFalseOptionState(\n              option.id,\n              variant,\n              currentQuestionResult,\n              localAnswers\n            );\n\n            const contentWithLetter = prependLetterToHtml(\n              getLetterByIndex(index),\n              option.option\n            );\n\n            return (\n              <section\n                key={option.id || `option-${index}`}\n                className=\"flex flex-col gap-2\"\n              >\n                <div\n                  className={cn(\n                    'w-full grid grid-cols-[1fr_auto] items-start gap-4 p-2 rounded-md border',\n                    !isDefaultVariant && shouldShowStatus && hasAnswered\n                      ? getStatusStyles(variantCorrect)\n                      : 'border-transparent'\n                  )}\n                >\n                  <HtmlMathRenderer\n                    content={contentWithLetter}\n                    className=\"text-text-900 text-sm\"\n                  />\n\n                  {isDefaultVariant ? (\n                    <Select\n                      size=\"medium\"\n                      value={getOptionSelection(option.id)}\n                      onValueChange={(value) =>\n                        handleSelectChange(option.id, value)\n                      }\n                    >\n                      <SelectTrigger className=\"w-[120px]\">\n                        <SelectValue placeholder=\"Selecione\" />\n                      </SelectTrigger>\n\n                      <SelectContent>\n                        <SelectItem value={TrueFalseEnum.VERDADEIRO}>\n                          Verdadeiro\n                        </SelectItem>\n                        <SelectItem value={TrueFalseEnum.FALSO}>\n                          Falso\n                        </SelectItem>\n                      </SelectContent>\n                    </Select>\n                  ) : (\n                    shouldShowStatus &&\n                    hasAnswered && <div>{getStatusBadge(variantCorrect)}</div>\n                  )}\n                </div>\n\n                {!isDefaultVariant && shouldShowStatus && (\n                  <span className=\"flex flex-row gap-2 items-center flex-wrap\">\n                    {hasAnswered ? (\n                      <>\n                        <Text size=\"2xs\" className=\"text-text-800\">\n                          Resposta selecionada: {studentAnswer}\n                        </Text>\n                        {!isStudentCorrect && (\n                          <Text size=\"2xs\" className=\"text-text-800\">\n                            | Resposta correta: {correctAnswer}\n                          </Text>\n                        )}\n                      </>\n                    ) : (\n                      <Text size=\"2xs\" className=\"text-text-800\">\n                        Não respondida | Resposta correta: {correctAnswer}\n                      </Text>\n                    )}\n                  </span>\n                )}\n              </section>\n            );\n          })}\n        </div>\n      </QuizContainer>\n    </>\n  );\n};\n\ninterface UserAnswer {\n  option: string;\n  dotOption: string | null;\n  correctOption: string;\n  isCorrect: boolean | null;\n}\n\nconst QuizConnectDots = ({ paddingBottom }: QuizVariantInterface) => {\n  const {\n    variant,\n    getCurrentQuestion,\n    getCurrentAnswer,\n    selectDissertativeAnswer,\n    getQuestionResultByQuestionId,\n    getUserAnswerByQuestionId,\n  } = useQuizStore();\n\n  const currentQuestion = getCurrentQuestion();\n  const currentQuestionResult = getQuestionResultByQuestionId(\n    currentQuestion?.id || ''\n  );\n  const currentAnswer = getCurrentAnswer();\n\n  // Extract options from the current question\n  // Each option has: id, option (left column), correctValue (right column)\n  const questionOptions = useMemo(() => {\n    if (!currentQuestion?.options) return [];\n    return currentQuestion.options;\n  }, [currentQuestion?.options]);\n\n  // Build dotsOptions from correctValue of each option (right column values)\n  // Shuffle them so they don't appear in the same order as the left column\n  const dotsOptions = useMemo(() => {\n    const dots = questionOptions\n      .map((opt) => ({ label: opt.correctValue || '' }))\n      .filter((opt) => opt.label !== '');\n    // Use question ID as seed for consistent shuffle\n    return shuffleWithSeed(dots, currentQuestion?.id || '');\n  }, [questionOptions, currentQuestion?.id]);\n\n  // Build options for display (left column with correct answer mapping)\n  const options = useMemo(() => {\n    return questionOptions.map((opt) => ({\n      id: opt.id,\n      label: opt.option,\n      correctOption: opt.correctValue || '',\n    }));\n  }, [questionOptions]);\n\n  // Parse stored matching answers\n  // In result mode, read from matchingAnswers array, fallback to answer JSON\n  // In default mode, read from currentAnswer.answer JSON string\n  const parsedAnswers: Record<string, string> = useMemo(() => {\n    if (\n      variant === QuizVariant.RESULT &&\n      currentQuestionResult?.matchingAnswers\n    ) {\n      // Convert matchingAnswers array to Record<optionId, selectedValue>\n      const answers: Record<string, string> = {};\n      for (const match of currentQuestionResult.matchingAnswers) {\n        answers[match.optionId] = match.selectedValue;\n      }\n      return answers;\n    }\n    // Fallback to answer JSON string (for older/partially migrated submissions)\n    return parseStoredAnswers(\n      variant,\n      currentQuestionResult?.answer,\n      currentAnswer?.answer\n    );\n  }, [\n    variant,\n    currentQuestionResult?.matchingAnswers,\n    currentQuestionResult?.answer,\n    currentAnswer?.answer,\n  ]);\n\n  const [userAnswers, setUserAnswers] = useState<UserAnswer[]>([]);\n\n  // Initialize userAnswers from options and stored answers\n  useEffect(() => {\n    if (options.length > 0) {\n      setUserAnswers(\n        options.map((option) => {\n          const storedValue = parsedAnswers[option.id] || null;\n          return {\n            option: option.label,\n            dotOption: storedValue,\n            correctOption: option.correctOption,\n            isCorrect: storedValue\n              ? storedValue === option.correctOption\n              : null,\n          };\n        })\n      );\n    }\n  }, [options, parsedAnswers]);\n\n  const handleSelectDot = (optionIndex: number, dotValue: string) => {\n    const option = options[optionIndex];\n    if (!option || !currentQuestion) return;\n\n    // Update local state\n    setUserAnswers((prev) => {\n      const next = [...prev];\n      next[optionIndex] = {\n        option: option.label,\n        dotOption: dotValue,\n        correctOption: option.correctOption,\n        isCorrect: dotValue ? dotValue === option.correctOption : null,\n      };\n      return next;\n    });\n\n    // Get the LATEST answers directly from the store (not from closure)\n    const latestStoreAnswer = getUserAnswerByQuestionId(currentQuestion.id);\n    let baseAnswers: Record<string, string> = {};\n    if (latestStoreAnswer?.answer) {\n      try {\n        const parsed = JSON.parse(latestStoreAnswer.answer);\n        baseAnswers = normalizeAnswerData(parsed);\n      } catch {\n        // Invalid JSON, start fresh\n      }\n    }\n\n    // Persist to shared store as JSON\n    const newAnswers = {\n      ...baseAnswers,\n      ...parsedAnswers,\n      [option.id]: dotValue,\n    };\n    selectDissertativeAnswer(currentQuestion.id, JSON.stringify(newAnswers));\n  };\n\n  const getLetterByIndex = (index: number) => String.fromCodePoint(97 + index); // 'a', 'b', 'c'...\n\n  const isDefaultVariant = variant === QuizVariant.DEFAULT;\n  const assignedDots = new Set(\n    userAnswers.map((a) => a.dotOption).filter(Boolean)\n  );\n\n  if (options.length === 0) {\n    return (\n      <QuizContainer className={cn('', paddingBottom)}>\n        <Text size=\"sm\" className=\"text-text-500 italic\">\n          Nenhuma opção de relacionamento disponível\n        </Text>\n      </QuizContainer>\n    );\n  }\n\n  return (\n    <>\n      <QuizSubTitle subTitle=\"Alternativas\" />\n\n      <QuizContainer className={cn('', paddingBottom)}>\n        <div className=\"flex flex-col gap-3.5\">\n          {options.map((option, index) => {\n            const answer = userAnswers[index] || {\n              option: option.label,\n              dotOption: null,\n              correctOption: option.correctOption,\n              isCorrect: null,\n            };\n            const variantCorrect = getAnswerStatus(answer.isCorrect);\n            return (\n              <section key={option.id} className=\"flex flex-col gap-2\">\n                <div\n                  className={cn(\n                    'grid grid-cols-[1fr_auto] items-center gap-4 p-2 rounded-md',\n                    !isDefaultVariant && variantCorrect\n                      ? getStatusStyles(variantCorrect)\n                      : ''\n                  )}\n                >\n                  <HtmlMathRenderer\n                    content={prependLetterToHtml(\n                      getLetterByIndex(index),\n                      option.label\n                    )}\n                    className=\"text-text-900 text-sm\"\n                  />\n\n                  {isDefaultVariant ? (\n                    <Select\n                      size=\"medium\"\n                      value={answer.dotOption || undefined}\n                      onValueChange={(value) => handleSelectDot(index, value)}\n                    >\n                      <SelectTrigger\n                        className=\"w-[180px] overflow-hidden truncate\"\n                        title={\n                          answer.dotOption\n                            ? stripHtmlTags(answer.dotOption)\n                            : undefined\n                        }\n                      >\n                        <SelectValue placeholder=\"Selecione opção\" />\n                      </SelectTrigger>\n\n                      <SelectContent>\n                        {dotsOptions\n                          .filter(\n                            (dot) =>\n                              !assignedDots.has(dot.label) ||\n                              answer.dotOption === dot.label\n                          )\n                          .map((dot) => (\n                            <SelectItem\n                              key={dot.label}\n                              value={dot.label}\n                              title={stripHtmlTags(dot.label)}\n                              truncate\n                            >\n                              {stripHtmlTags(dot.label)}\n                            </SelectItem>\n                          ))}\n                      </SelectContent>\n                    </Select>\n                  ) : (\n                    <div>\n                      {answer.isCorrect === null\n                        ? null\n                        : getStatusBadge(variantCorrect)}\n                    </div>\n                  )}\n                </div>\n\n                {!isDefaultVariant && (\n                  <span className=\"flex flex-row gap-2 items-center\">\n                    <Text size=\"2xs\" className=\"text-text-800\">\n                      Resposta selecionada:{' '}\n                      {answer.dotOption\n                        ? stripHtmlTags(answer.dotOption)\n                        : 'Nenhuma'}\n                    </Text>\n                    {answer.isCorrect === false && (\n                      <Text size=\"2xs\" className=\"text-text-800\">\n                        Resposta correta: {stripHtmlTags(answer.correctOption)}\n                      </Text>\n                    )}\n                  </span>\n                )}\n              </section>\n            );\n          })}\n        </div>\n      </QuizContainer>\n    </>\n  );\n};\n\nconst QuizFill = ({ paddingBottom }: QuizVariantInterface) => {\n  const {\n    getCurrentQuestion,\n    getQuestionResultByQuestionId,\n    getCurrentAnswer,\n    selectDissertativeAnswer,\n    variant,\n    getUserAnswerByQuestionId,\n  } = useQuizStore();\n\n  const currentQuestion = getCurrentQuestion();\n  const currentQuestionResult = getQuestionResultByQuestionId(\n    currentQuestion?.id || ''\n  );\n  const currentAnswer = getCurrentAnswer();\n\n  const baseId = useId();\n\n  // Get the additionalContent from the question (contains text with {optionId} placeholders)\n  // In result mode, prefer the persisted snapshot to match parsedAnswers\n  const additionalContent =\n    variant === QuizVariant.RESULT\n      ? currentQuestionResult?.additionalContent ||\n        currentQuestion?.additionalContent ||\n        ''\n      : currentQuestion?.additionalContent || '';\n\n  // Get the options from the question\n  // In result mode, prefer the persisted snapshot to match parsedAnswers\n  const questionOptions =\n    variant === QuizVariant.RESULT\n      ? currentQuestionResult?.options || currentQuestion?.options || []\n      : currentQuestion?.options || [];\n\n  // Shuffled options for dropdown display (consistent per question)\n  const shuffledOptions = useMemo(() => {\n    return shuffleWithSeed(questionOptions, currentQuestion?.id || '');\n  }, [questionOptions, currentQuestion?.id]);\n\n  // Parse current answers\n  // In result mode, read from fillAnswers object, fallback to answer JSON\n  // In default mode, read from currentAnswer.answer JSON string\n  const parsedAnswers: Record<string, string> = useMemo(() => {\n    if (variant === QuizVariant.RESULT && currentQuestionResult?.fillAnswers) {\n      // fillAnswers is already a Record<placeholderId, selectedOptionId>\n      return currentQuestionResult.fillAnswers;\n    }\n    // Fallback to answer JSON string (for older/partially migrated submissions)\n    return parseStoredAnswers(\n      variant,\n      currentQuestionResult?.answer,\n      currentAnswer?.answer\n    );\n  }, [\n    variant,\n    currentQuestionResult?.fillAnswers,\n    currentQuestionResult?.answer,\n    currentAnswer?.answer,\n  ]);\n\n  const [localAnswers, setLocalAnswers] =\n    useState<Record<string, string>>(parsedAnswers);\n\n  // Sync local answers when question changes\n  useEffect(() => {\n    setLocalAnswers(parsedAnswers);\n  }, [parsedAnswers, currentQuestion?.id]);\n\n  // Handle select change\n  const handleSelectChange = (placeholderId: string, optionId: string) => {\n    if (!currentQuestion) return;\n\n    // Get the LATEST answers directly from the store (not from closure)\n    const latestStoreAnswer = getUserAnswerByQuestionId(currentQuestion.id);\n    let baseAnswers: Record<string, string> = {};\n    if (latestStoreAnswer?.answer) {\n      try {\n        const parsed = JSON.parse(latestStoreAnswer.answer);\n        baseAnswers = normalizeAnswerData(parsed);\n      } catch {\n        // Invalid JSON, start fresh\n      }\n    }\n\n    const newAnswers = {\n      ...baseAnswers,\n      ...localAnswers,\n      [placeholderId]: optionId,\n    };\n    setLocalAnswers(newAnswers);\n\n    // Save to store as JSON string\n    selectDissertativeAnswer(currentQuestion.id, JSON.stringify(newAnswers));\n  };\n\n  // Get option text by ID\n  const getOptionTextById = (optionId: string): string => {\n    const option = questionOptions.find((opt) => opt.id === optionId);\n    return stripHtmlTags(option?.option || '');\n  };\n\n  // Check if an answer is correct (for result mode)\n  const isAnswerCorrect = (placeholderId: string): boolean => {\n    const selectedOptionId = localAnswers[placeholderId];\n    // The placeholder ID is the correct option ID\n    return selectedOptionId === placeholderId;\n  };\n\n  // Render the select for default mode\n  const renderDefaultSelect = (placeholderId: string) => {\n    const selectedOptionId = localAnswers[placeholderId];\n\n    return (\n      <span\n        key={placeholderId}\n        className=\"inline-block align-middle mx-1 my-2\"\n        style={{ display: 'inline-block', verticalAlign: 'middle' }}\n      >\n        <Select\n          value={selectedOptionId || undefined}\n          onValueChange={(value) => handleSelectChange(placeholderId, value)}\n        >\n          <SelectTrigger\n            className=\"w-auto min-w-[120px] max-w-[200px] h-7 px-2 bg-background border-gray-300 overflow-hidden truncate\"\n            title={stripHtmlTags(\n              shuffledOptions.find((o) => o.id === selectedOptionId)?.option ||\n                ''\n            )}\n          >\n            <SelectValue placeholder=\"Selecione opção\" />\n          </SelectTrigger>\n          <SelectContent>\n            {shuffledOptions.map((option) => (\n              <SelectItem\n                key={option.id}\n                value={option.id}\n                title={stripHtmlTags(option.option)}\n                truncate\n              >\n                {stripHtmlTags(option.option)}\n              </SelectItem>\n            ))}\n          </SelectContent>\n        </Select>\n      </span>\n    );\n  };\n\n  // Render the result badge\n  const renderResultBadge = (placeholderId: string) => {\n    const selectedOptionId = localAnswers[placeholderId];\n    const selectedOptionText = getOptionTextById(selectedOptionId);\n    const isCorrect = isAnswerCorrect(placeholderId);\n\n    if (!selectedOptionId) {\n      return (\n        <span\n          key={placeholderId}\n          className=\"inline-block align-middle mx-1 my-2\"\n          style={{ display: 'inline-block', verticalAlign: 'middle' }}\n        >\n          <Badge\n            variant=\"solid\"\n            action=\"error\"\n            iconRight={<XCircleIcon />}\n            size=\"large\"\n            className=\"py-1 px-2\"\n          >\n            Não respondido\n          </Badge>\n        </span>\n      );\n    }\n\n    return (\n      <span\n        key={placeholderId}\n        className=\"inline-block align-middle mx-1 my-2\"\n        style={{ display: 'inline-block', verticalAlign: 'middle' }}\n      >\n        <Badge\n          variant=\"solid\"\n          action={isCorrect ? 'success' : 'error'}\n          iconRight={isCorrect ? <CheckCircleIcon /> : <XCircleIcon />}\n          size=\"large\"\n          className=\"py-1 px-2\"\n        >\n          <span className=\"text-text-900\">{selectedOptionText}</span>\n        </Badge>\n      </span>\n    );\n  };\n\n  // Render the correct answer for resolution\n  const renderResolutionAnswer = (placeholderId: string) => {\n    // The placeholderId IS the correct option ID\n    const correctOptionText = getOptionTextById(placeholderId);\n\n    return (\n      <span className=\"inline mx-1 text-success-600 font-semibold border-b-2 border-success-600\">\n        {correctOptionText}\n      </span>\n    );\n  };\n\n  // Parse text and render with selects\n  const renderTextWithSelects = (text: string, isResolution?: boolean) => {\n    const elements: Array<{ element: string | ReactNode; id: string }> = [];\n    let lastIndex = 0;\n    const nextId = () => elements.length;\n\n    // Match {uuid} placeholders (UUID format or any alphanumeric with hyphens)\n    const regex = /\\{([a-zA-Z0-9-]+)\\}/g;\n    let match;\n\n    while ((match = regex.exec(text)) !== null) {\n      const [fullMatch, placeholderId] = match;\n      const startIndex = match.index;\n\n      // Add text before the placeholder\n      if (startIndex > lastIndex) {\n        elements.push({\n          element: text.slice(lastIndex, startIndex),\n          id: `${baseId}-text-${nextId()}`,\n        });\n      }\n\n      // Add the appropriate element based on variant and mode\n      if (isResolution) {\n        elements.push({\n          element: renderResolutionAnswer(placeholderId),\n          id: `${baseId}-resolution-${nextId()}`,\n        });\n      } else if (variant === QuizVariant.DEFAULT) {\n        elements.push({\n          element: renderDefaultSelect(placeholderId),\n          id: `${baseId}-select-${nextId()}`,\n        });\n      } else {\n        elements.push({\n          element: renderResultBadge(placeholderId),\n          id: `${baseId}-result-${nextId()}`,\n        });\n      }\n\n      lastIndex = match.index + fullMatch.length;\n    }\n\n    // Add remaining text\n    if (lastIndex < text.length) {\n      elements.push({\n        element: text.slice(lastIndex),\n        id: `${baseId}-text-${nextId()}`,\n      });\n    }\n\n    return elements;\n  };\n\n  // Render HTML content with selects replacing placeholders\n  const renderHtmlWithSelects = (\n    htmlContent: string,\n    isResolution?: boolean\n  ) => {\n    // For now, we'll strip HTML and render plain text with selects\n    // This preserves the placeholder functionality while handling HTML content\n    const textContent = stripHtmlTags(htmlContent);\n    return renderTextWithSelects(textContent, isResolution);\n  };\n\n  if (!currentQuestion || !additionalContent) {\n    return (\n      <>\n        <QuizSubTitle subTitle=\"Preenchimento\" />\n        <QuizContainer className=\"h-auto pb-0\">\n          <div className=\"space-y-6 px-4 h-auto\">\n            <Text\n              size=\"md\"\n              color=\"text-text-600\"\n              weight=\"normal\"\n              className={cn(paddingBottom)}\n            >\n              Nenhum conteúdo disponível para esta questão.\n            </Text>\n          </div>\n        </QuizContainer>\n      </>\n    );\n  }\n\n  return (\n    <>\n      <QuizSubTitle subTitle=\"Preencha as lacunas\" />\n\n      <QuizContainer\n        className={cn('', variant !== QuizVariant.RESULT && paddingBottom)}\n      >\n        <div className=\"px-4\">\n          <Text\n            as=\"div\"\n            size=\"lg\"\n            color=\"text-text-900\"\n            weight=\"normal\"\n            className=\"leading-[2.5] *:inline\"\n          >\n            {renderHtmlWithSelects(additionalContent).map((element) => (\n              <Fragment key={element.id}>{element.element}</Fragment>\n            ))}\n          </Text>\n        </div>\n      </QuizContainer>\n\n      {variant === QuizVariant.RESULT && (\n        <>\n          <QuizSubTitle subTitle=\"Resposta correta\" />\n\n          <QuizContainer className={cn('', paddingBottom)}>\n            <div className=\"px-4\">\n              <Text\n                as=\"div\"\n                size=\"lg\"\n                color=\"text-text-900\"\n                weight=\"normal\"\n                className=\"leading-[2.5] *:inline\"\n              >\n                {renderHtmlWithSelects(additionalContent, true).map(\n                  (element) => (\n                    <Fragment key={element.id}>{element.element}</Fragment>\n                  )\n                )}\n              </Text>\n            </div>\n          </QuizContainer>\n        </>\n      )}\n    </>\n  );\n};\n\nconst QuizImageQuestion = ({ paddingBottom }: QuizVariantInterface) => {\n  const {\n    variant,\n    getCurrentQuestion,\n    getCurrentAnswer,\n    selectDissertativeAnswer,\n    getQuestionResultByQuestionId,\n  } = useQuizStore();\n\n  const currentQuestion = getCurrentQuestion();\n  const currentAnswer = getCurrentAnswer();\n  const currentQuestionResult = getQuestionResultByQuestionId(\n    currentQuestion?.id || ''\n  );\n\n  // Get image URL from additionalContent\n  const imageUrl = currentQuestion?.additionalContent || '';\n\n  // Parse correct coordinates from first option (stored as JSON: {\"x\": number, \"y\": number})\n  const correctPositionRelative = useMemo(() => {\n    if (!currentQuestion?.options || currentQuestion.options.length === 0) {\n      return { x: 0.5, y: 0.5 }; // Default center\n    }\n    try {\n      const coords = JSON.parse(currentQuestion.options[0].option);\n      if (typeof coords.x === 'number' && typeof coords.y === 'number') {\n        // Coordinates are stored as percentages (0-100), convert to relative (0-1)\n        return { x: coords.x / 100, y: coords.y / 100 };\n      }\n    } catch {\n      // Fall back to default\n    }\n    return { x: 0.5, y: 0.5 };\n  }, [currentQuestion?.options]);\n\n  // Calculate correctRadiusRelative automatically based on the circle dimensions\n  const calculateCorrectRadiusRelative = (): number => {\n    // The correct answer circle has width: 15% and height: 30%\n    // We'll use the average of these as the radius\n    const circleWidthRelative = 0.15; // 15%\n    const circleHeightRelative = 0.3; // 30%\n\n    // Calculate the average radius (half of the average of width and height)\n    const averageRadius = (circleWidthRelative + circleHeightRelative) / 4;\n\n    // Add a small tolerance for better user experience\n    const tolerance = 0.02; // 2% tolerance\n\n    return averageRadius + tolerance;\n  };\n\n  const correctRadiusRelative = calculateCorrectRadiusRelative();\n\n  // Parse user's answer from stored JSON or result\n  const storedUserAnswer = useMemo(() => {\n    if (variant === QuizVariant.RESULT && currentQuestionResult?.answer) {\n      try {\n        const coords = JSON.parse(currentQuestionResult.answer);\n        if (typeof coords.x === 'number' && typeof coords.y === 'number') {\n          return { x: coords.x / 100, y: coords.y / 100 };\n        }\n      } catch {\n        // Fall back to null\n      }\n    } else if (currentAnswer?.answer) {\n      try {\n        const coords = JSON.parse(currentAnswer.answer);\n        if (typeof coords.x === 'number' && typeof coords.y === 'number') {\n          return { x: coords.x / 100, y: coords.y / 100 };\n        }\n      } catch {\n        // Fall back to null\n      }\n    }\n    return null;\n  }, [variant, currentQuestionResult?.answer, currentAnswer?.answer]);\n\n  const [clickPositionRelative, setClickPositionRelative] = useState<{\n    x: number;\n    y: number;\n  } | null>(storedUserAnswer);\n\n  // Sync with stored answer when it changes\n  useEffect(() => {\n    setClickPositionRelative(storedUserAnswer);\n  }, [storedUserAnswer]);\n\n  // Helper function to safely convert click coordinates to relative coordinates\n  const convertToRelativeCoordinates = (\n    x: number,\n    y: number,\n    rect: DOMRect\n  ): { x: number; y: number } => {\n    // Guard against division by zero or extremely small dimensions\n    const safeWidth = Math.max(rect.width, 0.001);\n    const safeHeight = Math.max(rect.height, 0.001);\n\n    // Convert to relative coordinates and clamp to [0, 1] range\n    const xRelative = Math.max(0, Math.min(1, x / safeWidth));\n    const yRelative = Math.max(0, Math.min(1, y / safeHeight));\n\n    return { x: xRelative, y: yRelative };\n  };\n\n  const handleImageClick = (event: MouseEvent<HTMLButtonElement>) => {\n    if (variant === QuizVariant.RESULT) return;\n\n    const rect = event.currentTarget.getBoundingClientRect();\n    const x = event.clientX - rect.left;\n    const y = event.clientY - rect.top;\n\n    // Use helper function for safe conversion\n    const positionRelative = convertToRelativeCoordinates(x, y, rect);\n    setClickPositionRelative(positionRelative);\n\n    // Save the answer to the store (as percentages 0-100)\n    if (currentQuestion) {\n      const answerJson = JSON.stringify({\n        x: Math.round(positionRelative.x * 100),\n        y: Math.round(positionRelative.y * 100),\n      });\n      selectDissertativeAnswer(currentQuestion.id, answerJson);\n    }\n  };\n\n  const handleKeyboardActivate = () => {\n    if (variant === QuizVariant.RESULT) return;\n    // Choose a deterministic position for keyboard activation; center is a reasonable default\n    const centerPosition = { x: 0.5, y: 0.5 };\n    setClickPositionRelative(centerPosition);\n\n    // Save the answer to the store (as percentages 0-100)\n    if (currentQuestion) {\n      const answerJson = JSON.stringify({\n        x: Math.round(centerPosition.x * 100),\n        y: Math.round(centerPosition.y * 100),\n      });\n      selectDissertativeAnswer(currentQuestion.id, answerJson);\n    }\n  };\n\n  const isCorrect = () => {\n    if (!clickPositionRelative) return false;\n\n    const distance = Math.sqrt(\n      Math.pow(clickPositionRelative.x - correctPositionRelative.x, 2) +\n        Math.pow(clickPositionRelative.y - correctPositionRelative.y, 2)\n    );\n\n    return distance <= correctRadiusRelative;\n  };\n\n  const getUserCircleColorClasses = () => {\n    if (variant === QuizVariant.DEFAULT) {\n      return 'bg-indicator-primary/70 border-[#F8CC2E]';\n    }\n\n    if (variant === QuizVariant.RESULT) {\n      return isCorrect()\n        ? 'bg-success-600/70 border-white' // Green for correct answer\n        : 'bg-indicator-error/70 border-white'; // Red for incorrect answer\n    }\n\n    return 'bg-success-600/70 border-white';\n  };\n\n  return (\n    <>\n      <QuizSubTitle subTitle=\"Clique na área correta\" />\n\n      <QuizContainer className={cn('', paddingBottom)}>\n        <div\n          data-testid=\"quiz-image-container\"\n          className=\"space-y-6 p-3 relative inline-block\"\n        >\n          {variant == 'result' && (\n            <div\n              data-testid=\"quiz-legend\"\n              className=\"flex items-center gap-4 text-xs\"\n            >\n              <div className=\"flex items-center gap-2\">\n                <div className=\"w-3 h-3 rounded-full bg-indicator-primary/70 border border-[#F8CC2E]\"></div>\n                <span className=\"text-text-600 font-medium text-sm\">\n                  Área correta\n                </span>\n              </div>\n              <div className=\"flex items-center gap-2\">\n                <div className=\"w-3 h-3 rounded-full bg-success-600/70 border border-white\"></div>\n                <span className=\"text-text-600 font-medium text-sm\">\n                  Resposta correta\n                </span>\n              </div>\n              <div className=\"flex items-center gap-2\">\n                <div className=\"w-3 h-3 rounded-full bg-indicator-error/70 border border-white\"></div>\n                <span className=\"text-text-600 font-medium text-sm\">\n                  Resposta incorreta\n                </span>\n              </div>\n            </div>\n          )}\n\n          <button\n            data-testid=\"quiz-image-button\"\n            type=\"button\"\n            className=\"relative cursor-pointer w-full h-full border-0 bg-transparent p-0\"\n            onClick={handleImageClick}\n            onKeyDown={(e) => {\n              if (e.key === 'Enter' || e.key === ' ') {\n                e.preventDefault();\n                handleKeyboardActivate();\n              }\n            }}\n            aria-label=\"Área da imagem interativa\"\n          >\n            <img\n              data-testid=\"quiz-image\"\n              src={imageUrl || ImageQuestion}\n              alt=\"Question\"\n              className=\"w-full h-auto rounded-md\"\n            />\n\n            {/* Correct answer circle - only show in result variant */}\n            {variant === QuizVariant.RESULT && (\n              <div\n                data-testid=\"quiz-correct-circle\"\n                className=\"absolute rounded-full bg-indicator-primary/70 border-4 border-[#F8CC2E] pointer-events-none\"\n                style={{\n                  minWidth: '50px',\n                  maxWidth: '160px',\n                  width: '15%',\n                  aspectRatio: '1 / 1',\n                  left: `calc(${correctPositionRelative.x * 100}% - 7.5%)`,\n                  top: `calc(${correctPositionRelative.y * 100}% - 15%)`,\n                }}\n              />\n            )}\n\n            {/* User's answer circle */}\n            {clickPositionRelative && (\n              <div\n                data-testid=\"quiz-user-circle\"\n                className={`absolute rounded-full border-4 pointer-events-none ${getUserCircleColorClasses()}`}\n                style={{\n                  minWidth: '30px',\n                  maxWidth: '52px',\n                  width: '5%',\n                  aspectRatio: '1 / 1',\n                  left: `calc(${clickPositionRelative.x * 100}% - 2.5%)`,\n                  top: `calc(${clickPositionRelative.y * 100}% - 2.5%)`,\n                }}\n              />\n            )}\n          </button>\n        </div>\n      </QuizContainer>\n    </>\n  );\n};\n\nexport {\n  QuizSubTitle,\n  QuizContainer,\n  QuizMultipleChoice,\n  QuizDissertative,\n  QuizTrueOrFalse,\n  QuizConnectDots,\n  QuizFill,\n  QuizImageQuestion,\n  QuizAlternative,\n};\n","/** Highlight color applied to matched search terms */\nconst HIGHLIGHT_COLOR = '#2883D7';\n\n/**\n * Strip HTML tags from a string\n * SSR-safe: uses DOMParser in browser, iterative fallback on server\n *\n * @param html - String that may contain HTML tags\n * @returns String with HTML tags removed\n *\n * @example\n * stripHtmlTags('<p>Hello <strong>World</strong></p>') // 'Hello World'\n * stripHtmlTags('No tags here') // 'No tags here'\n */\nexport function stripHtmlTags(html: string): string {\n  if (globalThis.window !== undefined && typeof DOMParser !== 'undefined') {\n    const doc = new DOMParser().parseFromString(html, 'text/html');\n    return doc.body.textContent || '';\n  }\n  // Server-side fallback: iterative O(n) approach to avoid regex backtracking\n  let result = '';\n  let inTag = false;\n  for (const char of html) {\n    if (char === '<') {\n      inTag = true;\n    } else if (char === '>') {\n      inTag = false;\n    } else if (!inTag) {\n      result += char;\n    }\n  }\n  return result;\n}\n\n/**\n * Normalize a string for case- and accent-insensitive comparison.\n * Decomposes characters via NFD, strips diacritic marks, then lowercases.\n *\n * @param value - The string to normalize\n * @returns Normalized string suitable for comparison\n *\n * @example\n * normalizeText('Matemática') // 'matematica'\n * normalizeText('Ação')       // 'acao'\n */\nexport function normalizeText(value: string): string {\n  return value.normalize('NFD').replace(/[̀-ͯ]/g, '').toLowerCase();\n}\n\n/**\n * Wrap every occurrence of a search term in a highlight `<span>` inside an HTML string.\n *\n * Traverses only text nodes so HTML tags, attributes, and entities are never touched.\n * Matching is case-insensitive and regex special characters in the term are escaped.\n * SSR-safe: returns the original HTML unchanged when running outside a browser context.\n *\n * @param html - The HTML string to annotate (e.g. a question statement)\n * @param term - The search term to highlight\n * @returns HTML string with match occurrences wrapped in highlight spans,\n *          or the original string when `term`/`html` is empty or in an SSR environment\n *\n * @example\n * highlightSearchTerm('<p>Hello World</p>', 'world')\n * // '<p>Hello <span style=\"color:#2883D7;font-weight:600\">World</span></p>'\n *\n * highlightSearchTerm('<span class=\"katex\">math</span>', 'katex')\n * // '<span class=\"katex\">math</span>'  ← tag/attribute left intact\n */\nexport function highlightSearchTerm(html: string, term: string): string {\n  if (!term || !html) return html;\n  if (globalThis.window === undefined) return html;\n\n  const escaped = term.replace(/[.*+?^${}()|[\\]\\\\]/g, String.raw`\\$&`);\n  const matchRegex = new RegExp(escaped, 'gi');\n\n  const container = document.createElement('div');\n  container.innerHTML = html;\n\n  const highlightTextNode = (textNode: Text): void => {\n    const text = textNode.data;\n    const matches = text.match(matchRegex);\n    if (!matches) return;\n\n    const parts = text.split(matchRegex);\n    const fragment = document.createDocumentFragment();\n\n    parts.forEach((part, i) => {\n      if (part) fragment.append(document.createTextNode(part));\n      if (i < matches.length) {\n        const span = document.createElement('span');\n        span.style.color = HIGHLIGHT_COLOR;\n        span.style.fontWeight = '600';\n        span.textContent = matches[i];\n        fragment.append(span);\n      }\n    });\n\n    textNode.replaceWith(fragment);\n  };\n\n  const walk = (node: Node): void => {\n    if (node.nodeType === Node.TEXT_NODE) {\n      highlightTextNode(node as Text);\n    } else {\n      // Snapshot childNodes before mutating so the loop is not affected by replacements\n      Array.from(node.childNodes).forEach(walk);\n    }\n  };\n\n  walk(container);\n  return container.innerHTML;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACVP,IAAM,kBAAkB;AAajB,SAAS,cAAc,MAAsB;AAClD,MAAI,WAAW,WAAW,UAAa,OAAO,cAAc,aAAa;AACvE,UAAM,MAAM,IAAI,UAAU,EAAE,gBAAgB,MAAM,WAAW;AAC7D,WAAO,IAAI,KAAK,eAAe;AAAA,EACjC;AAEA,MAAI,SAAS;AACb,MAAI,QAAQ;AACZ,aAAW,QAAQ,MAAM;AACvB,QAAI,SAAS,KAAK;AAChB,cAAQ;AAAA,IACV,WAAW,SAAS,KAAK;AACvB,cAAQ;AAAA,IACV,WAAW,CAAC,OAAO;AACjB,gBAAU;AAAA,IACZ;AAAA,EACF;AACA,SAAO;AACT;AAaO,SAAS,cAAc,OAAuB;AACnD,SAAO,MAAM,UAAU,KAAK,EAAE,QAAQ,UAAU,EAAE,EAAE,YAAY;AAClE;AAqBO,SAAS,oBAAoB,MAAc,MAAsB;AACtE,MAAI,CAAC,QAAQ,CAAC,KAAM,QAAO;AAC3B,MAAI,WAAW,WAAW,OAAW,QAAO;AAE5C,QAAM,UAAU,KAAK,QAAQ,uBAAuB,OAAO,QAAQ;AACnE,QAAM,aAAa,IAAI,OAAO,SAAS,IAAI;AAE3C,QAAM,YAAY,SAAS,cAAc,KAAK;AAC9C,YAAU,YAAY;AAEtB,QAAM,oBAAoB,CAAC,aAAyB;AAClD,UAAM,OAAO,SAAS;AACtB,UAAM,UAAU,KAAK,MAAM,UAAU;AACrC,QAAI,CAAC,QAAS;AAEd,UAAM,QAAQ,KAAK,MAAM,UAAU;AACnC,UAAM,WAAW,SAAS,uBAAuB;AAEjD,UAAM,QAAQ,CAAC,MAAM,MAAM;AACzB,UAAI,KAAM,UAAS,OAAO,SAAS,eAAe,IAAI,CAAC;AACvD,UAAI,IAAI,QAAQ,QAAQ;AACtB,cAAM,OAAO,SAAS,cAAc,MAAM;AAC1C,aAAK,MAAM,QAAQ;AACnB,aAAK,MAAM,aAAa;AACxB,aAAK,cAAc,QAAQ,CAAC;AAC5B,iBAAS,OAAO,IAAI;AAAA,MACtB;AAAA,IACF,CAAC;AAED,aAAS,YAAY,QAAQ;AAAA,EAC/B;AAEA,QAAM,OAAO,CAAC,SAAqB;AACjC,QAAI,KAAK,aAAa,KAAK,WAAW;AACpC,wBAAkB,IAAY;AAAA,IAChC,OAAO;AAEL,YAAM,KAAK,KAAK,UAAU,EAAE,QAAQ,IAAI;AAAA,IAC1C;AAAA,EACF;AAEA,OAAK,SAAS;AACd,SAAO,UAAU;AACnB;;;AD9EA,SAAS,uBAAuB;AAChC,SAAS,mBAAmB;A;;;;;AAQ8B,SA6LtD,YAAAA,WA7LsD,KA6LtD,YA7LsD;AAJnD,IAAM,iBAAiB,CAAC,WAA0B;AACvD,UAAQ,QAAQ;AAAA,IACd;AACE,aACE,oBAAC,iBAAM,SAAQ,SAAQ,QAAO,WAAU,UAAU,oBAAC,mBAAgB,GAAI,8BAEvE;AAAA,IAEJ;AACE,aACE,oBAAC,iBAAM,SAAQ,SAAQ,QAAO,SAAQ,UAAU,oBAAC,eAAY,GAAI,gCAEjE;AAAA,IAEJ;AACE,aAAO;AAAA,EACX;AACF;AAEO,IAAM,kBAAkB,CAAC,mBAAkC;AAChE,UAAQ,gBAAgB;AAAA,IACtB;AACE,aAAO;AAAA,IACT;AACE,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAMA,IAAM,sBAAsB,CAAC,WAA4C;AAEvE,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,UAAM,SAAiC,CAAC;AACxC,eAAW,QAAQ,QAAQ;AACzB,UACE,QACA,OAAO,SAAS,YAChB,cAAc,QACd,mBAAmB,MACnB;AACA,eAAO,KAAK,QAAkB,IAAI,KAAK;AAAA,MACzC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAGA,MAAI,UAAU,OAAO,WAAW,UAAU;AACxC,WAAO;AAAA,EACT;AAEA,SAAO,CAAC;AACV;AAOA,IAAM,qBAAqB,CACzB,SACA,cACA,kBAC2B;AAC3B,MAAI,mCAAgC;AAClC,QAAI,CAAC,aAAc,QAAO,CAAC;AAC3B,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,YAAY;AACtC,aAAO,oBAAoB,MAAM;AAAA,IACnC,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AACA,MAAI,eAAe;AACjB,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,aAAa;AACvC,aAAO,oBAAoB,MAAM;AAAA,IACnC,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AACA,SAAO,CAAC;AACV;AAMA,IAAM,kBAAkB,CACtB,cAC6B;AAC7B,MAAI,cAAc,KAAM;AACxB,MAAI,cAAc,MAAO;AACzB,SAAO;AACT;AAMA,IAAM,eAAe;AAAA,EACnB,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ;AAC/B,WACE,oBAAC,SAAI,WAAU,kBAAkB,GAAG,OAAO,KACzC,8BAAC,OAAE,WAAU,mCAAmC,oBAAS,GAC3D;AAAA,EAEJ;AACF;AAEA,IAAM,gBAAgB,WAGpB,CAAC,EAAE,UAAU,WAAW,GAAG,MAAM,GAAG,QAAQ;AAC5C,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ,CAAC;AAED,IAAM,kBAAkB,CAAC,EAAE,cAAc,MAA4B;AACnE,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,aAAa;AACjB,QAAM,kBAAkB,mBAAmB;AAC3C,QAAM,wBAAwB;AAAA,IAC5B,iBAAiB,MAAM;AAAA,EACzB;AAEA,QAAM,gBAAgB,iBAAiB;AACvC,QAAM,eAAe,iBAAiB,SAAS,IAAI,CAAC,WAAW;AAC7D,QAAI;AACJ,QAAI,mCAAgC;AAClC,YAAM,kBACJ,uBAAuB,SAAS,KAAK,CAAC,OAAO,GAAG,OAAO,OAAO,EAAE,GAC5D,aAAa;AAEnB,YAAM,aAAa,uBAAuB,gBAAgB;AAAA,QACxD,CAAC,mBAAmB,eAAe,aAAa,OAAO;AAAA,MACzD;AAGA,YAAM,2BACJ,uBAAuB,kEAEvB,uBAAuB;AAEzB,UAAI,0BAA0B;AAC5B,YAAI,iBAAiB;AACnB;AAAA,QACF,WAAW,cAAc,CAAC,iBAAiB;AACzC;AAAA,QACF,OAAO;AACL;AAAA,QACF;AAAA,MACF,OAAO;AAEL;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,OAAO,OAAO;AAAA,MACd,OAAO,OAAO;AAAA,MACd;AAAA,IACF;AAAA,EACF,CAAC;AAED,MAAI,CAAC;AACH,WACE,oBAAC,SACC,8BAAC,OAAE,uCAAmB,GACxB;AAGJ,SACE,qBAAAA,WAAA,EACE;AAAA,wBAAC,gBAAa,UAAS,gBAAe;AAAA,IAEtC,oBAAC,iBAAc,WAAW,GAAG,IAAI,aAAa,GAC5C,8BAAC,SAAI,WAAU,aACb;AAAA,MAAC;AAAA;AAAA,QACC,MAAM,sCAAkC,gBAAgB;AAAA,QAExD,MAAM,YAAY,iBAAiB,MAAM,GAAG;AAAA,QAC5C,QAAO;AAAA,QACP;AAAA,QACA,OACE,oCACI,uBAAuB,gBAAgB,CAAC,GAAG,YAAY,KACvD,eAAe,YAAY;AAAA,QAEjC,eACE,oCACI,uBAAuB,gBAAgB,CAAC,GAAG,YAAY,KACvD,eAAe,YAAY;AAAA,QAEjC,eAAe,CAAC,UAAU;AACxB,cAAI,iBAAiB;AACnB,yBAAa,gBAAgB,IAAI,KAAK;AAAA,UACxC;AAAA,QACF;AAAA;AAAA,MAlBK,YAAY,iBAAiB,MAAM,GAAG;AAAA,IAmB7C,GACF,GACF;AAAA,KACF;AAEJ;AAEA,IAAM,qBAAqB,CAAC,EAAE,cAAc,MAA4B;AACtE,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,aAAa;AACjB,QAAM,kBAAkB,mBAAmB;AAM3C,QAAM,cAAc,aAAa,CAAC,UAAU,MAAM,WAAW;AAC7D,QAAM,oBAAoB;AAAA,IACxB,MACE,kBACI,YAAY;AAAA,MACV,CAAC,WAAW,OAAO,eAAe,gBAAgB;AAAA,IACpD,IACA,CAAC;AAAA,IACP,CAAC,aAAa,eAAe;AAAA,EAC/B;AACA,QAAM,wBAAwB;AAAA,IAC5B,iBAAiB,MAAM;AAAA,EACzB;AAEA,QAAM,wBAAwB,OAAiB,CAAC,CAAC;AACjD,QAAM,oBAAoB,OAAe,EAAE;AAI3C,QAAM,sBAAsB,QAAQ,MAAM;AACxC,QAAI,qBAAqB,kBAAkB,SAAS,GAAG;AAErD,YAAM,8BAA8B,kBAAkB;AAAA,QAAK,CAAC,WAC1D,MAAM,QAAQ,OAAO,iBAAiB;AAAA,MACxC;AACA,UAAI,6BAA6B;AAC/B,eAAO,4BAA4B,qBAAqB,CAAC;AAAA,MAC3D;AAEA,aAAO,kBAAkB,IAAI,CAAC,WAAW,OAAO,QAAQ;AAAA,IAC1D;AACA,WAAO,CAAC;AAAA,EACV,GAAG,CAAC,iBAAiB,CAAC;AAGtB,QAAM,iBAAiB,QAAQ,MAAM;AACnC,WAAO,qBAAqB,OAAO,CAAC,OAAqB,OAAO,IAAI,KAAK,CAAC;AAAA,EAC5E,GAAG,CAAC,mBAAmB,CAAC;AAGxB,QAAM,uBAAuB,QAAQ,MAAM;AAEzC,QAAI,mCAAgC;AAClC,aACE,uBAAuB,iBAAiB,IAAI,CAAC,OAAO,GAAG,QAAQ,KAAK,CAAC;AAAA,IAEzE;AAEA,UAAM,oBAAoB,iBAAiB,MAAM;AACjD,UAAM,qBAAqB,kBAAkB,YAAY;AAEzD,QAAI,oBAAoB;AACtB,wBAAkB,UAAU;AAC5B,4BAAsB,UAAU;AAChC,aAAO;AAAA,IACT;AAGA,UAAM,mBACJ,KAAK,UAAU,sBAAsB,OAAO,MAC5C,KAAK,UAAU,cAAc;AAC/B,QAAI,kBAAkB;AACpB,4BAAsB,UAAU;AAChC,aAAO;AAAA,IACT;AAEA,WAAO,sBAAsB;AAAA,EAC/B,GAAG;AAAA,IACD;AAAA,IACA,iBAAiB;AAAA,IACjB;AAAA,IACA,uBAAuB;AAAA,EACzB,CAAC;AAGD,QAAM,uBAAuB;AAAA,IAC3B,CAAC,WAAqB;AACpB,UAAI,iBAAiB;AACnB,6BAAqB,gBAAgB,IAAI,MAAM;AAAA,MACjD;AAAA,IACF;AAAA,IACA,CAAC,iBAAiB,oBAAoB;AAAA,EACxC;AAGA,QAAM,cAAc;AAAA,IAClB,MAAM,YAAY,iBAAiB,MAAM,GAAG;AAAA,IAC5C,CAAC,iBAAiB,EAAE;AAAA,EACtB;AACA,QAAM,UAAU,iBAAiB,SAAS,IAAI,CAAC,WAAW;AACxD,QAAI;AAEJ,QAAI,mCAAgC;AAClC,YAAM,kBACJ,uBAAuB,SAAS,KAAK,CAAC,OAAO,GAAG,OAAO,OAAO,EAAE,GAC5D,aAAa;AAEnB,YAAM,aAAa,uBAAuB,iBAAiB;AAAA,QACzD,CAAC,OAAO,GAAG,aAAa,OAAO;AAAA,MACjC;AAGA,YAAM,2BACJ,uBAAuB,kEAEvB,uBAAuB;AAEzB,UAAI,0BAA0B;AAC5B,YAAI,iBAAiB;AACnB;AAAA,QACF,WAAW,cAAc,CAAC,iBAAiB;AACzC;AAAA,QACF,OAAO;AACL;AAAA,QACF;AAAA,MACF,OAAO;AAEL;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,OAAO,OAAO;AAAA,MACd,OAAO,OAAO;AAAA,MACd;AAAA,IACF;AAAA,EACF,CAAC;AAED,MAAI,CAAC;AACH,WACE,oBAAC,SACC,8BAAC,OAAE,6CAAyB,GAC9B;AAEJ,SACE,qBAAAA,WAAA,EACE;AAAA,wBAAC,gBAAa,UAAS,gBAAe;AAAA,IAEtC,oBAAC,iBAAc,WAAW,GAAG,IAAI,aAAa,GAC5C,8BAAC,SAAI,WAAU,aACb;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QAEA,MAAM;AAAA,QACN,gBAAgB;AAAA,QAChB,wBAAwB;AAAA,QACxB,MAAM,sCAAkC,gBAAgB;AAAA;AAAA,MAJnD;AAAA,IAKP,GACF,GACF;AAAA,KACF;AAEJ;AAEA,IAAM,mBAAmB,CAAC,EAAE,cAAc,MAA4B;AACpE,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,aAAa;AAEjB,QAAM,kBAAkB,mBAAmB;AAC3C,QAAM,wBAAwB;AAAA,IAC5B,iBAAiB,MAAM;AAAA,EACzB;AAEA,QAAM,gBAAgB,iBAAiB;AACvC,QAAM,cAAc,OAA4B,IAAI;AACpD,QAAM,YAAY,yBAAyB;AAE3C,QAAM,qBAAqB,CAAC,UAAkB;AAC5C,QAAI,iBAAiB;AACnB,+BAAyB,gBAAgB,IAAI,KAAK;AAAA,IACpD;AAAA,EACF;AAGA,QAAM,uBAAuB,YAAY,MAAM;AAC7C,QAAI,YAAY,SAAS;AACvB,kBAAY,QAAQ,MAAM,SAAS;AACnC,YAAM,eAAe,YAAY,QAAQ;AACzC,YAAM,YAAY;AAClB,YAAM,YAAY;AAClB,YAAM,YAAY,KAAK,IAAI,KAAK,IAAI,cAAc,SAAS,GAAG,SAAS;AACvE,kBAAY,QAAQ,MAAM,SAAS,GAAG,SAAS;AAAA,IACjD;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,YAAU,MAAM;AACd,yBAAqB;AAAA,EACvB,GAAG,CAAC,eAAe,oBAAoB,CAAC;AAExC,MAAI,CAAC,iBAAiB;AACpB,WACE,oBAAC,SAAI,WAAU,aACb,8BAAC,OAAE,WAAU,yBAAwB,8CAA0B,GACjE;AAAA,EAEJ;AAEA,QAAM,eACH,WAAW,WACR,uBAAuB,SACvB,eAAe,WAAW;AAChC,SACE,qBAAAA,WAAA,EACE;AAAA,wBAAC,gBAAa,UAAS,YAAW;AAAA,IAElC,oBAAC,iBAAc,WAAW,GAAG,WAAW,YAAY,aAAa,GAC/D,8BAAC,SAAI,WAAU,2CACZ,gDACC,oBAAC,SAAI,WAAU,aACb;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,aAAY;AAAA,QACZ,OAAO;AAAA,QACP,UAAU,CAAC,MAAM,mBAAmB,EAAE,OAAO,KAAK;AAAA,QAClD,MAAM;AAAA,QACN,WAAU;AAAA,QACV,WAAW;AAAA,QACX,oBAAoB,CAAC,CAAC;AAAA;AAAA,IACxB,GACF,IAEA,oBAAC,SAAI,WAAU,aACb,8BAAC,OAAE,WAAU,6CACV,yBAAe,8BAClB,GACF,GAEJ,GACF;AAAA,IAEC,qCACC,uBAAuB,mBACrB,qBAAAA,WAAA,EACE;AAAA,0BAAC,gBAAa,UAAS,iCAA0B;AAAA,MAEjD,oBAAC,iBAAc,WAAW,GAAG,IAAI,aAAa,GAC5C,8BAAC,OAAE,WAAU,6CACV,iCAAuB,iBAC1B,GACF;AAAA,OACF;AAAA,KAEN;AAEJ;AAEA,IAAM,kBAAkB,CAAC,EAAE,cAAc,MAA4B;AACnE,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,aAAa;AAEjB,QAAM,kBAAkB,mBAAmB;AAC3C,QAAM,gBAAgB,iBAAiB;AACvC,QAAM,wBAAwB;AAAA,IAC5B,iBAAiB,MAAM;AAAA,EACzB;AAGA,QAAM,UAAU,QAAQ,MAAM;AAC5B,QAAI,qCAAkC,uBAAuB,SAAS;AACpE,aAAO,sBAAsB;AAAA,IAC/B;AACA,WAAO,iBAAiB,WAAW,CAAC;AAAA,EACtC,GAAG,CAAC,SAAS,uBAAuB,SAAS,iBAAiB,OAAO,CAAC;AAGtE,QAAM,gBAAwC,QAAQ,MAAM;AAC1D,WAAO;AAAA,MACL;AAAA,MACA,uBAAuB;AAAA,MACvB,eAAe;AAAA,IACjB;AAAA,EACF,GAAG,CAAC,SAAS,uBAAuB,QAAQ,eAAe,MAAM,CAAC;AAGlE,QAAM,CAAC,cAAc,eAAe,IAClC,SAAiC,aAAa;AAGhD,YAAU,MAAM;AACd,oBAAgB,aAAa;AAAA,EAC/B,GAAG,CAAC,eAAe,iBAAiB,EAAE,CAAC;AAGvC,QAAM,qBAAqB,CAAC,UAAkB,UAAkB;AAC9D,QAAI,CAAC,gBAAiB;AAItB,UAAM,oBAAoB,0BAA0B,gBAAgB,EAAE;AACtE,QAAI,cAAsC,CAAC;AAC3C,QAAI,mBAAmB,QAAQ;AAC7B,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,kBAAkB,MAAM;AAClD,sBAAc,oBAAoB,MAAM;AAAA,MAC1C,QAAQ;AAAA,MAER;AAAA,IACF;AAGA,UAAM,gBAAgB;AAAA,MACpB,GAAG;AAAA,MACH,GAAG;AAAA,MACH,CAAC,QAAQ,GAAG;AAAA,IACd;AACA,oBAAgB,aAAa;AAG7B,6BAAyB,gBAAgB,IAAI,KAAK,UAAU,aAAa,CAAC;AAAA,EAC5E;AAGA,QAAM,qBAAqB,CAAC,aAAyC;AACnE,WAAO,aAAa,QAAQ;AAAA,EAC9B;AAEA,QAAM,mBAAmB,CAAC,UAAkB,OAAO,cAAc,KAAK,KAAK;AAE3E,QAAM,mBAAmB;AAGzB,QAAM,mBACJ,uBAAuB,kEACvB,uBAAuB;AAEzB,MAAI,QAAQ,WAAW,GAAG;AACxB,WACE,oBAAC,iBAAc,WAAW,GAAG,IAAI,aAAa,GAC5C,8BAAC,gBAAK,MAAK,MAAK,WAAU,wBAAuB,oEAEjD,GACF;AAAA,EAEJ;AAEA,SACE,qBAAAA,WAAA,EACE;AAAA,wBAAC,gBAAa,UAAS,gBAAe;AAAA,IAEtC,oBAAC,iBAAc,WAAW,GAAG,IAAI,aAAa,GAC5C,8BAAC,SAAI,WAAU,yBACZ,kBAAQ,IAAI,CAAC,QAAQ,UAAU;AAE9B,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,IAAI;AAAA,QACF,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,YAAM,oBAAoB;AAAA,QACxB,iBAAiB,KAAK;AAAA,QACtB,OAAO;AAAA,MACT;AAEA,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,WAAU;AAAA,UAEV;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAW;AAAA,kBACT;AAAA,kBACA,CAAC,oBAAoB,oBAAoB,cACrC,gBAAgB,cAAc,IAC9B;AAAA,gBACN;AAAA,gBAEA;AAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,SAAS;AAAA,sBACT,WAAU;AAAA;AAAA,kBACZ;AAAA,kBAEC,mBACC;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAK;AAAA,sBACL,OAAO,mBAAmB,OAAO,EAAE;AAAA,sBACnC,eAAe,CAAC,UACd,mBAAmB,OAAO,IAAI,KAAK;AAAA,sBAGrC;AAAA,4CAAC,iBAAc,WAAU,aACvB,8BAAC,eAAY,aAAY,aAAY,GACvC;AAAA,wBAEA,qBAAC,iBACC;AAAA,8CAAC,cAAW,6BAAiC,wBAE7C;AAAA,0BACA,oBAAC,cAAW,wBAA4B,mBAExC;AAAA,2BACF;AAAA;AAAA;AAAA,kBACF,IAEA,oBACA,eAAe,oBAAC,SAAK,yBAAe,cAAc,GAAE;AAAA;AAAA;AAAA,YAExD;AAAA,YAEC,CAAC,oBAAoB,oBACpB,oBAAC,UAAK,WAAU,8CACb,wBACC,qBAAAA,WAAA,EACE;AAAA,mCAAC,gBAAK,MAAK,OAAM,WAAU,iBAAgB;AAAA;AAAA,gBAClB;AAAA,iBACzB;AAAA,cACC,CAAC,oBACA,qBAAC,gBAAK,MAAK,OAAM,WAAU,iBAAgB;AAAA;AAAA,gBACpB;AAAA,iBACvB;AAAA,eAEJ,IAEA,qBAAC,gBAAK,MAAK,OAAM,WAAU,iBAAgB;AAAA;AAAA,cACL;AAAA,eACtC,GAEJ;AAAA;AAAA;AAAA,QA7DG,OAAO,MAAM,UAAU,KAAK;AAAA,MA+DnC;AAAA,IAEJ,CAAC,GACH,GACF;AAAA,KACF;AAEJ;AASA,IAAM,kBAAkB,CAAC,EAAE,cAAc,MAA4B;AACnE,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,aAAa;AAEjB,QAAM,kBAAkB,mBAAmB;AAC3C,QAAM,wBAAwB;AAAA,IAC5B,iBAAiB,MAAM;AAAA,EACzB;AACA,QAAM,gBAAgB,iBAAiB;AAIvC,QAAM,kBAAkB,QAAQ,MAAM;AACpC,QAAI,CAAC,iBAAiB,QAAS,QAAO,CAAC;AACvC,WAAO,gBAAgB;AAAA,EACzB,GAAG,CAAC,iBAAiB,OAAO,CAAC;AAI7B,QAAM,cAAc,QAAQ,MAAM;AAChC,UAAM,OAAO,gBACV,IAAI,CAAC,SAAS,EAAE,OAAO,IAAI,gBAAgB,GAAG,EAAE,EAChD,OAAO,CAAC,QAAQ,IAAI,UAAU,EAAE;AAEnC,WAAO,gBAAgB,MAAM,iBAAiB,MAAM,EAAE;AAAA,EACxD,GAAG,CAAC,iBAAiB,iBAAiB,EAAE,CAAC;AAGzC,QAAM,UAAU,QAAQ,MAAM;AAC5B,WAAO,gBAAgB,IAAI,CAAC,SAAS;AAAA,MACnC,IAAI,IAAI;AAAA,MACR,OAAO,IAAI;AAAA,MACX,eAAe,IAAI,gBAAgB;AAAA,IACrC,EAAE;AAAA,EACJ,GAAG,CAAC,eAAe,CAAC;AAKpB,QAAM,gBAAwC,QAAQ,MAAM;AAC1D,QACE,qCACA,uBAAuB,iBACvB;AAEA,YAAM,UAAkC,CAAC;AACzC,iBAAW,SAAS,sBAAsB,iBAAiB;AACzD,gBAAQ,MAAM,QAAQ,IAAI,MAAM;AAAA,MAClC;AACA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,MACL;AAAA,MACA,uBAAuB;AAAA,MACvB,eAAe;AAAA,IACjB;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA,uBAAuB;AAAA,IACvB,uBAAuB;AAAA,IACvB,eAAe;AAAA,EACjB,CAAC;AAED,QAAM,CAAC,aAAa,cAAc,IAAI,SAAuB,CAAC,CAAC;AAG/D,YAAU,MAAM;AACd,QAAI,QAAQ,SAAS,GAAG;AACtB;AAAA,QACE,QAAQ,IAAI,CAAC,WAAW;AACtB,gBAAM,cAAc,cAAc,OAAO,EAAE,KAAK;AAChD,iBAAO;AAAA,YACL,QAAQ,OAAO;AAAA,YACf,WAAW;AAAA,YACX,eAAe,OAAO;AAAA,YACtB,WAAW,cACP,gBAAgB,OAAO,gBACvB;AAAA,UACN;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,GAAG,CAAC,SAAS,aAAa,CAAC;AAE3B,QAAM,kBAAkB,CAAC,aAAqB,aAAqB;AACjE,UAAM,SAAS,QAAQ,WAAW;AAClC,QAAI,CAAC,UAAU,CAAC,gBAAiB;AAGjC,mBAAe,CAAC,SAAS;AACvB,YAAM,OAAO,CAAC,GAAG,IAAI;AACrB,WAAK,WAAW,IAAI;AAAA,QAClB,QAAQ,OAAO;AAAA,QACf,WAAW;AAAA,QACX,eAAe,OAAO;AAAA,QACtB,WAAW,WAAW,aAAa,OAAO,gBAAgB;AAAA,MAC5D;AACA,aAAO;AAAA,IACT,CAAC;AAGD,UAAM,oBAAoB,0BAA0B,gBAAgB,EAAE;AACtE,QAAI,cAAsC,CAAC;AAC3C,QAAI,mBAAmB,QAAQ;AAC7B,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,kBAAkB,MAAM;AAClD,sBAAc,oBAAoB,MAAM;AAAA,MAC1C,QAAQ;AAAA,MAER;AAAA,IACF;AAGA,UAAM,aAAa;AAAA,MACjB,GAAG;AAAA,MACH,GAAG;AAAA,MACH,CAAC,OAAO,EAAE,GAAG;AAAA,IACf;AACA,6BAAyB,gBAAgB,IAAI,KAAK,UAAU,UAAU,CAAC;AAAA,EACzE;AAEA,QAAM,mBAAmB,CAAC,UAAkB,OAAO,cAAc,KAAK,KAAK;AAE3E,QAAM,mBAAmB;AACzB,QAAM,eAAe,IAAI;AAAA,IACvB,YAAY,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,OAAO;AAAA,EACpD;AAEA,MAAI,QAAQ,WAAW,GAAG;AACxB,WACE,oBAAC,iBAAc,WAAW,GAAG,IAAI,aAAa,GAC5C,8BAAC,gBAAK,MAAK,MAAK,WAAU,wBAAuB,iEAEjD,GACF;AAAA,EAEJ;AAEA,SACE,qBAAAA,WAAA,EACE;AAAA,wBAAC,gBAAa,UAAS,gBAAe;AAAA,IAEtC,oBAAC,iBAAc,WAAW,GAAG,IAAI,aAAa,GAC5C,8BAAC,SAAI,WAAU,yBACZ,kBAAQ,IAAI,CAAC,QAAQ,UAAU;AAC9B,YAAM,SAAS,YAAY,KAAK,KAAK;AAAA,QACnC,QAAQ,OAAO;AAAA,QACf,WAAW;AAAA,QACX,eAAe,OAAO;AAAA,QACtB,WAAW;AAAA,MACb;AACA,YAAM,iBAAiB,gBAAgB,OAAO,SAAS;AACvD,aACE,qBAAC,aAAwB,WAAU,uBACjC;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAW;AAAA,cACT;AAAA,cACA,CAAC,oBAAoB,iBACjB,gBAAgB,cAAc,IAC9B;AAAA,YACN;AAAA,YAEA;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAS;AAAA,oBACP,iBAAiB,KAAK;AAAA,oBACtB,OAAO;AAAA,kBACT;AAAA,kBACA,WAAU;AAAA;AAAA,cACZ;AAAA,cAEC,mBACC;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,OAAO,OAAO,aAAa;AAAA,kBAC3B,eAAe,CAAC,UAAU,gBAAgB,OAAO,KAAK;AAAA,kBAEtD;AAAA;AAAA,sBAAC;AAAA;AAAA,wBACC,WAAU;AAAA,wBACV,OACE,OAAO,YACH,cAAc,OAAO,SAAS,IAC9B;AAAA,wBAGN,8BAAC,eAAY,aAAY,yBAAkB;AAAA;AAAA,oBAC7C;AAAA,oBAEA,oBAAC,iBACE,sBACE;AAAA,sBACC,CAAC,QACC,CAAC,aAAa,IAAI,IAAI,KAAK,KAC3B,OAAO,cAAc,IAAI;AAAA,oBAC7B,EACC,IAAI,CAAC,QACJ;AAAA,sBAAC;AAAA;AAAA,wBAEC,OAAO,IAAI;AAAA,wBACX,OAAO,cAAc,IAAI,KAAK;AAAA,wBAC9B,UAAQ;AAAA,wBAEP,wBAAc,IAAI,KAAK;AAAA;AAAA,sBALnB,IAAI;AAAA,oBAMX,CACD,GACL;AAAA;AAAA;AAAA,cACF,IAEA,oBAAC,SACE,iBAAO,cAAc,OAClB,OACA,eAAe,cAAc,GACnC;AAAA;AAAA;AAAA,QAEJ;AAAA,QAEC,CAAC,oBACA,qBAAC,UAAK,WAAU,oCACd;AAAA,+BAAC,gBAAK,MAAK,OAAM,WAAU,iBAAgB;AAAA;AAAA,YACnB;AAAA,YACrB,OAAO,YACJ,cAAc,OAAO,SAAS,IAC9B;AAAA,aACN;AAAA,UACC,OAAO,cAAc,SACpB,qBAAC,gBAAK,MAAK,OAAM,WAAU,iBAAgB;AAAA;AAAA,YACtB,cAAc,OAAO,aAAa;AAAA,aACvD;AAAA,WAEJ;AAAA,WA3EU,OAAO,EA6ErB;AAAA,IAEJ,CAAC,GACH,GACF;AAAA,KACF;AAEJ;AAEA,IAAM,WAAW,CAAC,EAAE,cAAc,MAA4B;AAC5D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,aAAa;AAEjB,QAAM,kBAAkB,mBAAmB;AAC3C,QAAM,wBAAwB;AAAA,IAC5B,iBAAiB,MAAM;AAAA,EACzB;AACA,QAAM,gBAAgB,iBAAiB;AAEvC,QAAM,SAAS,MAAM;AAIrB,QAAM,oBACJ,oCACI,uBAAuB,qBACvB,iBAAiB,qBACjB,KACA,iBAAiB,qBAAqB;AAI5C,QAAM,kBACJ,oCACI,uBAAuB,WAAW,iBAAiB,WAAW,CAAC,IAC/D,iBAAiB,WAAW,CAAC;AAGnC,QAAM,kBAAkB,QAAQ,MAAM;AACpC,WAAO,gBAAgB,iBAAiB,iBAAiB,MAAM,EAAE;AAAA,EACnE,GAAG,CAAC,iBAAiB,iBAAiB,EAAE,CAAC;AAKzC,QAAM,gBAAwC,QAAQ,MAAM;AAC1D,QAAI,qCAAkC,uBAAuB,aAAa;AAExE,aAAO,sBAAsB;AAAA,IAC/B;AAEA,WAAO;AAAA,MACL;AAAA,MACA,uBAAuB;AAAA,MACvB,eAAe;AAAA,IACjB;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA,uBAAuB;AAAA,IACvB,uBAAuB;AAAA,IACvB,eAAe;AAAA,EACjB,CAAC;AAED,QAAM,CAAC,cAAc,eAAe,IAClC,SAAiC,aAAa;AAGhD,YAAU,MAAM;AACd,oBAAgB,aAAa;AAAA,EAC/B,GAAG,CAAC,eAAe,iBAAiB,EAAE,CAAC;AAGvC,QAAM,qBAAqB,CAAC,eAAuB,aAAqB;AACtE,QAAI,CAAC,gBAAiB;AAGtB,UAAM,oBAAoB,0BAA0B,gBAAgB,EAAE;AACtE,QAAI,cAAsC,CAAC;AAC3C,QAAI,mBAAmB,QAAQ;AAC7B,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,kBAAkB,MAAM;AAClD,sBAAc,oBAAoB,MAAM;AAAA,MAC1C,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,UAAM,aAAa;AAAA,MACjB,GAAG;AAAA,MACH,GAAG;AAAA,MACH,CAAC,aAAa,GAAG;AAAA,IACnB;AACA,oBAAgB,UAAU;AAG1B,6BAAyB,gBAAgB,IAAI,KAAK,UAAU,UAAU,CAAC;AAAA,EACzE;AAGA,QAAM,oBAAoB,CAAC,aAA6B;AACtD,UAAM,SAAS,gBAAgB,KAAK,CAAC,QAAQ,IAAI,OAAO,QAAQ;AAChE,WAAO,cAAc,QAAQ,UAAU,EAAE;AAAA,EAC3C;AAGA,QAAM,kBAAkB,CAAC,kBAAmC;AAC1D,UAAM,mBAAmB,aAAa,aAAa;AAEnD,WAAO,qBAAqB;AAAA,EAC9B;AAGA,QAAM,sBAAsB,CAAC,kBAA0B;AACrD,UAAM,mBAAmB,aAAa,aAAa;AAEnD,WACE;AAAA,MAAC;AAAA;AAAA,QAEC,WAAU;AAAA,QACV,OAAO,EAAE,SAAS,gBAAgB,eAAe,SAAS;AAAA,QAE1D;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,oBAAoB;AAAA,YAC3B,eAAe,CAAC,UAAU,mBAAmB,eAAe,KAAK;AAAA,YAEjE;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAO;AAAA,oBACL,gBAAgB,KAAK,CAAC,MAAM,EAAE,OAAO,gBAAgB,GAAG,UACtD;AAAA,kBACJ;AAAA,kBAEA,8BAAC,eAAY,aAAY,yBAAkB;AAAA;AAAA,cAC7C;AAAA,cACA,oBAAC,iBACE,0BAAgB,IAAI,CAAC,WACpB;AAAA,gBAAC;AAAA;AAAA,kBAEC,OAAO,OAAO;AAAA,kBACd,OAAO,cAAc,OAAO,MAAM;AAAA,kBAClC,UAAQ;AAAA,kBAEP,wBAAc,OAAO,MAAM;AAAA;AAAA,gBALvB,OAAO;AAAA,cAMd,CACD,GACH;AAAA;AAAA;AAAA,QACF;AAAA;AAAA,MA7BK;AAAA,IA8BP;AAAA,EAEJ;AAGA,QAAM,oBAAoB,CAAC,kBAA0B;AACnD,UAAM,mBAAmB,aAAa,aAAa;AACnD,UAAM,qBAAqB,kBAAkB,gBAAgB;AAC7D,UAAM,YAAY,gBAAgB,aAAa;AAE/C,QAAI,CAAC,kBAAkB;AACrB,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,WAAU;AAAA,UACV,OAAO,EAAE,SAAS,gBAAgB,eAAe,SAAS;AAAA,UAE1D;AAAA,YAAC;AAAA;AAAA,cACC,SAAQ;AAAA,cACR,QAAO;AAAA,cACP,WAAW,oBAAC,eAAY;AAAA,cACxB,MAAK;AAAA,cACL,WAAU;AAAA,cACX;AAAA;AAAA,UAED;AAAA;AAAA,QAZK;AAAA,MAaP;AAAA,IAEJ;AAEA,WACE;AAAA,MAAC;AAAA;AAAA,QAEC,WAAU;AAAA,QACV,OAAO,EAAE,SAAS,gBAAgB,eAAe,SAAS;AAAA,QAE1D;AAAA,UAAC;AAAA;AAAA,YACC,SAAQ;AAAA,YACR,QAAQ,YAAY,YAAY;AAAA,YAChC,WAAW,YAAY,oBAAC,mBAAgB,IAAK,oBAAC,eAAY;AAAA,YAC1D,MAAK;AAAA,YACL,WAAU;AAAA,YAEV,8BAAC,UAAK,WAAU,iBAAiB,8BAAmB;AAAA;AAAA,QACtD;AAAA;AAAA,MAZK;AAAA,IAaP;AAAA,EAEJ;AAGA,QAAM,yBAAyB,CAAC,kBAA0B;AAExD,UAAM,oBAAoB,kBAAkB,aAAa;AAEzD,WACE,oBAAC,UAAK,WAAU,4EACb,6BACH;AAAA,EAEJ;AAGA,QAAM,wBAAwB,CAAC,MAAc,iBAA2B;AACtE,UAAM,WAA+D,CAAC;AACtE,QAAI,YAAY;AAChB,UAAM,SAAS,MAAM,SAAS;AAG9B,UAAM,QAAQ;AACd,QAAI;AAEJ,YAAQ,QAAQ,MAAM,KAAK,IAAI,OAAO,MAAM;AAC1C,YAAM,CAAC,WAAW,aAAa,IAAI;AACnC,YAAM,aAAa,MAAM;AAGzB,UAAI,aAAa,WAAW;AAC1B,iBAAS,KAAK;AAAA,UACZ,SAAS,KAAK,MAAM,WAAW,UAAU;AAAA,UACzC,IAAI,GAAG,MAAM,SAAS,OAAO,CAAC;AAAA,QAChC,CAAC;AAAA,MACH;AAGA,UAAI,cAAc;AAChB,iBAAS,KAAK;AAAA,UACZ,SAAS,uBAAuB,aAAa;AAAA,UAC7C,IAAI,GAAG,MAAM,eAAe,OAAO,CAAC;AAAA,QACtC,CAAC;AAAA,MACH,WAAW,qCAAiC;AAC1C,iBAAS,KAAK;AAAA,UACZ,SAAS,oBAAoB,aAAa;AAAA,UAC1C,IAAI,GAAG,MAAM,WAAW,OAAO,CAAC;AAAA,QAClC,CAAC;AAAA,MACH,OAAO;AACL,iBAAS,KAAK;AAAA,UACZ,SAAS,kBAAkB,aAAa;AAAA,UACxC,IAAI,GAAG,MAAM,WAAW,OAAO,CAAC;AAAA,QAClC,CAAC;AAAA,MACH;AAEA,kBAAY,MAAM,QAAQ,UAAU;AAAA,IACtC;AAGA,QAAI,YAAY,KAAK,QAAQ;AAC3B,eAAS,KAAK;AAAA,QACZ,SAAS,KAAK,MAAM,SAAS;AAAA,QAC7B,IAAI,GAAG,MAAM,SAAS,OAAO,CAAC;AAAA,MAChC,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAGA,QAAM,wBAAwB,CAC5B,aACA,iBACG;AAGH,UAAM,cAAc,cAAc,WAAW;AAC7C,WAAO,sBAAsB,aAAa,YAAY;AAAA,EACxD;AAEA,MAAI,CAAC,mBAAmB,CAAC,mBAAmB;AAC1C,WACE,qBAAAA,WAAA,EACE;AAAA,0BAAC,gBAAa,UAAS,iBAAgB;AAAA,MACvC,oBAAC,iBAAc,WAAU,eACvB,8BAAC,SAAI,WAAU,yBACb;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,OAAM;AAAA,UACN,QAAO;AAAA,UACP,WAAW,GAAG,aAAa;AAAA,UAC5B;AAAA;AAAA,MAED,GACF,GACF;AAAA,OACF;AAAA,EAEJ;AAEA,SACE,qBAAAA,WAAA,EACE;AAAA,wBAAC,gBAAa,UAAS,uBAAsB;AAAA,IAE7C;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,GAAG,IAAI,qCAAkC,aAAa;AAAA,QAEjE,8BAAC,SAAI,WAAU,QACb;AAAA,UAAC;AAAA;AAAA,YACC,IAAG;AAAA,YACH,MAAK;AAAA,YACL,OAAM;AAAA,YACN,QAAO;AAAA,YACP,WAAU;AAAA,YAET,gCAAsB,iBAAiB,EAAE,IAAI,CAAC,YAC7C,oBAAC,YAA2B,kBAAQ,WAArB,QAAQ,EAAqB,CAC7C;AAAA;AAAA,QACH,GACF;AAAA;AAAA,IACF;AAAA,IAEC,qCACC,qBAAAA,WAAA,EACE;AAAA,0BAAC,gBAAa,UAAS,oBAAmB;AAAA,MAE1C,oBAAC,iBAAc,WAAW,GAAG,IAAI,aAAa,GAC5C,8BAAC,SAAI,WAAU,QACb;AAAA,QAAC;AAAA;AAAA,UACC,IAAG;AAAA,UACH,MAAK;AAAA,UACL,OAAM;AAAA,UACN,QAAO;AAAA,UACP,WAAU;AAAA,UAET,gCAAsB,mBAAmB,IAAI,EAAE;AAAA,YAC9C,CAAC,YACC,oBAAC,YAA2B,kBAAQ,WAArB,QAAQ,EAAqB;AAAA,UAEhD;AAAA;AAAA,MACF,GACF,GACF;AAAA,OACF;AAAA,KAEJ;AAEJ;AAEA,IAAM,oBAAoB,CAAC,EAAE,cAAc,MAA4B;AACrE,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,aAAa;AAEjB,QAAM,kBAAkB,mBAAmB;AAC3C,QAAM,gBAAgB,iBAAiB;AACvC,QAAM,wBAAwB;AAAA,IAC5B,iBAAiB,MAAM;AAAA,EACzB;AAGA,QAAM,WAAW,iBAAiB,qBAAqB;AAGvD,QAAM,0BAA0B,QAAQ,MAAM;AAC5C,QAAI,CAAC,iBAAiB,WAAW,gBAAgB,QAAQ,WAAW,GAAG;AACrE,aAAO,EAAE,GAAG,KAAK,GAAG,IAAI;AAAA,IAC1B;AACA,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,gBAAgB,QAAQ,CAAC,EAAE,MAAM;AAC3D,UAAI,OAAO,OAAO,MAAM,YAAY,OAAO,OAAO,MAAM,UAAU;AAEhE,eAAO,EAAE,GAAG,OAAO,IAAI,KAAK,GAAG,OAAO,IAAI,IAAI;AAAA,MAChD;AAAA,IACF,QAAQ;AAAA,IAER;AACA,WAAO,EAAE,GAAG,KAAK,GAAG,IAAI;AAAA,EAC1B,GAAG,CAAC,iBAAiB,OAAO,CAAC;AAG7B,QAAM,iCAAiC,MAAc;AAGnD,UAAM,sBAAsB;AAC5B,UAAM,uBAAuB;AAG7B,UAAM,iBAAiB,sBAAsB,wBAAwB;AAGrE,UAAM,YAAY;AAElB,WAAO,gBAAgB;AAAA,EACzB;AAEA,QAAM,wBAAwB,+BAA+B;AAG7D,QAAM,mBAAmB,QAAQ,MAAM;AACrC,QAAI,qCAAkC,uBAAuB,QAAQ;AACnE,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,sBAAsB,MAAM;AACtD,YAAI,OAAO,OAAO,MAAM,YAAY,OAAO,OAAO,MAAM,UAAU;AAChE,iBAAO,EAAE,GAAG,OAAO,IAAI,KAAK,GAAG,OAAO,IAAI,IAAI;AAAA,QAChD;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF,WAAW,eAAe,QAAQ;AAChC,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,cAAc,MAAM;AAC9C,YAAI,OAAO,OAAO,MAAM,YAAY,OAAO,OAAO,MAAM,UAAU;AAChE,iBAAO,EAAE,GAAG,OAAO,IAAI,KAAK,GAAG,OAAO,IAAI,IAAI;AAAA,QAChD;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AACA,WAAO;AAAA,EACT,GAAG,CAAC,SAAS,uBAAuB,QAAQ,eAAe,MAAM,CAAC;AAElE,QAAM,CAAC,uBAAuB,wBAAwB,IAAI,SAGhD,gBAAgB;AAG1B,YAAU,MAAM;AACd,6BAAyB,gBAAgB;AAAA,EAC3C,GAAG,CAAC,gBAAgB,CAAC;AAGrB,QAAM,+BAA+B,CACnC,GACA,GACA,SAC6B;AAE7B,UAAM,YAAY,KAAK,IAAI,KAAK,OAAO,IAAK;AAC5C,UAAM,aAAa,KAAK,IAAI,KAAK,QAAQ,IAAK;AAG9C,UAAM,YAAY,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,IAAI,SAAS,CAAC;AACxD,UAAM,YAAY,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,IAAI,UAAU,CAAC;AAEzD,WAAO,EAAE,GAAG,WAAW,GAAG,UAAU;AAAA,EACtC;AAEA,QAAM,mBAAmB,CAAC,UAAyC;AACjE,QAAI,kCAAgC;AAEpC,UAAM,OAAO,MAAM,cAAc,sBAAsB;AACvD,UAAM,IAAI,MAAM,UAAU,KAAK;AAC/B,UAAM,IAAI,MAAM,UAAU,KAAK;AAG/B,UAAM,mBAAmB,6BAA6B,GAAG,GAAG,IAAI;AAChE,6BAAyB,gBAAgB;AAGzC,QAAI,iBAAiB;AACnB,YAAM,aAAa,KAAK,UAAU;AAAA,QAChC,GAAG,KAAK,MAAM,iBAAiB,IAAI,GAAG;AAAA,QACtC,GAAG,KAAK,MAAM,iBAAiB,IAAI,GAAG;AAAA,MACxC,CAAC;AACD,+BAAyB,gBAAgB,IAAI,UAAU;AAAA,IACzD;AAAA,EACF;AAEA,QAAM,yBAAyB,MAAM;AACnC,QAAI,kCAAgC;AAEpC,UAAM,iBAAiB,EAAE,GAAG,KAAK,GAAG,IAAI;AACxC,6BAAyB,cAAc;AAGvC,QAAI,iBAAiB;AACnB,YAAM,aAAa,KAAK,UAAU;AAAA,QAChC,GAAG,KAAK,MAAM,eAAe,IAAI,GAAG;AAAA,QACpC,GAAG,KAAK,MAAM,eAAe,IAAI,GAAG;AAAA,MACtC,CAAC;AACD,+BAAyB,gBAAgB,IAAI,UAAU;AAAA,IACzD;AAAA,EACF;AAEA,QAAM,YAAY,MAAM;AACtB,QAAI,CAAC,sBAAuB,QAAO;AAEnC,UAAM,WAAW,KAAK;AAAA,MACpB,KAAK,IAAI,sBAAsB,IAAI,wBAAwB,GAAG,CAAC,IAC7D,KAAK,IAAI,sBAAsB,IAAI,wBAAwB,GAAG,CAAC;AAAA,IACnE;AAEA,WAAO,YAAY;AAAA,EACrB;AAEA,QAAM,4BAA4B,MAAM;AACtC,QAAI,qCAAiC;AACnC,aAAO;AAAA,IACT;AAEA,QAAI,mCAAgC;AAClC,aAAO,UAAU,IACb,mCACA;AAAA,IACN;AAEA,WAAO;AAAA,EACT;AAEA,SACE,qBAAAA,WAAA,EACE;AAAA,wBAAC,gBAAa,UAAS,6BAAyB;AAAA,IAEhD,oBAAC,iBAAc,WAAW,GAAG,IAAI,aAAa,GAC5C;AAAA,MAAC;AAAA;AAAA,QACC,eAAY;AAAA,QACZ,WAAU;AAAA,QAET;AAAA,qBAAW,YACV;AAAA,YAAC;AAAA;AAAA,cACC,eAAY;AAAA,cACZ,WAAU;AAAA,cAEV;AAAA,qCAAC,SAAI,WAAU,2BACb;AAAA,sCAAC,SAAI,WAAU,wEAAuE;AAAA,kBACtF,oBAAC,UAAK,WAAU,qCAAoC,6BAEpD;AAAA,mBACF;AAAA,gBACA,qBAAC,SAAI,WAAU,2BACb;AAAA,sCAAC,SAAI,WAAU,8DAA6D;AAAA,kBAC5E,oBAAC,UAAK,WAAU,qCAAoC,8BAEpD;AAAA,mBACF;AAAA,gBACA,qBAAC,SAAI,WAAU,2BACb;AAAA,sCAAC,SAAI,WAAU,kEAAiE;AAAA,kBAChF,oBAAC,UAAK,WAAU,qCAAoC,gCAEpD;AAAA,mBACF;AAAA;AAAA;AAAA,UACF;AAAA,UAGF;AAAA,YAAC;AAAA;AAAA,cACC,eAAY;AAAA,cACZ,MAAK;AAAA,cACL,WAAU;AAAA,cACV,SAAS;AAAA,cACT,WAAW,CAAC,MAAM;AAChB,oBAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,oBAAE,eAAe;AACjB,yCAAuB;AAAA,gBACzB;AAAA,cACF;AAAA,cACA,cAAW;AAAA,cAEX;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,eAAY;AAAA,oBACZ,KAAK,YAAY;AAAA,oBACjB,KAAI;AAAA,oBACJ,WAAU;AAAA;AAAA,gBACZ;AAAA,gBAGC,qCACC;AAAA,kBAAC;AAAA;AAAA,oBACC,eAAY;AAAA,oBACZ,WAAU;AAAA,oBACV,OAAO;AAAA,sBACL,UAAU;AAAA,sBACV,UAAU;AAAA,sBACV,OAAO;AAAA,sBACP,aAAa;AAAA,sBACb,MAAM,QAAQ,wBAAwB,IAAI,GAAG;AAAA,sBAC7C,KAAK,QAAQ,wBAAwB,IAAI,GAAG;AAAA,oBAC9C;AAAA;AAAA,gBACF;AAAA,gBAID,yBACC;AAAA,kBAAC;AAAA;AAAA,oBACC,eAAY;AAAA,oBACZ,WAAW,sDAAsD,0BAA0B,CAAC;AAAA,oBAC5F,OAAO;AAAA,sBACL,UAAU;AAAA,sBACV,UAAU;AAAA,sBACV,OAAO;AAAA,sBACP,aAAa;AAAA,sBACb,MAAM,QAAQ,sBAAsB,IAAI,GAAG;AAAA,sBAC3C,KAAK,QAAQ,sBAAsB,IAAI,GAAG;AAAA,oBAC5C;AAAA;AAAA,gBACF;AAAA;AAAA;AAAA,UAEJ;AAAA;AAAA;AAAA,IACF,GACF;AAAA,KACF;AAEJ;","names":["Fragment"]}