Compare commits
6 commits
increase-t
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| d6a2af950c | |||
| b8e1d0f3fe | |||
| b019913621 | |||
| a00142e17c | |||
| 550b5c3d39 | |||
| 74c2bfd229 |
11 changed files with 3756 additions and 11 deletions
3194
package-lock.json
generated
Normal file
3194
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -9,6 +9,66 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
|
<div class="footer-main">
|
||||||
|
<div class="footer-decoration" aria-hidden="true">
|
||||||
|
<svg
|
||||||
|
class="footer-decoration__svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 1440 480"
|
||||||
|
preserveAspectRatio="xMidYMid slice"
|
||||||
|
fill="none"
|
||||||
|
>
|
||||||
|
<g stroke="white" stroke-linecap="round">
|
||||||
|
<circle
|
||||||
|
cx="1180"
|
||||||
|
cy="360"
|
||||||
|
r="130"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-opacity="0.14"
|
||||||
|
stroke-dasharray="10 8"
|
||||||
|
/>
|
||||||
|
<circle cx="1180" cy="360" r="98" stroke-width="1" stroke-opacity="0.08" />
|
||||||
|
<path
|
||||||
|
d="M60 100 Q220 20 400 110 T720 80"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke-opacity="0.16"
|
||||||
|
stroke-dasharray="6 10"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M100 320 Q340 260 560 340 T980 300"
|
||||||
|
stroke-width="1.2"
|
||||||
|
stroke-opacity="0.12"
|
||||||
|
stroke-dasharray="4 12"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M200 60 L240 100 M240 60 L200 100"
|
||||||
|
stroke-width="1"
|
||||||
|
stroke-opacity="0.1"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M320 400 L350 430 M350 400 L320 430"
|
||||||
|
stroke-width="1"
|
||||||
|
stroke-opacity="0.1"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M900 140 L930 170 M930 140 L900 170"
|
||||||
|
stroke-width="1"
|
||||||
|
stroke-opacity="0.08"
|
||||||
|
/>
|
||||||
|
<circle cx="180" cy="200" r="4" fill="white" fill-opacity="0.12" stroke="none" />
|
||||||
|
<circle cx="210" cy="220" r="3" fill="white" fill-opacity="0.1" stroke="none" />
|
||||||
|
<circle cx="240" cy="205" r="3.5" fill="white" fill-opacity="0.1" stroke="none" />
|
||||||
|
<circle cx="680" cy="90" r="3" fill="white" fill-opacity="0.08" stroke="none" />
|
||||||
|
<circle cx="710" cy="105" r="4" fill="white" fill-opacity="0.08" stroke="none" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
d="M1320 40 L1348 8 L1356 16 L1328 48 Z"
|
||||||
|
fill="white"
|
||||||
|
fill-opacity="0.1"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="content-container">
|
<div id="content-container">
|
||||||
<section class="footer-block">
|
<section class="footer-block">
|
||||||
<img
|
<img
|
||||||
|
|
@ -55,7 +115,24 @@
|
||||||
>
|
>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<section class="credits-container">
|
<section class="credits-container">
|
||||||
|
<div class="credits-decoration" aria-hidden="true">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 1440 48"
|
||||||
|
preserveAspectRatio="none"
|
||||||
|
fill="none"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M0 24 Q180 8 360 24 T720 24 T1080 24 T1440 24"
|
||||||
|
stroke="white"
|
||||||
|
stroke-width="1"
|
||||||
|
stroke-opacity="0.2"
|
||||||
|
stroke-dasharray="5 9"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
Copyright {new Date().getFullYear()}
|
Copyright {new Date().getFullYear()}
|
||||||
|
|
||||||
<a href="https://leomurca.xyz" target="_blank" rel="noreferrer"
|
<a href="https://leomurca.xyz" target="_blank" rel="noreferrer"
|
||||||
|
|
@ -69,11 +146,31 @@
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
footer {
|
footer {
|
||||||
background-color: var(--color-primary);
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.footer-main {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: var(--color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-decoration {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-decoration__svg {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
opacity: 0.95;
|
||||||
|
}
|
||||||
|
|
||||||
#content-container {
|
#content-container {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
width: 85%;
|
width: 85%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
@ -154,12 +251,30 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.credits-container {
|
.credits-container {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
background-color: var(--color-secondary);
|
background-color: var(--color-secondary);
|
||||||
color: white;
|
color: white;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 20px 30px;
|
padding: 20px 30px;
|
||||||
padding-left: 9%;
|
padding-left: 9%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.credits-decoration {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 48px;
|
||||||
|
pointer-events: none;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.credits-decoration svg {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.credits-container a {
|
.credits-container a {
|
||||||
|
|
|
||||||
15
src/lib/translations/en-US/error.json
Normal file
15
src/lib/translations/en-US/error.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"seo.title": "Page not found — Embroidery Viewer",
|
||||||
|
"seo.description": "The page you are looking for could not be found.",
|
||||||
|
"seo.keywords": "404, page not found, embroidery viewer",
|
||||||
|
"seo.url": "https://embroideryviewer.xyz",
|
||||||
|
"notFound.code": "404",
|
||||||
|
"notFound.title": "This stitch went off pattern",
|
||||||
|
"notFound.description": "The page you are looking for may have been moved, removed, or never existed. Let's get you back to previewing embroidery designs.",
|
||||||
|
"notFound.home": "Back to home",
|
||||||
|
"notFound.viewer": "Open the viewer",
|
||||||
|
"notFound.imageAlt": "Embroidery design preview on screen",
|
||||||
|
"generic.title": "Something went wrong",
|
||||||
|
"generic.description": "We hit a snag while loading this page. Please try again or return to the home page.",
|
||||||
|
"generic.home": "Back to home"
|
||||||
|
}
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
},
|
},
|
||||||
"supportedFormats": {
|
"supportedFormats": {
|
||||||
"summary": "What embroidery file formats are supported?",
|
"summary": "What embroidery file formats are supported?",
|
||||||
"description": "Embroidery Viewer supports popular formats such as PES, DST, and EXP. This allows you to preview most embroidery designs used by home and commercial machines."
|
"description": "Embroidery Viewer supports PES, DST, JEF, EXP, and PEC — the most common formats for home and commercial embroidery machines."
|
||||||
},
|
},
|
||||||
"needSoftware": {
|
"needSoftware": {
|
||||||
"summary": "Do I need to install any embroidery software?",
|
"summary": "Do I need to install any embroidery software?",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,12 @@
|
||||||
{
|
{
|
||||||
"seo.title": "Free Online Embroidery File Viewer - Fast, Private & No Signup",
|
"seo.title": "Free Online Embroidery File Viewer — Fast, Private & No Signup",
|
||||||
"seo.description": "Upload and preview embroidery files instantly with Embroidery Viewer. Supports DST, PES, JEF, EXP, VP3 and more. No installs, no uploads – 100% browser-based and free.",
|
"seo.description": "Preview embroidery files instantly in your browser with Embroidery Viewer. Supports PES, DST, JEF, EXP, and PEC. No install, no signup — free and private.",
|
||||||
"seo.keywords": "embroidery viewer, online embroidery viewer, embroidery file preview, DST viewer, PES viewer, free embroidery tool, JEF viewer, EXP embroidery, VP3 embroidery viewer, embroidery preview tool, browser embroidery renderer, convert embroidery to PNG",
|
"seo.keywords": "embroidery viewer, online embroidery viewer, embroidery file preview, DST viewer, PES viewer, free embroidery tool, JEF viewer, EXP embroidery, embroidery preview tool, browser embroidery renderer",
|
||||||
"seo.url": "https://embroideryviewer.xyz"
|
"seo.url": "https://embroideryviewer.xyz",
|
||||||
|
"seo.image": "https://embroideryviewer.xyz/og/viewer.png",
|
||||||
|
"howTo.title": "How to preview embroidery files online",
|
||||||
|
"howTo.step1": "Open Embroidery Viewer in your web browser.",
|
||||||
|
"howTo.step2": "Go to the online viewer page.",
|
||||||
|
"howTo.step3": "Drag and drop your embroidery file (PES, DST, JEF, EXP, or PEC).",
|
||||||
|
"howTo.step4": "Preview your design instantly — no software installation required."
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -247,6 +247,16 @@ const config = {
|
||||||
key: 'announcement',
|
key: 'announcement',
|
||||||
loader: async () => (await import('./en-US/announcement.json')).default,
|
loader: async () => (await import('./en-US/announcement.json')).default,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
locale: SUPPORTED_LOCALES.PT_BR,
|
||||||
|
key: 'error',
|
||||||
|
loader: async () => (await import('./pt-BR/error.json')).default,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
locale: SUPPORTED_LOCALES.EN_US,
|
||||||
|
key: 'error',
|
||||||
|
loader: async () => (await import('./en-US/error.json')).default,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
15
src/lib/translations/pt-BR/error.json
Normal file
15
src/lib/translations/pt-BR/error.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"seo.title": "Página não encontrada — Embroidery Viewer",
|
||||||
|
"seo.description": "A página que você procura não foi encontrada.",
|
||||||
|
"seo.keywords": "404, página não encontrada, visualizador de bordado",
|
||||||
|
"seo.url": "https://embroideryviewer.xyz",
|
||||||
|
"notFound.code": "404",
|
||||||
|
"notFound.title": "Este ponto saiu do desenho",
|
||||||
|
"notFound.description": "A página pode ter sido movida, removida ou nunca existiu. Vamos voltar para visualizar seus bordados.",
|
||||||
|
"notFound.home": "Voltar ao início",
|
||||||
|
"notFound.viewer": "Abrir o visualizador",
|
||||||
|
"notFound.imageAlt": "Prévia de desenho de bordado na tela",
|
||||||
|
"generic.title": "Algo deu errado",
|
||||||
|
"generic.description": "Encontramos um problema ao carregar esta página. Tente novamente ou volte ao início.",
|
||||||
|
"generic.home": "Voltar ao início"
|
||||||
|
}
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
},
|
},
|
||||||
"supportedFormats": {
|
"supportedFormats": {
|
||||||
"summary": "Quais formatos de arquivos de bordado são suportados?",
|
"summary": "Quais formatos de arquivos de bordado são suportados?",
|
||||||
"description": "O Embroidery Viewer suporta formatos populares como PES, DST e EXP. Isso permite visualizar a maioria dos designs de bordado usados em máquinas domésticas e industriais."
|
"description": "O Embroidery Viewer suporta PES, DST, JEF, EXP e PEC — os formatos mais usados em máquinas de bordado domésticas e comerciais."
|
||||||
},
|
},
|
||||||
"needSoftware": {
|
"needSoftware": {
|
||||||
"summary": "Preciso instalar algum software de bordado?",
|
"summary": "Preciso instalar algum software de bordado?",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,12 @@
|
||||||
{
|
{
|
||||||
"seo.title": "Visualizador de Bordado Online Grátis - Rápido, Privado e Sem Cadastro",
|
"seo.title": "Visualizador de Bordado Online Grátis — Rápido, Privado e Sem Cadastro",
|
||||||
"seo.description": "Envie e visualize arquivos de bordado instantaneamente com o Embroidery Viewer. Compatível com DST, PES, JEF, EXP, VP3 e mais. Sem instalações, sem uploads – 100% no navegador e gratuito.",
|
"seo.description": "Visualize arquivos de bordado instantaneamente no navegador com o Embroidery Viewer. Compatível com PES, DST, JEF, EXP e PEC. Sem instalação, sem cadastro — gratuito e privado.",
|
||||||
"seo.keywords": "visualizador de bordado, visualizador online de bordado, visualizar arquivos de bordado, visualizar DST, visualizar PES, ferramenta gratuita de bordado, visualizador JEF, bordado EXP, visualizador VP3, pré-visualização de bordado, renderizador de bordado no navegador, converter bordado em PNG",
|
"seo.keywords": "visualizador de bordado, visualizador online de bordado, visualizar arquivos de bordado, visualizar DST, visualizar PES, ferramenta gratuita de bordado, visualizador JEF, bordado EXP, pré-visualização de bordado, renderizador de bordado no navegador",
|
||||||
"seo.url": "https://embroideryviewer.xyz"
|
"seo.url": "https://embroideryviewer.xyz",
|
||||||
|
"seo.image": "https://embroideryviewer.xyz/og/viewer.png",
|
||||||
|
"howTo.title": "Como visualizar arquivos de bordado online",
|
||||||
|
"howTo.step1": "Abra o Embroidery Viewer no seu navegador.",
|
||||||
|
"howTo.step2": "Acesse a página do visualizador online.",
|
||||||
|
"howTo.step3": "Arraste e solte seu arquivo de bordado (PES, DST, JEF, EXP ou PEC).",
|
||||||
|
"howTo.step4": "Visualize o design na hora — sem instalar nenhum software."
|
||||||
}
|
}
|
||||||
|
|
|
||||||
283
src/routes/+error.svelte
Normal file
283
src/routes/+error.svelte
Normal file
|
|
@ -0,0 +1,283 @@
|
||||||
|
<script>
|
||||||
|
import { resolve } from '$app/paths';
|
||||||
|
import { PUBLIC_IMAGE_BASE_URL } from '$env/static/public';
|
||||||
|
import { t } from '$lib/translations';
|
||||||
|
import { isMobile } from '$lib/utils/isMobile';
|
||||||
|
|
||||||
|
import Head from '$lib/components/Head.svelte';
|
||||||
|
|
||||||
|
/** @type {{ status: number }} */
|
||||||
|
let { status } = $props();
|
||||||
|
|
||||||
|
const isNotFound = $derived(status === 404);
|
||||||
|
|
||||||
|
const embroideryImage = isMobile()
|
||||||
|
? `${PUBLIC_IMAGE_BASE_URL}/t/f_webp,w_480/embroidery-viewer/hero-mobile.webp`
|
||||||
|
: `${PUBLIC_IMAGE_BASE_URL}/t/f_webp,w_640/embroidery-viewer/viewer-screenshot.webp`;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Head
|
||||||
|
title="error.seo.title"
|
||||||
|
description="error.seo.description"
|
||||||
|
keywords="error.seo.keywords"
|
||||||
|
url="error.seo.url"
|
||||||
|
shouldBeIndexed={false}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<section class="error-page" aria-labelledby="error-heading">
|
||||||
|
<div class="thread-bg" aria-hidden="true"></div>
|
||||||
|
|
||||||
|
<div class="error-card" class:single-column={!isNotFound}>
|
||||||
|
<div class="copy">
|
||||||
|
<p class="code">{isNotFound ? $t('error.notFound.code') : status}</p>
|
||||||
|
<h1 id="error-heading">
|
||||||
|
{isNotFound ? $t('error.notFound.title') : $t('error.generic.title')}
|
||||||
|
</h1>
|
||||||
|
<p class="description">
|
||||||
|
{isNotFound
|
||||||
|
? $t('error.notFound.description')
|
||||||
|
: $t('error.generic.description')}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="actions">
|
||||||
|
<a class="organic-btn" href={resolve('/')}>
|
||||||
|
{isNotFound ? $t('error.notFound.home') : $t('error.generic.home')}
|
||||||
|
</a>
|
||||||
|
{#if isNotFound}
|
||||||
|
<a class="organic-btn-secondary outline" href={resolve('/viewer')}>
|
||||||
|
{$t('error.notFound.viewer')}
|
||||||
|
</a>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if isNotFound}
|
||||||
|
<div class="visual">
|
||||||
|
<div class="hoop" aria-hidden="true">
|
||||||
|
<div class="hoop-inner">
|
||||||
|
<img
|
||||||
|
src={embroideryImage}
|
||||||
|
width="640"
|
||||||
|
height="480"
|
||||||
|
alt={$t('error.notFound.imageAlt')}
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="needle" aria-hidden="true"></div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.error-page {
|
||||||
|
position: relative;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 120px 24px 80px;
|
||||||
|
overflow: hidden;
|
||||||
|
background:
|
||||||
|
radial-gradient(
|
||||||
|
circle at 15% 20%,
|
||||||
|
rgba(6, 52, 95, 0.08),
|
||||||
|
transparent 45%
|
||||||
|
),
|
||||||
|
radial-gradient(
|
||||||
|
circle at 85% 80%,
|
||||||
|
rgba(25, 71, 149, 0.1),
|
||||||
|
transparent 50%
|
||||||
|
),
|
||||||
|
linear-gradient(180deg, #f8fafb 0%, #eef3f8 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thread-bg {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.35;
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg width='600' height='600' viewBox='0 0 600 600' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' stroke='%2306345f' stroke-width='1.2' opacity='0.5'%3E%3Cpath d='M80 120 Q200 40 320 140 T520 100' stroke-dasharray='6 8'/%3E%3Cpath d='M60 380 Q180 300 300 400 T540 360' stroke-dasharray='4 10'/%3E%3Ccircle cx='300' cy='300' r='120' stroke-dasharray='3 6'/%3E%3C/g%3E%3C/svg%3E");
|
||||||
|
background-size: 520px;
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-card.single-column {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
max-width: 520px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-card.single-column .description {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-card.single-column .actions {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-card {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
width: min(100%, 1000px);
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 48px;
|
||||||
|
align-items: center;
|
||||||
|
padding: 48px;
|
||||||
|
background: rgba(255, 255, 255, 0.88);
|
||||||
|
border-radius: 32px 58% 42% 68% / 48% 38% 62% 52%;
|
||||||
|
box-shadow:
|
||||||
|
0 24px 48px rgba(6, 52, 95, 0.12),
|
||||||
|
0 0 0 1px rgba(6, 52, 95, 0.06);
|
||||||
|
backdrop-filter: blur(6px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.code {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0 0 8px;
|
||||||
|
font-size: clamp(3rem, 10vw, 4.5rem);
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1;
|
||||||
|
letter-spacing: -0.04em;
|
||||||
|
color: var(--color-primary);
|
||||||
|
background: linear-gradient(135deg, #06345f 0%, #194795 55%, #3d6eb5 100%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 0 0 16px;
|
||||||
|
font-size: clamp(1.5rem, 3vw, 2rem);
|
||||||
|
line-height: 1.25;
|
||||||
|
color: var(--color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 1.05rem;
|
||||||
|
line-height: 1.65;
|
||||||
|
color: #3a4a5c;
|
||||||
|
max-width: 38ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 14px;
|
||||||
|
margin-top: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions .organic-btn,
|
||||||
|
.actions .organic-btn-secondary {
|
||||||
|
font-size: 1rem;
|
||||||
|
padding: 16px 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.organic-btn-secondary.outline {
|
||||||
|
background: transparent;
|
||||||
|
color: var(--color-primary);
|
||||||
|
border: 2px solid var(--color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.organic-btn-secondary.outline:hover {
|
||||||
|
background: var(--color-primary);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.visual {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hoop {
|
||||||
|
position: relative;
|
||||||
|
width: min(100%, 340px);
|
||||||
|
aspect-ratio: 1;
|
||||||
|
border-radius: 50%;
|
||||||
|
padding: 14px;
|
||||||
|
background: linear-gradient(145deg, #c9a227 0%, #8b6914 40%, #d4af37 100%);
|
||||||
|
box-shadow:
|
||||||
|
inset 0 2px 4px rgba(255, 255, 255, 0.45),
|
||||||
|
inset 0 -4px 8px rgba(0, 0, 0, 0.2),
|
||||||
|
0 16px 32px rgba(6, 52, 95, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hoop-inner {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #f2f6f5;
|
||||||
|
border: 3px dashed rgba(6, 52, 95, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hoop-inner img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.needle {
|
||||||
|
position: absolute;
|
||||||
|
top: 8%;
|
||||||
|
right: 6%;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%2306345f' d='M8 40 L24 4 L28 8 L14 38 Z'/%3E%3Ccircle cx='8' cy='40' r='4' fill='%23194795'/%3E%3C/svg%3E");
|
||||||
|
background-size: contain;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
transform: rotate(12deg);
|
||||||
|
filter: drop-shadow(2px 4px 6px rgba(0, 0, 0, 0.15));
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 860px) {
|
||||||
|
.error-card {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
text-align: center;
|
||||||
|
padding: 36px 28px;
|
||||||
|
border-radius: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.visual {
|
||||||
|
order: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hoop {
|
||||||
|
width: min(280px, 80vw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.error-page {
|
||||||
|
padding-top: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions .organic-btn,
|
||||||
|
.actions .organic-btn-secondary {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,9 +1,107 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { PUBLIC_IMAGE_BASE_URL } from '$env/static/public';
|
||||||
|
import { t } from '$lib/translations';
|
||||||
|
|
||||||
import Head from '$lib/components/Head.svelte';
|
import Head from '$lib/components/Head.svelte';
|
||||||
|
import StructuredData from '$lib/components/StructuredData.svelte';
|
||||||
import Hero from '$lib/sections/Hero.svelte';
|
import Hero from '$lib/sections/Hero.svelte';
|
||||||
import Features from '$lib/sections/Features.svelte';
|
import Features from '$lib/sections/Features.svelte';
|
||||||
import Faq from '$lib/sections/Faq.svelte';
|
import Faq from '$lib/sections/Faq.svelte';
|
||||||
import MobileApp from '$lib/sections/MobileApp.svelte';
|
import MobileApp from '$lib/sections/MobileApp.svelte';
|
||||||
|
|
||||||
|
const baseUrl = 'https://embroideryviewer.xyz';
|
||||||
|
const viewerUrl = `${baseUrl}/viewer`;
|
||||||
|
const logoUrl = `${PUBLIC_IMAGE_BASE_URL}/t/f_webp/embroidery-viewer/logo-icon.webp`;
|
||||||
|
|
||||||
|
const faqKeys = [
|
||||||
|
'openPesOnline',
|
||||||
|
'supportedFormats',
|
||||||
|
'needSoftware',
|
||||||
|
'isSafe',
|
||||||
|
'multipleFiles',
|
||||||
|
'mobileSupport',
|
||||||
|
];
|
||||||
|
|
||||||
|
const howToSteps = ['step1', 'step2', 'step3', 'step4'];
|
||||||
|
|
||||||
|
$: structuredData = {
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@graph': [
|
||||||
|
{
|
||||||
|
'@type': 'WebSite',
|
||||||
|
'@id': `${baseUrl}/#website`,
|
||||||
|
url: baseUrl,
|
||||||
|
name: 'Embroidery Viewer',
|
||||||
|
description: $t('home.seo.description'),
|
||||||
|
inLanguage: ['en-US', 'pt-BR'],
|
||||||
|
publisher: { '@id': `${baseUrl}/#organization` },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'@type': 'Organization',
|
||||||
|
'@id': `${baseUrl}/#organization`,
|
||||||
|
name: 'Embroidery Viewer',
|
||||||
|
url: baseUrl,
|
||||||
|
logo: {
|
||||||
|
'@type': 'ImageObject',
|
||||||
|
url: logoUrl,
|
||||||
|
},
|
||||||
|
email: 'leo@leomurca.xyz',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'@type': 'WebPage',
|
||||||
|
'@id': `${baseUrl}/#webpage`,
|
||||||
|
url: baseUrl,
|
||||||
|
name: $t('home.seo.title'),
|
||||||
|
description: $t('home.seo.description'),
|
||||||
|
isPartOf: { '@id': `${baseUrl}/#website` },
|
||||||
|
about: { '@id': `${baseUrl}/#webapp` },
|
||||||
|
primaryImageOfPage: {
|
||||||
|
'@type': 'ImageObject',
|
||||||
|
url: $t('home.seo.image'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'@type': 'WebApplication',
|
||||||
|
'@id': `${baseUrl}/#webapp`,
|
||||||
|
name: 'Embroidery Viewer',
|
||||||
|
url: viewerUrl,
|
||||||
|
applicationCategory: 'DesignApplication',
|
||||||
|
operatingSystem: 'Any',
|
||||||
|
browserRequirements: 'Requires JavaScript. Requires HTML5.',
|
||||||
|
offers: {
|
||||||
|
'@type': 'Offer',
|
||||||
|
price: '0',
|
||||||
|
priceCurrency: 'USD',
|
||||||
|
},
|
||||||
|
description: $t('home.seo.description'),
|
||||||
|
featureList:
|
||||||
|
'PES, DST, JEF, EXP, PEC embroidery file preview; multiple files; browser-based',
|
||||||
|
screenshot: $t('home.seo.image'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'@type': 'FAQPage',
|
||||||
|
'@id': `${baseUrl}/#faq`,
|
||||||
|
mainEntity: faqKeys.map((key) => ({
|
||||||
|
'@type': 'Question',
|
||||||
|
name: $t(`faq.items.${key}.summary`),
|
||||||
|
acceptedAnswer: {
|
||||||
|
'@type': 'Answer',
|
||||||
|
text: $t(`faq.items.${key}.description`),
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'@type': 'HowTo',
|
||||||
|
'@id': `${baseUrl}/#howto`,
|
||||||
|
name: $t('home.howTo.title'),
|
||||||
|
step: howToSteps.map((step, i) => ({
|
||||||
|
'@type': 'HowToStep',
|
||||||
|
position: i + 1,
|
||||||
|
text: $t(`home.howTo.${step}`),
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Head
|
<Head
|
||||||
|
|
@ -11,8 +109,11 @@
|
||||||
description="home.seo.description"
|
description="home.seo.description"
|
||||||
keywords="home.seo.keywords"
|
keywords="home.seo.keywords"
|
||||||
url="home.seo.url"
|
url="home.seo.url"
|
||||||
|
ogImage="home.seo.image"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<StructuredData data={structuredData} />
|
||||||
|
|
||||||
<Hero />
|
<Hero />
|
||||||
<Features />
|
<Features />
|
||||||
<MobileApp />
|
<MobileApp />
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue