feat. FX_PREREGIST_01 템플릿 제작

This commit is contained in:
clkim
2025-11-04 21:14:45 +09:00
parent e76ac480b7
commit 6518695096
37 changed files with 678 additions and 59 deletions

View File

@@ -36,7 +36,7 @@
@apply line-clamp-2 text-[16px] font-[500] leading-[24px] drop-shadow-[0_2px_2px_rgba(0,0,0,0.6)] md:line-clamp-1 md:text-[24px] md:leading-[34px];
}
.title-sm {
@apply text-[15px] font-[500] leading-[24px] tracking-[-0.45px] md:text-[20px] md:leading-[30px] md:tracking-[-0.6px];
@apply text-[15px] font-[500] leading-[24px] tracking-[-0.45px] drop-shadow-[0_2px_2px_rgba(0,0,0,0.6)] md:text-[20px] md:leading-[30px] md:tracking-[-0.6px];
}
.title-xs {
@apply text-[14px] font-[500] leading-[20px] tracking-[-0.42px] md:text-[18px] md:leading-[26px] md:tracking-[-0.54px];

View File

@@ -13,6 +13,7 @@ interface Props {
arrows?: boolean
pagination?: boolean
paginationData?: PageDataResourceGroups
destroy?: boolean
breakpoints?: ResponsiveOptions['breakpoints']
}
@@ -23,6 +24,7 @@ const props = withDefaults(defineProps<Props>(), {
drag: true,
arrows: true,
pagination: true,
destroy: false,
})
const emit = defineEmits(['mounted', 'move', 'arrowClick'])
@@ -50,6 +52,7 @@ const options = computed((): ResponsiveOptions => {
trimSpace: false,
arrows: props.arrows,
pagination: props.pagination,
destroy: props.destroy,
classes: {
arrows: 'splide-arrows',
arrow: 'splide-arrow',

View File

@@ -11,6 +11,7 @@ import GrBoard01 from '#layers/templates/GrBoard01/index.vue'
import GrContents01 from '#layers/templates/GrContents01/index.vue'
import FxVideo01 from '#layers/templates/FxVideo01/index.vue'
import FxDownload01 from '#layers/templates/FxDownload01/index.vue'
import FxPreregist01 from '#layers/templates/FxPreregist01/index.vue'
const templateRegistry = {
GR_VISUAL_01: { component: GrVisual01 },
@@ -26,6 +27,7 @@ const templateRegistry = {
GR_CONTENTS_01: { component: GrContents01 },
FX_VIDEO_01: { component: FxVideo01 },
FX_DOWNLOAD_01: { component: FxDownload01 },
FX_PREREGIST_01: { component: FxPreregist01 },
} as const
type TemplateKey = keyof typeof templateRegistry

View File

@@ -1,15 +1,7 @@
<script setup lang="ts">
console.log('🚀 ~ promotion')
</script>
<script setup lang="ts"></script>
<template>
<div class="promotion-wrap">
<slot />
</div>
<LayoutsHeader />
<slot />
<LayoutsFooter />
</template>
<style scoped>
.promo-wrap {
background-color: tan;
}
</style>

View File

@@ -0,0 +1,627 @@
<script setup lang="ts">
import { SplideSlide } from '@splidejs/vue-splide'
import { getComponentGroup, getComponentGroupAry } from '#layers/utils/dataUtil'
import type { PageDataTemplateComponents } from '#layers/types/api/pageData'
interface Props {
components: PageDataTemplateComponents
pageVerTmplSeq: number
}
const props = defineProps<Props>()
const { tm } = useI18n()
const test = {
subTitle: {
groups: [
{
display: {
text: '사전 등록 기간 + 2024.06.04 ~ 정식 오픈 전까지',
color_code: '',
color_name: 'primary',
},
resource_type: 'TXT',
},
],
},
mainTitle: {
groups: [
{
display: {
text: '로드나인 사전 등록',
color_code: '',
color_name: 'primary',
},
resource_type: 'TXT',
},
],
},
background: {
groups: [
{
res_path: {
path_mo: '/local/template/l9/16/1/1/FX_PREREGIST_01/common/bg_m.jpg',
path_pc: '/local/template/l9/16/1/1/FX_PREREGIST_01/common/bg.jpg',
},
resource_type: 'IMG_COMM',
},
],
},
txtSnsLink: {
groups: [
{
display: {
text: 'https://pf.kakao.com/_xmyxjpG',
},
resource_type: 'TXT',
},
{
display: {
text: 'https://www.youtube.com/@LORDNINE_KR',
},
resource_type: 'TXT',
},
],
},
description: {
groups: [
{
display: {
text: '로드나인은 PC, GooglePlay, AppStore에서 즐기실 수 있습니다',
color_code: '',
color_name: 'text-primary',
},
resource_type: 'TXT',
},
],
},
imgAccReward: {
groups: [
{
display: {
text: '골드 100,000',
},
res_path: {
path_mo:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward01_m.png',
path_pc:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward01.png',
},
resource_type: 'IMG_LANG',
},
{
display: {
text: '중급 물약 x100',
},
res_path: {
path_mo:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward02_m.png',
path_pc:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward02.png',
},
resource_type: 'IMG_LANG',
},
{
display: {
text: '방어구 강화석 x3',
},
res_path: {
path_mo:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward03_m.png',
path_pc:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward03.png',
},
resource_type: 'IMG_LANG',
},
{
display: {
text: '무기 강화석 x3',
},
res_path: {
path_mo:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward04_m.png',
path_pc:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward04.png',
},
resource_type: 'IMG_LANG',
},
// {
// display: {
// text: '순수한 무기 강화석 x1',
// },
// res_path: {
// path_mo:
// '/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward05_m.png',
// path_pc:
// '/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward05.png',
// },
// resource_type: 'IMG_LANG',
// },
],
},
imgSnsButton: {
groups: [
{
res_path: {
path_mo:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/sns_button01_m.jpg',
path_pc:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/sns_button01.jpg',
},
tracking: {
click_item: 'imgSnsButton_7. 사전등록-SNS버튼이미지(1)',
action_type: 'click',
click_sarea: 'promotionPreregist_tmpl_01__imgSnsButton',
},
resource_type: 'IMG_LANG',
},
{
res_path: {
path_mo:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/sns_button02_m.jpg',
path_pc:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/sns_button02.jpg',
},
tracking: {
click_item: 'imgSnsButton_7. 사전등록-SNS버튼이미지(2)',
action_type: 'click',
click_sarea: 'promotionPreregist_tmpl_01__imgSnsButton',
},
resource_type: 'IMG_LANG',
},
],
},
imgSnsReward: {
groups: [
{
res_path: {
path_mo:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_preregist_reward_sns_m.png',
path_pc:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_preregist_reward_sns.png',
},
resource_type: 'IMG_LANG',
},
],
},
subTitleAccReward: {
groups: [
{
display: {
text: '이벤트 기간 + 2024.06.04 ~ 정식 오픈 전까지',
color_code: '#c5902f',
color_name: '',
},
resource_type: 'TXT',
},
],
},
imgPreregistReward: {
groups: [
{
res_path: {
path_mo:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_preregist_reward_m.png',
path_pc:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_preregist_reward.png',
},
resource_type: 'IMG_LANG',
},
],
},
mainTitleAccReward: {
groups: [
{
display: {
text: '카카오톡 공식 채널 구독 이벤트',
color_code: '#c5902f',
color_name: '',
},
resource_type: 'TXT',
},
],
},
backgroundAccReward: {
groups: [
{
res_path: {
path_mo:
'/local/template/l9/16/1/1/FX_PREREGIST_01/common/bg_acc_reward_m.jpg',
path_pc:
'/local/template/l9/16/1/1/FX_PREREGIST_01/common/bg_acc_reward.jpg',
},
resource_type: 'IMG_COMM',
},
],
},
descriptionAccReward: {
groups: [
{
display: {
text: '※ 달성 여부는 실시간으로 반영되지 않을 수 있습니다.',
color_code: '#737474',
color_name: '',
},
resource_type: 'TXT',
},
],
},
isAccRewardCompleted: {},
preregistButtonColor: {
groups: [
{
display: {
color_code: '#cc0000',
color_name: '',
},
resource_type: 'COLOR',
},
{
display: {
color_code: '#ccff00',
color_name: '',
},
resource_type: 'COLOR',
},
],
},
rewardTitleAccReward: {
groups: [
{
display: {
text: '누적 목표를 달성할수록 더 많은 보상을 드립니다!',
color_code: '#33312e',
color_name: '',
},
resource_type: 'TXT',
},
],
},
imgAccRewardIncomplete: {
groups: [
{
display: {
text: '골드 100,000',
},
res_path: {
path_mo:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete01_m.png',
path_pc:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete01.png',
},
resource_type: 'IMG_LANG',
},
{
display: {
text: '중급 물약 x100',
},
res_path: {
path_mo:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete02_m.png',
path_pc:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete02.png',
},
resource_type: 'IMG_LANG',
},
{
display: {
text: '방어구 강화석 x3',
},
res_path: {
path_mo:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete03_m.png',
path_pc:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete03.png',
},
resource_type: 'IMG_LANG',
},
{
display: {
text: '무기 강화석 x3',
},
res_path: {
path_mo:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete04_m.png',
path_pc:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete04.png',
},
resource_type: 'IMG_LANG',
},
{
display: {
text: '순수한 무기 강화석 x1',
},
res_path: {
path_mo:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete05_m.png',
path_pc:
'/local/template/l9/16/1/1/FX_PREREGIST_01/ko/img_acc_reward_incomplete05.png',
},
resource_type: 'IMG_LANG',
},
],
},
} as any
// Constants
const PREREGIST_PLATFORMS = [
{ platform: 'stove', label: '사전 등록 하기' },
{ platform: 'google_play', label: '사전 등록 하기' },
{ platform: 'app_store', label: '사전 등록 하기' },
] as const
const COLOR_INDEX = {
BACKGROUND: 0,
TEXT: 1,
} as const
// Preregist Section
const backgroundData = computed(() =>
getComponentGroup(props.components, 'background')
)
const mainTitleData = computed(() =>
getComponentGroup(props.components, 'mainTitle')
)
const subTitleData = computed(() =>
getComponentGroup(props.components, 'subTitle')
)
const imgPreregistRewardData = computed(() =>
getComponentGroup(props.components, 'imgPreregistReward')
)
const imgSnsRewardData = computed(() =>
getComponentGroup(props.components, 'imgSnsReward')
)
const preregistButtonColorData = computed(() =>
getComponentGroupAry(props.components, 'preregistButtonColor')
)
const imgSnsButtonData = computed(() =>
getComponentGroupAry(props.components, 'imgSnsButton')
)
const txtSnsLinkData = computed(() =>
getComponentGroupAry(props.components, 'txtSnsLink')
)
const descriptionData = computed(() =>
getComponentGroup(props.components, 'description')
)
const snsButtons = computed(() => {
const buttons = imgSnsButtonData.value
const links = txtSnsLinkData.value
if (!buttons?.length) return []
return buttons.map((button, index) => ({
image: button,
link: links?.[index]?.display?.text ?? '',
}))
})
const buttonColors = computed(() => {
const colorData = preregistButtonColorData.value
if (!colorData?.length) {
return { background: undefined, text: undefined }
}
return {
background: getColorCode({
colorName: colorData[COLOR_INDEX.BACKGROUND]?.display?.color_name,
colorCode: colorData[COLOR_INDEX.BACKGROUND]?.display?.color_code,
}),
text: getColorCode({
colorName: colorData[COLOR_INDEX.TEXT]?.display?.color_name,
colorCode: colorData[COLOR_INDEX.TEXT]?.display?.color_code,
}),
}
})
// Reward Section
const backgroundAccRewardData = computed(() =>
getComponentGroup(props.components, 'backgroundAccReward')
)
const mainTitleAccRewardData = computed(() =>
getComponentGroup(props.components, 'mainTitleAccReward')
)
const subTitleAccRewardData = computed(() =>
getComponentGroup(props.components, 'subTitleAccReward')
)
const rewardTitleAccRewardData = computed(() =>
getComponentGroup(props.components, 'rewardTitleAccReward')
)
const imgAccRewardData = computed(() =>
getComponentGroupAry(test, 'imgAccReward')
)
const imgAccRewardLength = computed(() => imgAccRewardData.value?.length ?? 0)
const descriptionAccRewardData = computed(() =>
getComponentGroup(props.components, 'descriptionAccReward')
)
const splideOptions = computed(() => {
return {
type: 'slide',
gap: 16,
arrows: false,
pagination: false,
destroy: true,
breakpoints: {
[BREAKPOINTS.md - 1]: {
destroy: imgAccRewardLength.value <= 3,
perPage: 'auto',
focus: 'center',
drag: imgAccRewardLength.value > 3,
padding: {
left: 40,
right: 40,
},
},
[BREAKPOINTS.sm - 1]: {
destroy: false,
gap: 12,
drag: true,
padding: {
left: 20,
right: 20,
},
},
},
}
})
</script>
<template>
<section class="relative py-[80px] md:py-[120px]">
<WidgetsBackground v-if="backgroundData" :resources-data="backgroundData" />
<div class="content-standard">
<WidgetsMainTitle
v-if="mainTitleData"
:resources-data="mainTitleData"
class="title-xlg"
/>
<WidgetsSubTitle
v-if="subTitleData"
:resources-data="subTitleData"
class="title-sm mt-2"
/>
<div class="flex flex-col gap-4 mt-8 md:flex-row">
<div v-if="imgPreregistRewardData" class="w-full max-w-[446px]">
<AtomsImg
:src="getImagePaths(imgPreregistRewardData)"
loading="lazy"
decoding="async"
class="w-full h-full object-contain"
/>
</div>
<div v-if="imgSnsRewardData" class="relative w-full max-w-[446px]">
<AtomsImg
:src="getImagePaths(imgSnsRewardData)"
loading="lazy"
decoding="async"
class="w-full h-full object-contain"
/>
<ul
v-if="snsButtons.length"
class="absolute bottom-[20px] left-0 w-full flex items-center justify-center gap-2 md:bottom-[24px] md:gap-3"
>
<li
v-for="(snsButton, index) in snsButtons"
:key="`sns-${snsButton.link}-${index}`"
>
<a
:href="snsButton.link"
target="_blank"
rel="noopener noreferrer"
>
<AtomsImg :src="getImagePaths(snsButton.image)" />
<span class="sr-only">
{{ snsButton.link }}
</span>
</a>
</li>
</ul>
</div>
</div>
<div
v-if="PREREGIST_PLATFORMS.length"
class="flex gap-3 justify-center flex-wrap mt-8 md:gap-2.5"
>
<AtomsButtonLauncher
v-for="item in PREREGIST_PLATFORMS"
:key="`preregist-${item.platform}`"
type="duplication"
:platform="item.platform"
:background-color="buttonColors.background"
:text-color="buttonColors.text"
>
{{ item.label }}
</AtomsButtonLauncher>
</div>
<WidgetsDescription
v-if="descriptionData"
:resources-data="descriptionData"
class="mt-8"
/>
</div>
</section>
<section class="relative py-[80px] md:py-[120px]">
<WidgetsBackground
v-if="backgroundAccRewardData"
:resources-data="backgroundAccRewardData"
/>
<div class="content-standard">
<WidgetsMainTitle
v-if="mainTitleAccRewardData"
:resources-data="mainTitleAccRewardData"
class="title-xlg"
/>
<WidgetsSubTitle
v-if="subTitleAccRewardData"
:resources-data="subTitleAccRewardData"
class="title-sm mt-2"
/>
<WidgetsSubTitle
v-if="rewardTitleAccRewardData"
tag="h4"
:resources-data="rewardTitleAccRewardData"
class="mt-[48px] text-[18px] font-[700] leading-[26px] tracking-[-0.54px] drop-shadow-[0_2px_2px_rgba(0,0,0,0.6)] md:mt-[72px] md:text-[24px] md:leading-[34px] md:tracking-[0.72px]"
/>
<div v-if="imgAccRewardLength" class="mt-6 md:mt-8">
<ul class="hidden md:flex justify-center md:mb-[20px]">
<li
v-for="index in imgAccRewardLength"
:key="index"
class="flex items-center"
>
<span class="progress-bullet"></span>
<div v-if="index !== imgAccRewardLength" class="progress-bar">
<span class="progress-fill"></span>
</div>
</li>
</ul>
<BlocksSlideDefault
v-bind="splideOptions"
class="w-[100vw] mx-[-20px] sm:mx-[-40px] md:w-auto md:mx-auto"
>
<SplideSlide
v-for="(item, index) in imgAccRewardData"
:key="`reward-${item.id ?? index}`"
class="w-[162px] h-[228px] md:w-[176px] md:h-[249px]"
>
<AtomsImg
:src="getImagePaths(item)"
:alt="item?.display?.text ?? `Reward ${index + 1}`"
loading="lazy"
decoding="async"
class="w-full h-full object-contain"
/>
</SplideSlide>
</BlocksSlideDefault>
</div>
<WidgetsDescription
v-if="descriptionAccRewardData"
:resources-data="descriptionAccRewardData"
class="mt-6 md:mt-8"
/>
</div>
</section>
</template>
<style scoped>
/* destroy되었을 때 (슬라이드 비활성화) 중앙 정렬 */
.splide:not(.is-active):deep(.splide__list) {
@apply flex justify-center gap-3 md:gap-4;
}
.progress-bullet {
@apply block w-3 h-3 rounded-full transition-all duration-300;
background-color: red;
/* background-color: var(--pagination-disabled); */
}
.progress-bar {
@apply relative w-[180px] h-0.5 overflow-hidden;
/* background-color: var(--pagination-disabled); */
background-color: red;
}
.progress-fill {
@apply absolute inset-y-0 left-0 w-[0];
background-color: var(--pagination-active);
}
</style>

View File

@@ -58,33 +58,42 @@ const { data: slideData } = await useAsyncData(
server: false,
}
)
const slideLength = computed(() => slideData.value.length)
const slideClass = computed(() => ({
'is-one-item': slideLength.value === 1,
'is-two-items': slideLength.value === 2,
'is-three-items': slideLength.value === 3,
'is-four-items': slideLength.value === 4,
}))
const splideOptions = computed(() => ({
gap: 20,
perPage: 4,
drag: false,
arrows: slideLength.value > 4,
pagination: slideLength.value > 4,
breakpoints: {
[BREAKPOINTS.lg - 1]: {
perPage: 2,
arrows: slideLength.value > 2,
pagination: slideLength.value > 2,
const slideLength = computed(() => slideData.value.length ?? 0)
const splideOptions = computed(() => {
return {
gap: 20,
perPage: 4,
drag: false,
arrows: slideLength.value > 4,
pagination: slideLength.value > 4,
destroy: slideLength.value <= 4,
breakpoints: {
[BREAKPOINTS.lg - 1]: {
perPage: 2,
arrows: slideLength.value > 2,
pagination: slideLength.value > 2,
destroy: slideLength.value < 3,
},
[BREAKPOINTS.md - 1]: {
drag: true,
perPage: 1,
arrows: false,
pagination: false,
destroy: slideLength.value < 2,
padding: {
left: 40,
right: 40,
},
},
[BREAKPOINTS.sm - 1]: {
padding: {
left: 20,
right: 20,
},
},
},
[BREAKPOINTS.md - 1]: {
drag: true,
perPage: 1,
arrows: false,
pagination: false,
},
},
}))
}
})
const getArticleUrl = (articleId: string) => {
const communityUrl = gameData.value?.url_json?.community
@@ -118,7 +127,7 @@ const onArrowClick = (direction, targetIndex) => {
v-if="slideLength > 0"
:slide-item-length="slideLength"
v-bind="splideOptions"
:class="`${slideClass} w-full`"
class="w-full"
@arrow-click="onArrowClick"
>
<SplideSlide
@@ -158,9 +167,6 @@ const onArrowClick = (direction, targetIndex) => {
.splide {
@apply mt-[24px] md:max-w-[776px] md:mt-[48px] md:mx-auto md:px-[72px] lg:max-w-[1428px];
}
.splide:deep(.splide__track) {
@apply !px-[20px] md:max-w-[632px] lg:max-w-[1284px] md:mx-auto md:!px-[0] sm:!px-[40px];
}
.splide:deep(.arrow-prev) {
@apply top-[calc(50%-28px)] left-[0];
}
@@ -168,23 +174,11 @@ const onArrowClick = (direction, targetIndex) => {
@apply top-[calc(50%-28px)] right-[0];
}
.slide-inner {
@apply w-[275px] aspect-[1/1] md:w-[306px] md:box-border;
@apply w-[275px] aspect-[1/1] md:w-[306px];
}
.splide.is-one-item:deep(.splide__track) {
@apply max-w-[315px] sm:max-w-[355px] mx-auto md:max-w-[306px];
}
.splide.is-two-items:deep(.splide__track) {
@apply lg:max-w-[632px];
}
.splide.is-two-items:deep(.splide__list) {
@apply md:!translate-x-0;
}
.splide.is-three-items:deep(.splide__track) {
@apply lg:max-w-[958px];
}
.splide.is-three-items:deep(.splide__list),
.splide.is-four-items:deep(.splide__list) {
@apply lg:!translate-x-0;
/* destroy되었을 때 (슬라이드 비활성화) 중앙 정렬 */
.splide:not(.is-active):deep(.splide__list) {
@apply flex justify-center gap-5;
}
</style>

View File

@@ -49,6 +49,7 @@ const buttonListData = computed(() => {
v-if="getImagePaths(item)"
:src="getImagePaths(item)"
:alt="item?.group_label"
class="w-full object-contain"
/>
</div>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 887 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

View File

Before

Width:  |  Height:  |  Size: 351 KiB

After

Width:  |  Height:  |  Size: 351 KiB

View File

Before

Width:  |  Height:  |  Size: 638 KiB

After

Width:  |  Height:  |  Size: 638 KiB

View File

Before

Width:  |  Height:  |  Size: 315 KiB

After

Width:  |  Height:  |  Size: 315 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB