<template>
  <div class="mark-body" @scroll="viewScroll">
    <div ref="dragContainer" class="mark-body-container">
      <div v-if="!store.currentTask" class="mark-body-none">
        <div>
          <img src="@/assets/image-none-task.png" />
          <p>
            {{ store.message }}
          </p>
        </div>
      </div>
      <div v-else-if="store.isScanImage" :style="{ width: answerPaperScale }">
        <div
          v-for="(item, index) in sliceImagesWithTrackList"
          :key="index"
          class="single-image-container"
        >
          <img :src="item.url" draggable="false" />
          <MarkDrawTrack
            :trackList="item.trackList"
            :specialTagList="item.tagList"
            :sliceImageHeight="item.originalImageHeight"
            :sliceImageWidth="item.originalImageWidth"
            :dx="0"
            :dy="0"
          />
          <!-- 客观题答案标记 -->
          <template v-if="item.answerTags">
            <div
              v-for="(tag, tindex) in item.answerTags"
              :key="`tag-${tindex}`"
              :style="tag.style"
            >
              {{ tag.answer }}
            </div>
          </template>
          <!-- 试题评分明细 -->
          <template v-if="item.markDetail">
            <div
              v-for="(minfo, mindex) in item.markDetail"
              :key="`mark-${mindex}`"
              :style="minfo.style"
              class="mark-info"
            >
              <div v-if="minfo.isFillQuestion">
                <div
                  v-for="user in minfo.users"
                  :key="user.userId"
                  :style="{ color: user.color }"
                >
                  <p>{{ user.prename }}：{{ user.userName }}，评分：</p>
                  <p>
                    {{
                      user.scores
                        .map((s) => `${s.subNumber}:${s.score}分`)
                        .join("，")
                    }}
                  </p>
                </div>
              </div>
              <div v-else>
                <p
                  v-for="user in minfo.users"
                  :key="user.userId"
                  :style="{ color: user.color }"
                >
                  {{ user.prename }}：{{ user.userName }}，评分：{{
                    user.score
                  }}
                </p>
              </div>
              <h3>得分：{{ minfo.score }}，满分：{{ minfo.maxScore }}</h3>
            </div>
          </template>
          <!-- 客观题 -->
          <template v-if="item.objectiveAnswerTags">
            <div
              v-for="tag in item.objectiveAnswerTags"
              :key="tag.id"
              class="mark-objective"
              :style="tag.style"
            >
              得分：{{ tag.score }}，满分：{{ tag.totalScore }}
            </div>
          </template>

          <!-- 总分 -->
          <div class="mark-total">
            总分：{{ totalScore }}，主观题得分：{{
              subjectiveScore
            }}，客观题得分：{{ objectiveScore }}
          </div>
          <hr class="image-seperator" />
        </div>
      </div>
      <div v-else>未知数据</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { reactive, watch } from "vue";
import { store } from "@/store/store";
import MarkDrawTrack from "@/features/mark/MarkDrawTrack.vue";
import type {
  SpecialTag,
  Track,
  ColorMap,
  PaperRecogData,
  Question,
} from "@/types";
import { useTimers } from "@/setups/useTimers";
import { loadImage, addHeaderTrackColorAttr, calcSum } from "@/utils/utils";
import { dragImage } from "@/features/mark/use/draggable";
import { maxNum } from "@/utils/utils";

interface SliceImage {
  url: string;
  trackList: Array<Track>;
  tagList: Array<SpecialTag>;
  originalImageWidth: number;
  originalImageHeight: number;
  width: string; // 图片在整个图片列表里面的宽度比例
  answerTags?: AnswerTagItem[];
  markDetail?: MarkDetailItem[];
  objectiveAnswerTags?: ObjectiveAnswerTagItem[];
}

const { origImageUrls = "sliceUrls" } = defineProps<{
  origImageUrls?: "sheetUrls" | "sliceUrls";
}>();
const emit = defineEmits(["error", "getIsMultComments", "getScrollStatus"]);

const { dragContainer } = dragImage();
const viewScroll = () => {
  if (
    dragContainer.value.scrollTop + dragContainer.value.offsetHeight + 50 >=
    dragContainer.value.scrollHeight
  ) {
    emit("getScrollStatus");
  }
};
const { addTimeout } = useTimers();

const totalScore = $computed(() => {
  return store.currentTask?.markerScore || 0;
});
const objectiveScore = $computed(() => {
  return store.currentTask?.objectiveScore || 0;
});
const subjectiveScore = $computed(() => {
  return totalScore - objectiveScore;
});

let sliceImagesWithTrackList: SliceImage[] = reactive([]);
let maxImageWidth = 0;

function addTrackColorAttr(tList: Track[]): Track[] {
  let markerIds: (number | undefined)[] = tList
    .map((v) => v.userId)
    .filter((x) => !!x);
  markerIds = Array.from(new Set(markerIds));
  // markerIds.sort();
  let colorMap: ColorMap = {};
  for (let i = 0; i < markerIds.length; i++) {
    const mId: any = markerIds[i];
    if (i == 0) {
      colorMap[mId + ""] = "red";
    } else if (i == 1) {
      colorMap[mId + ""] = "blue";
    } else if (i > 1) {
      colorMap[mId + ""] = "gray";
    }
  }
  if (Object.keys(colorMap).length > 1) {
    emit("getIsMultComments", true);
  }
  tList = tList.map((item: Track) => {
    item.color = colorMap[item.userId + ""] || "red";
    item.isByMultMark = markerIds.length > 1;
    return item;
  });
  return tList;
}

function addTagColorAttr(tList: SpecialTag[]): SpecialTag[] {
  let markerIds: (number | undefined)[] = tList
    .map((v) => v.userId)
    .filter((x) => !!x);
  markerIds = Array.from(new Set(markerIds));
  // markerIds.sort();
  let colorMap: ColorMap = {};
  for (let i = 0; i < markerIds.length; i++) {
    const mId: any = markerIds[i];
    if (i == 0) {
      colorMap[mId + ""] = "red";
    } else if (i == 1) {
      colorMap[mId + ""] = "blue";
    } else if (i > 1) {
      colorMap[mId + ""] = "gray";
    }
  }
  tList = tList.map((item: SpecialTag) => {
    item.color = colorMap[item.userId + ""] || "red";
    item.isByMultMark = markerIds.length > 1;
    return item;
  });
  return tList;
}

async function processImage() {
  if (!store.currentTask) return;

  const images = [];
  const urls = store.currentTask[origImageUrls] || [];
  for (const url of urls) {
    const image = await loadImage(url);
    images.push(image);
  }

  maxImageWidth = Math.max(...images.map((i) => i.naturalWidth));

  const trackLists = (store.currentTask.questionList || [])
    // .map((q) => q.trackList)
    .map((q) => {
      let tList = q.trackList;
      return q.headerTrack?.length
        ? addHeaderTrackColorAttr(q.headerTrack)
        : addTrackColorAttr(tList);
    })
    .flat();
  store.setting.doubleTrack = trackLists.some((item) => item.isByMultMark);

  // 解析各试题答题区域以及评分
  const markDetailList = parseMarkDetailList();
  // 解析客观题的得分情况，按大题统计
  const objectiveAnswerTagList = parseObjectiveAnswerTags();

  for (const url of urls) {
    const indexInSliceUrls = urls.indexOf(url) + 1;
    const image = images[indexInSliceUrls - 1];

    const thisImageTrackList = trackLists.filter(
      (t) => t.offsetIndex === indexInSliceUrls
    );
    const thisImageTagList = store.currentTask.headerTagList?.length
      ? addHeaderTrackColorAttr(
          (store.currentTask.headerTagList || []).filter(
            (t) => t.offsetIndex === indexInSliceUrls
          )
        )
      : addTagColorAttr(
          (store.currentTask.specialTagList || []).filter(
            (t) => t.offsetIndex === indexInSliceUrls
          )
        );
    const answerTags = paserRecogData(image, indexInSliceUrls - 1);

    sliceImagesWithTrackList.push({
      url,
      trackList: thisImageTrackList,
      tagList: thisImageTagList,
      originalImageWidth: image.naturalWidth,
      originalImageHeight: image.naturalHeight,
      width: (image.naturalWidth / maxImageWidth) * 100 + "%",
      answerTags,
      markDetail: markDetailList[indexInSliceUrls - 1],
      objectiveAnswerTags: objectiveAnswerTagList[indexInSliceUrls - 1],
    });
  }
}

// 解析客观题答案展示位置
interface AnswerTagItem {
  mainNumber: number;
  subNumber: string;
  answer: string;
  style: Record<string, string>;
}
function paserRecogData(imgDom: HTMLImageElement, imageIndex): AnswerTagItem[] {
  if (
    !store.currentTask.recogDatas?.length ||
    !store.currentTask.recogDatas[imageIndex]
  )
    return [];

  const answerMap = store.currentTask.answerMap || {};
  const { naturalWidth, naturalHeight } = imgDom;
  const recogData: PaperRecogData = JSON.parse(
    window.atob(store.currentTask.recogDatas[imageIndex])
  );
  const answerTags: AnswerTagItem[] = [];
  // const optionsBlocks = [];
  recogData.question.forEach((question) => {
    question.fill_result.forEach((result) => {
      const tagSize = result.fill_size[1];
      const fillPositions = result.fill_position.map((pos) => {
        return pos.split(",").map((n) => n * 1);
      });

      const offsetLt = result.fill_size.map((item) => item * 0.4);
      const tagLeft =
        maxNum(fillPositions.map((pos) => pos[0])) +
        result.fill_size[0] -
        offsetLt[0];
      const tagTop = fillPositions[0][1] - offsetLt[1];

      const { answer, isRight } =
        answerMap[`${result.main_number}_${result.sub_number}`] || {};

      answerTags.push({
        mainNumber: result.main_number,
        subNumber: result.sub_number,
        answer,
        style: {
          height: ((100 * tagSize) / naturalHeight).toFixed(4) + "%",
          fontSize: ((100 * 20) / tagSize).toFixed(4) + "%",
          left: ((100 * tagLeft) / naturalWidth).toFixed(4) + "%",
          top: ((100 * tagTop) / naturalHeight).toFixed(4) + "%",
          position: "absolute",
          color: isRight ? "#05b575" : "#f53f3f",
          fontWeight: 600,
          lineHeight: 1,
          zIndex: 9,
        },
      });

      // 测试：选项框
      // fillPositions.forEach((fp, index) => {
      //   optionsBlocks.push({
      //     mainNumber: result.main_number,
      //     subNumber: result.sub_number,
      //     filled: !!result.fill_option[index],
      //     style: {
      //       width:
      //         ((100 * result.fill_size[0]) / naturalWidth).toFixed(4) + "%",
      //       height:
      //         ((100 * result.fill_size[1]) / naturalHeight).toFixed(4) + "%",
      //       left:
      //         ((100 * (fp[0] - offsetLt[0])) / naturalWidth).toFixed(4) + "%",
      //       top:
      //         ((100 * (fp[1] - offsetLt[1])) / naturalHeight).toFixed(4) + "%",
      //       position: "absolute",
      //       border: "1px solid #f53f3f",
      //       background: result.fill_option[index]
      //         ? "rgba(245, 63, 63, 0.5)"
      //         : "transparent",
      //       zIndex: 9,
      //     },
      //   });
      // });
    });
  });

  return answerTags;
}

interface QuestionItem {
  mainNumber: number;
  subNumber: number | string;
}
interface QuestionArea {
  i: number;
  x: number;
  y: number;
  w: number;
  h: number;
  qStruct: string;
}
function parseQuestionAreas(questions: QuestionItem[]) {
  if (!questions.length || !store.currentTask.cardData?.length) return [];

  let pictureConfigs: QuestionArea[] = [];
  const structs = questions.map(
    (item) => `${item.mainNumber}_${item.subNumber}`
  );
  store.currentTask.cardData.forEach((page, pindex) => {
    page.exchange.answer_area.forEach((area) => {
      const [x, y, w, h] = area.area;
      const qStruct = `${area.main_number}_${area.sub_number}`;

      const pConfig: QuestionArea = {
        i: pindex + 1,
        x,
        y,
        w,
        h,
        qStruct,
      };

      if (typeof area.sub_number === "number") {
        if (!structs.includes(qStruct)) return;
        pictureConfigs.push(pConfig);
        return;
      }
      // 复合区域处理，比如填空题，多个小题合并为一个区域
      if (typeof area.sub_number === "string") {
        const areaStructs = area.sub_number
          .split(",")
          .map((subNumber) => `${area.main_number}_${subNumber}`);
        if (
          structs.some((struct) => areaStructs.includes(struct)) &&
          !pictureConfigs.find((item) => item.qStruct === qStruct)
        ) {
          pictureConfigs.push(pConfig);
        }
      }
    });
  });
  // console.log(pictureConfigs);

  // 合并相邻区域
  pictureConfigs.sort((a, b) => {
    return a.i - b.i || a.x - b.x || a.y - b.y;
  });
  let combinePictureConfigList: QuestionArea[] = [];
  let prevConfig = null;
  pictureConfigs.forEach((item, index) => {
    if (!index) {
      prevConfig = { ...item };
      combinePictureConfigList.push(prevConfig);
      return;
    }

    const elasticRate = 0.01;
    if (
      prevConfig.i === item.i &&
      prevConfig.y + prevConfig.h + elasticRate >= item.y &&
      prevConfig.w === item.w &&
      prevConfig.x === item.x
    ) {
      prevConfig.h = item.y + item.h - prevConfig.y;
    } else {
      prevConfig = { ...item };
      combinePictureConfigList.push(prevConfig);
    }
  });
  // console.log(combinePictureConfigList);
  return combinePictureConfigList;
}

