<template>
  <div class="document-compare-page" @click="onPageClick">
    <intelligence-left-tab-bar />

    <div class="compare-main">
      <header class="page-header">
        <div class="page-header-left">
          <img class="header-file-icon" src="./icons/file-type-icon.png" alt="" />
          <span class="page-header-file-name">{{ displayFileName }}</span>
        </div>

        <div v-if="isCompareLoading" class="page-header-status">
          <span class="status-loading-dot" />
          <span class="page-header-status-title">文档解析中</span>
          <span class="page-header-status-text">已完成...{{ translationProgress }}%，已用时{{ elapsedSeconds }}秒</span>
        </div>

        <div v-else class="page-header-action-group" @click.stop>
          <button
            v-for="action in headerActions"
            :key="action.key"
            type="button"
            class="header-action-btn"
            :class="action.variant === 'primary' ? 'header-action-btn--primary' : ''"
            @click="onHeaderAction(action.key)"
          >
            {{ action.label }}
          </button>
        </div>
      </header>

      <div class="compare-body">
        <div v-if="isCompareLoading" class="compare-loading-placeholder">
          <img class="compare-loading-placeholder-img" :src="comparePlaceholderUrl" alt="" />
          <div class="compare-loading-placeholder-text">{{ compareLoadingText }}</div>
        </div>

        <template v-else>
          <div class="compare-content">
            <aside class="article-nav-tree">
              <div class="tree-title">导航</div>
              <el-tree
                ref="articleTreeRef"
                :data="articleTree"
                node-key="id"
                :props="treeProps"
                :current-node-key="currentNodeKey"
                highlight-current
                default-expand-all
                @node-click="onClickTreeNode"
              />
            </aside>

            <div ref="compareScrollRef" class="sync-compare-scroll" @scroll="onSyncScroll">
              <section
                v-for="page in pageBlocks"
                :key="page.pageId"
                :id="page.pageId"
                class="page-block"
                :class="{ 'page-block--active': currentPageId === page.pageId }"
              >
                <div class="page-block__body" :class="{ 'page-block__body--absolute': page.pageLayoutMode === 'absolute' }">
                  <template v-if="page.pageLayoutMode === 'absolute'">
                    <div class="page-column">
                      <div class="page-canvas-wrapper">
                        <div class="page-canvas">
                          <article
                            v-for="item in page.items"
                            :key="`${page.pageId}-${item.id}-en`"
                            class="page-node page-node--en"
                            :class="[getBlockVariantClass(item.blockType), shouldCenterBlock(item) ? 'page-node--center' : '', ENABLE_DEBUG_BOX ? 'page-node--debug' : '']"
                            :style="getBlockStyle(item)"
                            :data-section-id="item.id"
                          >
                            <div class="page-node__content">
                              <div v-if="item.blockType === 'table' && item.tableHtml" class="page-item__html" v-html="item.tableHtml"></div>
                              <img
                                v-else-if="item.blockType === 'image'"
                                class="page-item__image"
                                :src="getEnglishImageSrc(item)"
                                alt=""
                                @error="onEnglishImageError(item)"
                              />
                              <div v-else class="page-item__content" v-html="renderBlockHtml(item.text, item.styleSpans)"></div>
                            </div>
                            <span v-if="ENABLE_DEBUG_BOX" class="page-node__debug-label">{{ getBlockTypeLabel(item.blockType) }}</span>
                          </article>
                        </div>
                      </div>
                    </div>

                    <div class="page-column">
                      <div class="page-canvas-wrapper">
                        <div class="page-canvas">
                          <slot name="zh-page-canvas" :page="page"></slot>
                        </div>
                      </div>
                    </div>
                  </template>

                  <template v-else>
                    <article
                      v-for="item in page.items"
                      :key="`${page.pageId}-${item.id}`"
                      class="page-item"
                      :data-section-id="item.id"
                    >
                      <div class="page-item__text page-item__text--en" :class="[getBlockVariantClass(item.blockType), shouldCenterBlock(item) ? 'page-item__text--center' : '']">
                        <div v-if="item.blockType === 'table' && item.tableHtml" class="page-item__html" v-html="item.tableHtml"></div>
                        <img
                          v-else-if="item.blockType === 'image'"
                          class="page-item__image"
                          :src="getEnglishImageSrc(item)"
                          alt=""
                          @error="onEnglishImageError(item)"
                        />
                        <div v-else class="page-item__content" v-html="renderBlockHtml(item.text, item.styleSpans)"></div>
                      </div>
                      <div class="page-item__text page-item__text--zh" :class="[getBlockVariantClass(item.blockType), shouldCenterBlock(item) ? 'page-item__text--center' : '']">
                        <slot name="zh-flow-item" :item="item" :page="page"></slot>
                      </div>
                    </article>
                  </template>
                </div>
              </section>
            </div>
          </div>
        </template>
      </div>
    </div>
  </div>
</template>

<script setup>
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { useRoute } from 'vue-router'
import IntelligenceLeftTabBar from '@/components/intelligenceLeftTabBar/index.vue'
import comparePlaceholderUrl from './icons/container-1885-placeholder.png'
import mergedAns from './merged_ans.json'

const route = useRoute()
const ENABLE_ABSOLUTE_LAYOUT = true
const ENABLE_DEBUG_BOX = false
const PAGE_BBOX_VALID_THRESHOLD = 0.7

const ESTIMATED_SECONDS = 65
const headerActions = [
  { key: 'submit-review', label: '提交审核' },
  { key: 'preview', label: '预览' },
  { key: 'export', label: '导出' },
  { key: 'write-report', label: '写报' },
  { key: 'save', label: '保存', variant: 'primary' }
]

const normalizedPages = ref([])
const normalizedBlocks = ref([])
const articleTree = ref([])
const articleTreeRef = ref(null)
const compareScrollRef = ref(null)
const currentNodeKey = ref('')
const currentPageId = ref('')
const isCompareLoading = ref(true)
const elapsedSeconds = ref(0)
const translationProgress = ref(0)
const timerId = ref(null)
const imageLoadErrorMap = ref({})
const treeProps = { label: 'title', children: 'children' }

const displayFileName = computed(() => {
  const fileName = route.query.fileName
  return typeof fileName === 'string' && fileName ? fileName : '未命名文档（占位）'
})
const compareLoadingText = computed(() => `文档解析中，预计用时${ESTIMATED_SECONDS}秒，已用时${elapsedSeconds.value}秒...`)

const pageBlocks = computed(() => {
  return normalizedPages.value.map((page) => {
    const pageItems = normalizedBlocks.value
      .filter((block) => block.pageIdx === page.pageIdx)
      .sort((a, b) => a.readingOrder - b.readingOrder)
    const absoluteCount = pageItems.filter((item) => item.layoutMode === 'absolute').length
    const hitRate = pageItems.length ? absoluteCount / pageItems.length : 0
    const pageLayoutMode = ENABLE_ABSOLUTE_LAYOUT && pageItems.length > 0 && hitRate >= PAGE_BBOX_VALID_THRESHOLD ? 'absolute' : 'flow'
    return {
      pageId: `page-${page.pageIdx}`,
      pageLayoutMode,
      items: pageItems
    }
  })
})

function shouldCenterBlock(block) {
  if (!block) return false
  if (block.blockType !== 'heading') return false
  const text = String(block.text || '').trim()
  if (!text) return false
  const strongHeading = block.headingLevel != null
  const chapterLike = /^(I|II|III|IV|V|VI|VII|VIII|IX|X|XI|XII)[\.|、\s]/i.test(text)
  const alphaHeading = /^[A-Z][a-zA-Z\s/&-]{3,}$/.test(text) && !/^[A-Z]{1,3}\b/.test(text)
  const chineseHeading = /^[一二三四五六七八九十]+[、.]/.test(text)
  const notNumericList = !/^\d+[\.|、]/.test(text)
  return strongHeading || (notNumericList && (chapterLike || alphaHeading || chineseHeading))
}

function mapSemanticTypeToNodeType(semanticType, contentPayload = {}) {
  if (semanticType === 'heading' || contentPayload.heading_level != null) return 'heading'
  if (semanticType === 'paragraph') return 'paragraph'
  if (semanticType === 'table' || contentPayload.type === 'table') return 'table'
  if (semanticType === 'page_number') return 'page_number'
  if (semanticType === 'image' || contentPayload.preview_img_path) return 'image'
  return 'unknown'
}

function getBlockTypeLabel(type) {
  const labelMap = { heading: '标题', paragraph: '正文', table: '表格', image: '图片', page_number: '页码', unknown: '未知' }
  return labelMap[type] || '未知'
}

function getBlockVariantClass(type) {
  return `document-block--${type || 'unknown'}`
}

function isValidBboxNorm(rawBboxNorm) {
  if (!Array.isArray(rawBboxNorm) || rawBboxNorm.length !== 4) return false
  const [l, t, r, b] = rawBboxNorm.map((value) => Number(value))
  if (![l, t, r, b].every((value) => Number.isFinite(value))) return false
  if (l < 0 || t < 0 || r > 1 || b > 1) return false
  if (r <= l || b <= t) return false
  return true
}

function normalizeBboxFromPixel(rawBbox, pageMeta) {
  if (!Array.isArray(rawBbox) || rawBbox.length !== 4) return []
  const pageWidth = Number(pageMeta?.width || 0)
  const pageHeight = Number(pageMeta?.height || 0)
  if (pageWidth <= 0 || pageHeight <= 0) return []
  const [l, t, r, b] = rawBbox.map((value) => Number(value))
  if (![l, t, r, b].every((value) => Number.isFinite(value))) return []
  return [l / pageWidth, t / pageHeight, r / pageWidth, b / pageHeight]
}

function getBlockStyle(item) {
  if (!isValidBboxNorm(item?.bboxNorm)) return {}
  const [l, t, r, b] = item.bboxNorm
  const baseHeightPercent = (b - t) * 100
  return {
    left: `${l * 100}%`,
    top: `${t * 100}%`,
    width: `${(r - l) * 100}%`,
    height: `${Math.min(100 - t * 100, baseHeightPercent)}%`,
    position: 'absolute',
    overflow: 'hidden'
  }
}

function escapeHtml(text = '') {
  return String(text)
    .replaceAll('&', '&amp;')
    .replaceAll('<', '&lt;')
    .replaceAll('>', '&gt;')
    .replaceAll('"', '&quot;')
    .replaceAll("'", '&#39;')
}

function renderBlockHtml(text = '', styleSpans = []) {
  const safeText = escapeHtml(text)
  if (!Array.isArray(styleSpans) || styleSpans.length === 0) return safeText.replaceAll('\n', '<br />')

  const sorted = [...styleSpans].sort((a, b) => a.start - b.start)
  let html = ''
  let cursor = 0

  sorted.forEach((span) => {
    const start = Math.max(0, span.start || 0)
    const end = Math.max(start, span.end || start)
    if (start > cursor) html += escapeHtml(text.slice(cursor, start))
    const spanText = escapeHtml(text.slice(start, end))
    const style = span?.style || {}
    const inlineStyle = [
      style.bold ? 'font-weight:700' : '',
      style.italic ? 'font-style:italic' : '',
      style.underline ? 'text-decoration:underline' : '',
      style.color_hex ? `color:${style.color_hex}` : ''
    ].filter(Boolean).join(';')
    html += `<span style="${inlineStyle}">${spanText}</span>`
    cursor = end
  })

  if (cursor < text.length) html += escapeHtml(text.slice(cursor))
  return html.replaceAll('\n', '<br />')
}

function resolveImageUrl(rawPath) {
  const path = String(rawPath || '').trim()
  if (!path) return ''
  if (/^(https?:)?\/\//i.test(path) || /^(data|blob):/i.test(path)) return path
  const normalizedPath = path.replaceAll('\\', '/')
  const baseUrl = String(
    import.meta.env.VITE_INTELLIGENT_TRANSLATION_ASSET_BASE_URL || import.meta.env.VITE_BASE_FILE_URL || ''
  ).trim()
  if (baseUrl) {
    return `${baseUrl.replace(/\/+$/, '')}/${normalizedPath.replace(/^\/+/, '')}`
  }
  return normalizedPath.startsWith('/') ? normalizedPath : `/${normalizedPath}`
}

function getEnglishImageSrc(item) {
  if (!item?.id) return comparePlaceholderUrl
  if (imageLoadErrorMap.value[item.id]) return comparePlaceholderUrl
  const resolvedUrl = resolveImageUrl(item.imagePath)
  return resolvedUrl || comparePlaceholderUrl
}

function onEnglishImageError(item) {
  if (!item?.id) return
  imageLoadErrorMap.value = {
    ...imageLoadErrorMap.value,
    [item.id]: true
  }
}

function buildNormalizedBlocks(rawData) {
  const pages = Array.isArray(rawData?.data?.pages) ? rawData.data.pages : []
  const nodes = Array.isArray(rawData?.data?.merged_nodes) ? rawData.data.merged_nodes : []
  const pageSizeMap = pages.reduce((acc, page) => {
    acc[page.page_idx] = { width: page.width, height: page.height }
    return acc
  }, {})

  normalizedPages.value = pages.map((page) => ({
    pageIdx: page.page_idx,
    width: page.width,
    height: page.height,
    rotation: page.rotation,
    nodeIds: Array.isArray(page.node_ids) ? page.node_ids : []
  }))

  normalizedBlocks.value = nodes.map((node, index) => {
    const contentPayload = node?.content_payload || {}
    const blockType = mapSemanticTypeToNodeType(node.semantic_type, contentPayload)
    const bbox = Array.isArray(node?.layout?.bbox) ? node.layout.bbox : []
    const originBboxNorm = Array.isArray(node?.layout?.bbox_norm) ? node.layout.bbox_norm : []
    const pageMeta = pageSizeMap[node.page_idx] || null
    const convertedBboxNorm = normalizeBboxFromPixel(bbox, pageMeta)
    const bboxNorm = isValidBboxNorm(originBboxNorm) ? originBboxNorm : (isValidBboxNorm(convertedBboxNorm) ? convertedBboxNorm : [])
    const layoutMode = isValidBboxNorm(bboxNorm) ? 'absolute' : 'flow'
    return {
      id: node.node_id || `node_${index}`,
      nodeId: node.node_id || '',
      pageIdx: node.page_idx ?? null,
      type: blockType,
      blockType,
      semanticType: node.semantic_type || 'unknown',
      readingOrder: node?.layout?.reading_order ?? index,
      title: contentPayload.text || node.node_id || `未命名块${index + 1}`,
      text: contentPayload.text || '',
      translatedText: '',
      html: contentPayload.html || '',
      headingLevel: contentPayload.heading_level ?? null,
      tableHtml: contentPayload.table_body_html || '',
      translatedTableHtml: contentPayload.table_body_html || '',
      imagePath: contentPayload.img_path || contentPayload.preview_img_path || '',
      previewImgPath: contentPayload.preview_img_path || '',
      bbox,
      bboxNorm,
      layoutMode,
      layout: {
        bbox,
        bboxNorm,
        angle: node?.layout?.angle ?? 0,
        link: node?.layout?.link ?? null,
        zIndex: node?.layout?.z_index ?? null
      },
      styleSpans: Array.isArray(node.style_spans) ? node.style_spans : []
    }
  })
}

function buildNavigationTree(rawData) {
  const nodes = Array.isArray(rawData?.data?.merged_nodes) ? rawData.data.merged_nodes : []
  articleTree.value = nodes
    .map((node, index) => {
      const contentPayload = node?.content_payload || {}
      const nodeType = mapSemanticTypeToNodeType(node.semantic_type, contentPayload)
      const text = contentPayload.text || node.node_id || '未命名块'
      if (nodeType !== 'heading') return null
      if (!shouldCenterBlock({ ...node, blockType: nodeType, headingLevel: contentPayload.heading_level, text })) return null
      return {
        id: node.node_id || `heading_${index}`,
        title: text,
        pageIdx: node.page_idx ?? 0,
        nodeType,
        sectionId: node.node_id || `heading_${index}`,
        children: []
      }
    })
    .filter(Boolean)
}

function findBlockElementById(blockId) {
  return document.querySelector(`[data-section-id='${blockId}']`)
}

async function onClickTreeNode(nodeData) {
  currentNodeKey.value = nodeData.id
  const targetPage = pageBlocks.value.find((page) => page.items.some((item) => item.id === nodeData.id))
  currentPageId.value = targetPage?.pageId || currentPageId.value
  await nextTick()
  findBlockElementById(nodeData.id)?.scrollIntoView({ behavior: 'smooth', block: 'center' })
}

function onSyncScroll() {
  const scroller = compareScrollRef.value
  if (!scroller) return
  const pageEls = Array.from(scroller.querySelectorAll('.page-block'))
  const viewportTop = scroller.getBoundingClientRect().top
  let activePage = pageBlocks.value[0]?.pageId || ''

  for (const pageEl of pageEls) {
    const rect = pageEl.getBoundingClientRect()
    if (rect.top - viewportTop <= 96) activePage = pageEl.id
  }

  currentPageId.value = activePage
  const activePageBlocks = pageBlocks.value.find((page) => page.pageId === activePage)?.items || []
  const activeHeading = articleTree.value.find((item) => activePageBlocks.some((block) => block.id === item.id))
  if (activeHeading) currentNodeKey.value = activeHeading.id
}

function onPageClick() {
  currentNodeKey.value = currentPageId.value || currentNodeKey.value
}

function onHeaderAction(actionKey) {
  ElMessage.info(`顶部功能按钮占位：${actionKey}`)
}

function getFirstNavigableNode(nodes) {
  if (!Array.isArray(nodes)) return null
  return nodes.find((node) => node?.id) || null
}

onMounted(() => {
  const requestStartTime = Date.now()
  const updateElapsedSeconds = () => {
    elapsedSeconds.value = Math.floor((Date.now() - requestStartTime) / 1000)
  }

  updateElapsedSeconds()
  timerId.value = window.setInterval(updateElapsedSeconds, 1000)

  try {
    buildNormalizedBlocks(mergedAns)
    buildNavigationTree(mergedAns)
    translationProgress.value = Number(mergedAns?.data?.pages?.length ? 100 : 0)
    const firstNode = getFirstNavigableNode(articleTree.value)
    if (firstNode) {
      currentNodeKey.value = firstNode.id
      currentPageId.value = `page-${firstNode.pageIdx ?? 0}`
    }
  } catch (error) {
    ElMessage.error(error?.message || '本地 JSON 加载失败')
  } finally {
    isCompareLoading.value = false
  }
})

onUnmounted(() => {
  if (timerId.value !== null) {
    clearInterval(timerId.value)
    timerId.value = null
  }
})
</script>

<style scoped lang="scss">
.document-compare-page {
  display: flex;
  height: calc(100vh - 64px);
  min-height: calc(100vh - 64px);
  overflow: hidden;
  background: #fff;
}

.compare-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  position: relative;
}