// 获取属于填空题的试题号
function getFillLines() {
  if (!store.currentTask.cardData?.length) return {};

  const questions: Record<number, string[]> = {};
  store.currentTask.cardData.forEach((page) => {
    page.columns.forEach((column) => {
      column.elements.forEach((element) => {
        if (element.type !== "FILL_LINE") return;

        if (!questions[element.topicNo]) questions[element.topicNo] = [];

        for (let i = 0; i < element.questionsCount; i++) {
          questions[element.topicNo].push(
            `${element.topicNo}_${element.startNumber + i}`
          );
        }
      });
    });
  });
  return questions;
}

// 解析各试题答题区域以及评分
interface MarkDetailUserItem {
  userId: string;
  userName: string;
  prename: string;
  color: string;
  scores: Array<{ subNumber: string; score: number }>;
  score: number;
}
type UserMapType = Record<string, MarkDetailUserItem>;
interface MarkDetailItem {
  mainNumber: number;
  subNumber: string;
  isFillQuestion: boolean;
  score: number;
  maxScore: number;
  users: MarkDetailUserItem[];
  area: QuestionArea;
  style: Record<string, string>;
}

function parseMarkDetailList(): Array<MarkDetailItem[]> {
  const dataList: Array<MarkDetailItem[]> = [];
  const questions = store.currentTask.questionList || [];

  const fillQues = getFillLines();
  let fillQuestions = [] as Question[];
  let otherQuestions = questions;
  if (Object.keys(fillQues).length) {
    const fillQNos = Object.values(fillQues).flat();
    fillQuestions = questions.filter((q) =>
      fillQNos.includes(`${q.mainNumber}_${q.subNumber}`)
    );
    otherQuestions = questions.filter(
      (q) => !fillQNos.includes(`${q.mainNumber}_${q.subNumber}`)
    );
  }

  // 填空题：合并所有小题为一个区域
  Object.values(fillQues).forEach((qnos) => {
    const groupQuestions = fillQuestions.filter((q) =>
      qnos.includes(`${q.mainNumber}_${q.subNumber}`)
    );
    const areas = parseQuestionAreas(groupQuestions);
    if (!areas.length) return;
    const area = { ...areas[0] };
    const imgIndex = area.i - 1;
    if (!dataList[imgIndex]) {
      dataList[imgIndex] = [];
    }

    const userMap: UserMapType = {};
    // 大题分成两个部分给两个人评 与 大题被两人同时评 是不一样的
    const isDoubleMark = !groupQuestions.some((question) => {
      const userIds = question.trackList.map((track) => track.userId);
      const uids = new Set(userIds);
      return uids.size === 1;
    });
    groupQuestions.forEach((question) => {
      question.trackList.forEach((track) => {
        if (!userMap[track.userId]) {
          userMap[track.userId] = {
            userId: track.userId,
            userName: track.userName,
            color: track.color || "red",
            prename: "",
            scores: [],
            score: 0,
          };
        }
        const existUserScore = userMap[track.userId].scores.find(
          (s) => s.subNumber === track.subNumber
        );
        if (existUserScore) {
          existUserScore.score += track.score;
        } else {
          userMap[track.userId].scores.push({
            score: track.score,
            subNumber: track.subNumber,
          });
        }
      });
    });

    const users = Object.values(userMap).map((user, index) => {
      const zhs = ["一", "二", "三"];
      const prename = isDoubleMark ? `${zhs[index] || ""}评` : "评卷员";
      return {
        ...user,
        prename,
        score: calcSum(user.scores.map((s) => s.score)),
      };
    });

    const score = calcSum(groupQuestions.map((item) => item.score || 0));
    const maxScore = calcSum(groupQuestions.map((item) => item.maxScore));

    dataList[imgIndex].push({
      mainNumber: groupQuestions[0].mainNumber,
      subNumber: "",
      isFillQuestion: true,
      score,
      maxScore,
      users,
      area,
      style: {
        position: "absolute",
        left: (100 * area.x).toFixed(4) + "%",
        top: (100 * area.y).toFixed(4) + "%",
        width: (100 * area.w).toFixed(4) + "%",
        fontSize: "14px",
        lineHeight: 1,
        zIndex: 9,
      },
    });
  });

  // 其他试题
  otherQuestions.forEach((question) => {
    const areas = parseQuestionAreas([question]);
    const area = { ...areas[0] };
    const imgIndex = area.i - 1;
    if (!dataList[imgIndex]) {
      dataList[imgIndex] = [];
    }

    const userMap: UserMapType = {};
    const isArbitration = Boolean(question.headerTrack?.length);
    const tList = isArbitration ? question.headerTrack : question.trackList;
    tList.forEach((track) => {
      if (!userMap[track.userId]) {
        userMap[track.userId] = {
          userId: track.userId,
          userName: track.userName,
          color: track.color || "red",
          prename: "",
          scores: [],
          score: 0,
        };
      }
      userMap[track.userId].scores.push({
        score: track.score,
        subNumber: track.subNumber,
      });
    });

    const isDoubleMark = Object.keys(userMap).length > 1;
    const users = Object.values(userMap).map((user, index) => {
      const zhs = ["一", "二", "三"];
      let prename = "";
      if (isArbitration) {
        prename = "仲裁";
      } else {
        prename = isDoubleMark ? `${zhs[index] || ""}评` : "评卷员";
      }
      return {
        ...user,
        prename,
        score: calcSum(user.scores.map((s) => s.score)),
      };
    });

    dataList[imgIndex].push({
      mainNumber: question.mainNumber,
      subNumber: question.subNumber,
      isFillQuestion: false,
      score: question.score,
      maxScore: question.maxScore,
      users,
      area,
      style: {
        position: "absolute",
        left: (100 * area.x).toFixed(4) + "%",
        top: (100 * area.y).toFixed(4) + "%",
        width: (100 * area.w).toFixed(4) + "%",
        fontSize: "14px",
        lineHeight: 1,
        zIndex: 9,
      },
    });
  });

  return dataList;
}

// 解析客观题区域总分
interface ObjectiveAnswerTagItem {
  id: string;
  mainNumber: number;
  subNumbers: string;
  score: number;
  totalScore: number;
  style: Record<string, string | number>;
}
function parseObjectiveAnswerTags() {
  const objectiveAnswerTags: Array<ObjectiveAnswerTagItem[]> = [];

  if (!store.currentTask.cardData?.length || !store.currentTask.answerMap)
    return objectiveAnswerTags;

  store.currentTask.cardData.forEach((page, pindex) => {
    if (!objectiveAnswerTags[pindex]) objectiveAnswerTags[pindex] = [];

    page.columns.forEach((column) => {
      column.elements.forEach((element) => {
        if (element.type !== "FILL_QUESTION") return;

        const ogroup = objectiveAnswerTags.find((tgroup) =>
          tgroup.some((oitem) => oitem.id === element.parent.id)
        );
        if (ogroup) return;

        const parent = element.parent;
        const oaTagItem: ObjectiveAnswerTagItem = {
          id: parent.id,
          mainNumber: parent.topicNo,
          subNumbers: `${parent.startNumber}~${
            parent.startNumber + parent.questionsCount - 1
          }`,
          score: 0,
          totalScore: 0,
          style: {
            position: "absolute",
            left: 0,
            top: 0,
            textAlign: "right",
            width: "44%",
            fontSize: "20px",
            fontWeight: "bold",
            color: "#f53f3f",
            lineHeight: 1,
            zIndex: 9,
          },
        };

        let area = [0, 0];
        page.exchange.fill_area.forEach((fa) => {
          fa.items.forEach((fitem) => {
            if (
              fitem.main_number === oaTagItem.mainNumber &&
              fitem.sub_number === parent.startNumber
            ) {
              area = fitem.options[0];
            }
          });
        });

        const left = (100 * (area[0] - 0.015)).toFixed(4);
        const top = (100 * (area[1] - 0.04)).toFixed(4);
        oaTagItem.style.left = `${left}%`;
        oaTagItem.style.top = `${top}%`;

        const questions: Array<{ score: number; totalScore: number }> = [];
        for (let i = 0; i < parent.questionsCount; i++) {
          const qans = store.currentTask.answerMap[
            `${parent.topicNo}_${i + parent.startNumber}`
          ] || { score: 0, totalScore: 0 };
          questions[i] = {
            score: qans.score,
            totalScore: qans.totalScore,
          };
        }

        oaTagItem.score = calcSum(questions.map((q) => q.score || 0));
        oaTagItem.totalScore = calcSum(questions.map((q) => q.totalScore || 0));

        objectiveAnswerTags[pindex].push(oaTagItem);
      });
    });
  });

  return objectiveAnswerTags;
}