.page-header {
  box-sizing: border-box;
  flex-shrink: 0;
  width: 100%;
  height: 64px;
  padding: 0 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  background: var(--bg-white-100);
  box-shadow: 0 0 20px 0 rgba(25, 69, 130, 0.1);
  border-bottom: 1px solid var(--bg-black-5);
}

.compare-body {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding: 8px;
  background: var(--color-primary-2);
  box-sizing: border-box;
}

.page-header-left { display: flex; align-items: center; gap: 8px; min-width: 0; }
.header-file-icon { width: 24px; height: 24px; flex-shrink: 0; display: block; }
.page-header-file-name { font-family: 'Source Han Sans CN', sans-serif; font-size: 18px; font-weight: 400; line-height: 26px; color: var(--text-primary-80-color, #344054); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.page-header-status { display: inline-flex; align-items: center; height: 38px; padding: 0 12px; border: 1px solid var(--color-primary-35); border-radius: 50px; background: var(--color-primary-10); gap: 12px; flex-shrink: 0; box-sizing: border-box; }
.status-loading-dot { width: 14px; height: 14px; border: 2px solid var(--color-primary-35); border-top-color: var(--color-primary-100, #2563eb); border-radius: 50%; animation: compare-spin 0.8s linear infinite; }
.page-header-status-title, .page-header-status-text { font-family: 'Source Han Sans CN', sans-serif; font-size: 14px; line-height: 22px; color: var(--color-primary-100); }
.page-header-status-title { font-weight: 700; }
.page-header-status-text { font-weight: 400; }
.page-header-action-group { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.header-action-btn { box-sizing: border-box; padding: 6px 19px; border: 1px solid var(--bg-black-10); border-radius: 6px; background: #fff; font-family: 'Source Han Sans CN', sans-serif; font-weight: 400; font-size: 16px; line-height: 24px; color: var(--text-primary-80-color, #344054); cursor: pointer; }
.header-action-btn--primary { background: var(--color-primary-100); border: none; color: var(--bg-white-100); }

@keyframes compare-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.compare-loading-placeholder { flex: 1; min-height: 560px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; padding: 16px; box-sizing: border-box; background: var(--bg-white-100); border-radius: 8px; }
.compare-loading-placeholder-img { max-width: 100%; max-height: min(720px, calc(100vh - 160px)); width: auto; height: auto; object-fit: contain; display: block; }
.compare-loading-placeholder-text { font-family: 'Source Han Sans CN', sans-serif; font-weight: 400; font-size: 16px; line-height: 30px; color: #344054; }
.compare-content { flex: 1; min-height: 0; display: flex; gap: 12px; overflow: hidden; }
.article-nav-tree { width: 280px; flex-shrink: 0; padding: 16px 19px; display: flex; flex-direction: column; min-height: 0; overflow: hidden; border: 1px solid #e8ecf2; border-radius: 8px; background: #fff; }
.tree-title { font-family: 'Source Han Sans CN', sans-serif; font-weight: 700; font-size: 16px; line-height: 24px; letter-spacing: 1px; color: var(--text-primary-80-color); margin-bottom: 17px; }
:deep(.article-nav-tree .el-tree-node__label) { font-family: 'Source Han Sans CN', sans-serif; font-weight: 400; font-size: 14px; line-height: 22px; color: var(--text-primary-80-color); }
.sync-compare-scroll { flex: 1; min-width: 0; min-height: 0; overflow-y: auto; overflow-x: hidden; border: 1px solid #e8ecf2; border-radius: 8px; background: #fff; padding: 16px; box-sizing: border-box; }
.page-block { display: flex; flex-direction: column; gap: 12px; padding: 12px 0 20px; border-bottom: 1px solid #d9e2ec; }
.page-block--active { background: #f8fafc; }
.page-block__body { display: flex; flex-direction: column; gap: 12px; }
.page-block__body--absolute { flex-direction: row; align-items: flex-start; }
.page-column { width: calc(50% - 6px); min-width: 0; }
.page-canvas-wrapper { width: 100%; }
.page-canvas { position: relative; width: 100%; aspect-ratio: 21 / 29.7; border: 1px solid #e4e7ec; border-radius: 8px; overflow: hidden; background: #fff; }
.page-node { position: absolute; box-sizing: border-box; padding: 0; }
.page-node--en { border-right: 1px solid #eef2f7; }
.page-node__content { width: 100%; height: 100%; overflow: hidden; padding: 1px 2px 4px; box-sizing: border-box; }
.page-node--center .page-item__content { text-align: center; }
.page-node--debug { border: 1px dashed #1677ff; }
.page-node__debug-label { position: absolute; left: 0; top: 0; font-size: 10px; line-height: 14px; padding: 0 4px; color: #fff; background: rgba(22, 119, 255, 0.8); }
.page-item { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; align-items: stretch; }
.page-item__text { min-height: 72px; padding: 0; background: transparent; border: none; }
.page-item__text--en { border-right: 1px solid #eef2f7; padding-right: 12px; }
.page-item__text--zh { padding-left: 12px; }
.page-item__text--center .page-item__content { text-align: center; }
.page-item__content { font-size: 14px; line-height: 1.85; color: #344054; white-space: pre-wrap; word-break: break-word; }
.page-item__html :deep(table) { width: 100%; border-collapse: collapse; font-size: 13px; }
.page-item__html :deep(td), .page-item__html :deep(th) { border: 1px solid #d0d5dd; padding: 8px; vertical-align: top; }
.page-item__image { width: 100%; height: 100%; object-fit: contain; display: block; border-radius: 6px; }
.page-item--heading .page-item__content { font-size: 18px; font-weight: 700; color: #101828; }
.page-item--paragraph .page-item__content { font-size: 14px; }
.page-item--table .page-item__content { font-size: 13px; }
.page-item--image .page-item__content { font-size: 13px; color: #667085; }
.page-item--page_number .page-item__content { font-size: 12px; color: #98a2b3; }
.page-item--unknown .page-item__content { color: #667085; font-style: italic; }
.page-node--en.document-block--heading .page-item__content,
.page-node--en.document-block--paragraph .page-item__content {
  line-height: 1.9;
  padding-bottom: 3px;
}
.page-node--en.document-block--table .page-item__content,
.page-node--en.document-block--page_number .page-item__content {
  line-height: 1.9;
  padding-bottom: 3px;
}

@media (max-width: 1360px) {
  .page-block__body { gap: 10px; }
  .page-block__body--absolute { flex-direction: column; }
  .page-column { width: 100%; }
}
</style>