// should not render twice at the same time
let renderLock = false;
const renderPaperAndMark = async () => {
  if (renderLock) {
    console.log("上个任务还未渲染完毕，稍等一秒再尝试渲染");
    await new Promise((res) => setTimeout(res, 1000));
    await renderPaperAndMark();
    return;
  }
  renderLock = true;
  sliceImagesWithTrackList.splice(0);

  if (!store.currentTask) {
    renderLock = false;
    return;
  }

  try {
    store.globalMask = true;
    await processImage();
  } catch (error) {
    sliceImagesWithTrackList.splice(0);
    console.log("render error ", error);
    // 图片加载出错，自动加载下一个任务
    emit("error");
  } finally {
    await new Promise((res) => setTimeout(res, 500));
    store.globalMask = false;
    renderLock = false;
  }
};

watch(() => store.currentTask, renderPaperAndMark);

watch(
  (): (number | undefined)[] => [
    store.minimapScrollToX,
    store.minimapScrollToY,
  ],
  () => {
    const container = document.querySelector<HTMLDivElement>(
      ".mark-body-container"
    );
    addTimeout(() => {
      if (
        container &&
        typeof store.minimapScrollToX === "number" &&
        typeof store.minimapScrollToY === "number"
      ) {
        const { scrollWidth, scrollHeight } = container;
        container.scrollTo({
          top: scrollHeight * store.minimapScrollToY,
          left: scrollWidth * store.minimapScrollToX,
          behavior: "smooth",
        });
      }
    }, 10);
  }
);

const answerPaperScale = $computed(() => {
  // 放大、缩小不影响页面之前的滚动条定位
  let percentWidth = 0;
  let percentTop = 0;
  const container = document.querySelector(".mark-body-container");
  if (container) {
    const { scrollLeft, scrollTop, scrollWidth, scrollHeight } = container;
    percentWidth = scrollLeft / scrollWidth;
    percentTop = scrollTop / scrollHeight;
  }

  addTimeout(() => {
    if (container) {
      const { scrollWidth, scrollHeight } = container;
      container.scrollTo({
        left: scrollWidth * percentWidth,
        top: scrollHeight * percentTop,
      });
    }
  }, 10);
  const scale = store.setting.uiSetting["answer.paper.scale"];
  return scale * 100 + "%";
});
</script>

<style scoped>
.mark-body-container {
  overflow: auto;
  background-color: var(--app-container-bg-color);
  background-image: linear-gradient(45deg, #e0e0e0 25%, transparent 25%),
    linear-gradient(-45deg, #e0e0e0 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, #e0e0e0 75%),
    linear-gradient(-45deg, transparent 75%, #e0e0e0 75%);
  background-size: 20px 20px;
  background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
  transform: inherit;

  cursor: grab;
  user-select: none;
}
.mark-body-container img {
  width: 100%;
}
.single-image-container {
  position: relative;
}
.image-seperator {
  border: 2px solid rgba(120, 120, 120, 0.1);
}
.mark-info {
  display: flex;
  justify-content: space-between;
}
.mark-info h3 {
  font-size: 20px;
  font-weight: bold;
  line-height: 1;
  color: #f53f3f;
}
.mark-info p {
  margin: 0;
  line-height: 20px;
  font-weight: bold;
}
.mark-total {
  font-size: 20px;
  font-weight: bold;
  position: absolute;
  top: 1%;
  left: 15%;
  z-index: 9;
  color: #f53f3f;
}
</style>
