Version 3.0.0 Redesign #34

Merged
leomurca merged 20 commits from redesign_all into main 2026-04-24 15:14:30 +00:00
18 changed files with 278 additions and 289 deletions
Showing only changes of commit 6354336610 - Show all commits

View file

@ -1,86 +1,17 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<style>
:root {
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 24px;
font-weight: 400;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
* {
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
flex-direction: column;
margin: 0;
width: 100%;
height: 100%;
}
#app {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
background-color: #f2f6f5;
z-index: 10;
}
input[type='submit'] {
width: 100%;
font-size: 20px;
margin-top: 20px;
background-color: #05345f;
font-weight: 700;
color: white;
padding: 10px;
-webkit-appearance: none;
border-radius: 0;
}
input[type='submit']:hover {
cursor: pointer;
background-color: black;
color: white;
}
body a {
text-decoration: none;
color: #06345f;
border-bottom: 3px solid #06345f;
}
body a:hover {
background-color: #06345f;
color: #ffffff;
}
:is(h1, h2, h3, h4, h5, h6) {
color: #06345f;
}
strong {
color: #06345f;
}
ul li::marker {
color: #06345f;
}
</style>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" /> <link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&display=swap"
rel="stylesheet"
/>
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" /> <link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="shortcut icon" href="/favicon.ico" /> <link rel="shortcut icon" href="/favicon.ico" />

View file

@ -96,12 +96,13 @@
<style> <style>
header { header {
position: absolute;
top: 0;
z-index: 2;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 10px 100px; padding: 10px 300px 10px 100px;
background-color: #f8f9fa;
border-bottom: 1px solid #ddd;
width: 100%; width: 100%;
} }

View file

@ -0,0 +1,115 @@
<script>
import { resolve } from '$app/paths';
import { PUBLIC_IMAGE_BASE_URL } from '$env/static/public';
import { isMobile } from '$lib/utils/isMobile';
const backgroundImage = isMobile()
? `${PUBLIC_IMAGE_BASE_URL}/t/f_webp/embroidery-viewer/hero-mobile.webp`
: `${PUBLIC_IMAGE_BASE_URL}/t/f_webp,w_1920,h_1080/embroidery-viewer/hero.webp`;
</script>
<section
id="hero"
style={`background: url(${backgroundImage}) center/cover no-repeat`}
>
<div class="overlay">
<h1>Preview your embroidery designs instantly — no software needed</h1>
<p>Fast, private & no signup required</p>
<a class="organic-btn" href={resolve('/viewer')}>Try Your Design</a>
</div>
</section>
<style>
#hero {
position: relative;
z-index: 0;
min-height: 100vh;
display: flex;
}
.overlay {
display: flex;
flex-direction: column;
max-width: 800px;
z-index: 1;
padding-left: 100px;
padding-top: 130px;
}
h1 {
font-size: clamp(3.5rem, 4vw, 3.5rem);
font-weight: 700;
margin-bottom: 1rem;
line-height: 1.2;
}
p {
font-size: 1.5rem;
margin-bottom: 2rem;
}
.organic-btn {
background: var(--color-primary);
width: fit-content;
color: white;
border: none;
padding: 20px 60px;
font-size: 16px;
cursor: pointer;
border-radius: 58% 42% 65% 27% / 40% 60% 60% 70%;
border: 1px solid var(--color-primary);
transition: all 0.3s ease;
}
.organic-btn:hover {
color: var(--color-primary);
background-color: #ffffff;
border: 1px solid var(--color-primary);
}
@media (max-width: 1350px) {
h1 {
font-size: clamp(3.3rem, 4vw, 3.3rem);
}
}
@media (max-width: 1280px) {
h1 {
font-size: clamp(3rem, 4vw, 3rem);
}
p {
font-size: 1.1rem;
}
}
@media (max-width: 1180px) {
h1 {
font-size: clamp(3rem, 4vw, 3rem);
}
}
@media (max-width: 768px) {
h1 {
font-size: clamp(2rem, 4vw, 2rem);
}
p {
margin-top: 0;
}
#hero {
background-size: contain !important;
background-position: bottom !important;
}
.overlay {
width: 100%;
padding-top: 100px;
padding-left: 0;
height: 100vh;
padding-left: 20px;
padding-right: 20px;
}
}
</style>

47
src/lib/styles/fonts.css Normal file
View file

@ -0,0 +1,47 @@
@font-face {
font-family: 'Merienda';
font-display: swap;
src:
url('/fonts/merienda.regular.woff2') format('woff2'),
url('/fonts/merienda.regular.woff') format('woff');
font-weight: 400;
font-style: normal;
font-display: swap;
font-optical-sizing: auto;
}
@font-face {
font-family: 'Merienda';
font-display: swap;
src:
url('/fonts/merienda.medium.woff2') format('woff2'),
url('/fonts/merienda.medium.woff') format('woff');
font-weight: 500;
font-style: normal;
font-display: swap;
font-optical-sizing: auto;
}
@font-face {
font-family: 'Merienda';
font-display: swap;
src:
url('/fonts/merienda.semi-bold.woff2') format('woff2'),
url('/fonts/merienda.semi-bold.woff') format('woff');
font-weight: 600;
font-style: normal;
font-display: swap;
font-optical-sizing: auto;
}
@font-face {
font-family: 'Merienda';
font-display: swap;
src:
url('/fonts/merienda.bold.woff2') format('woff2'),
url('/fonts/merienda.bold.woff') format('woff');
font-weight: 700;
font-style: normal;
font-display: swap;
font-optical-sizing: auto;
}

74
src/lib/styles/global.css Normal file
View file

@ -0,0 +1,74 @@
:root {
font-family: 'Merienda', cursive;
font-size: 16px;
line-height: 24px;
font-weight: 400;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
* {
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
flex-direction: column;
margin: 0;
width: 100%;
height: 100%;
}
#app {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
background-color: #f2f6f5;
z-index: 10;
}
input[type='submit'] {
width: 100%;
font-size: 20px;
margin-top: 20px;
background-color: #05345f;
font-weight: 700;
color: white;
padding: 10px;
-webkit-appearance: none;
border-radius: 0;
}
input[type='submit']:hover {
cursor: pointer;
background-color: black;
color: white;
}
body a {
text-decoration: none;
color: #06345f;
border-bottom: 3px solid #06345f;
}
body a:hover {
background-color: #06345f;
color: #ffffff;
}
:is(h1, h2, h3, h4, h5, h6) {
color: #06345f;
}
strong {
color: #06345f;
}
ul li::marker {
color: #06345f;
}

View file

@ -0,0 +1,5 @@
:root {
--color-primary: #06345f;
--font-base: 'Merienda';
}

View file

@ -0,0 +1,9 @@
import { browser } from '$app/environment';
export const isMobile = () => {
if (browser) {
return window.matchMedia('only screen and (max-width: 768px)').matches;
} else {
return null;
}
};

View file

@ -1,4 +1,8 @@
<script> <script>
import '$lib/styles/fonts.css';
import '$lib/styles/variables.css';
import '$lib/styles/global.css';
import { browser } from '$app/environment'; import { browser } from '$app/environment';
import { onMount } from 'svelte'; import { onMount } from 'svelte';

View file

@ -1,85 +1,22 @@
<script> <script>
// @ts-nocheck // @ts-nocheck
import { applyAction, enhance } from '$app/forms'; import { t } from '$lib/translations';
import { invalidateAll } from '$app/navigation';
import { t, locale, SUPPORTED_LOCALES } from '$lib/translations';
import { resolve } from '$app/paths'; import { resolve } from '$app/paths';
import Seo from '$lib/components/Seo.svelte'; import Seo from '$lib/components/Seo.svelte';
import appScreenshot from '$lib/assets/app-with-frame.png'; import Hero from '$lib/sections/Hero.svelte';
import appScreenshotPt from '$lib/assets/app-with-frame-pt.png';
let { data } = $props(); let { data } = $props();
/**
* @type {{ textColor: String; message: String; } | null}
*/
let feedbackMessage = $state(null);
/**
* @type {boolean}
*/
let loading = $state(false);
// svelte-ignore state_referenced_locally // svelte-ignore state_referenced_locally
const metadata = data.metadata; const metadata = data.metadata;
const resetFeedback = () => {
if (feedbackMessage) feedbackMessage = null
}
</script> </script>
<Seo {...metadata} /> <Seo {...metadata} />
<!-- eslint-disable svelte/no-at-html-tags --> <!-- eslint-disable svelte/no-at-html-tags -->
<div class="beta-section"> <Hero />
<div class="beta-content">
<div class="beta-image">
<img src={$locale === SUPPORTED_LOCALES.EN_US ? appScreenshot : appScreenshotPt} alt="Embroidery Viewer App Screenshot" />
</div>
<div class="beta-text">
<h1>{$t("home.banner.title")}</h1>
<p class="lead">
{@html $t('home.banner.subtitle')}
</p>
<p>
{$t('home.banner.description')}
</p>
<form
action="/"
method="POST"
class="beta-form"
use:enhance={() => {
loading = true;
return async ({ result }) => {
loading = false;
feedbackMessage = result.data;
if (result.type === 'success') await invalidateAll();
applyAction(result);
};
}}>
<label for="name">{$t("home.banner.name")}</label>
<input type="text" name="name" id="name" oninput={resetFeedback} required />
<label for="email">{$t("home.banner.email")}</label>
<input type="email" name="email" id="email" oninput={resetFeedback} required />
<button type="submit">{$t(loading ? 'home.banner.cta.loading' : 'home.banner.cta') }</button>
{#if feedbackMessage !== null}
<p style="margin-top: 1rem; color: {feedbackMessage.textColor}">
{$t(feedbackMessage.message)}
</p>
{/if}
</form>
</div>
</div>
</div>
<div class="home-container"> <div class="home-container">
<section aria-labelledby="main-title"> <section aria-labelledby="main-title">
@ -106,7 +43,7 @@
<h2 id="donation-title">{$t('home.donation.title')}</h2> <h2 id="donation-title">{$t('home.donation.title')}</h2>
{@html $t('home.donation.description')} {@html $t('home.donation.description')}
<p> <p>
<a href={resolve("/donate")} class="button">{$t('home.donation.cta')}</a> <a href={resolve('/donate')} class="button">{$t('home.donation.cta')}</a>
{$t('home.donation.cta.description')} {$t('home.donation.cta.description')}
</p> </p>
</section> </section>
@ -115,57 +52,13 @@
<section aria-labelledby="cta-title"> <section aria-labelledby="cta-title">
<h2 id="cta-title">{$t('home.cta.title')}</h2> <h2 id="cta-title">{$t('home.cta.title')}</h2>
<p> <p>
<a href={resolve("/viewer")} class="button">{$t('home.cta.cta')}</a> <a href={resolve('/viewer')} class="button">{$t('home.cta.cta')}</a>
{@html $t('home.cta.cta.description')} {@html $t('home.cta.cta.description')}
</p> </p>
</section> </section>
</div> </div>
<style> <style>
.beta-form {
background: white;
color: #000;
padding: 1.5rem;
border-radius: 10px;
max-width: 400px;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
}
.beta-form label {
display: block;
margin-top: 1rem;
font-weight: bold;
}
.beta-form input {
width: 100%;
padding: 0.6rem;
margin-top: 0.3rem;
border: 1px solid #ccc;
border-radius: 6px;
}
.beta-form button {
margin-top: 1.5rem;
width: 100%;
background-color: #05345f;
color: white;
border: none;
padding: 0.8rem;
font-size: 1rem;
border-radius: 6px;
cursor: pointer;
}
.beta-form button:disabled {
background-color: #7aa3c1;
cursor: wait;
}
.beta-form button:hover:enabled {
background-color: #042b4f;
}
.home-container { .home-container {
margin: 0 auto; margin: 0 auto;
width: 70%; width: 70%;
@ -177,97 +70,4 @@
width: 90%; width: 90%;
} }
} }
.beta-section {
background-color: #05345f;
color: white;
padding: 3rem 1rem;
display: flex;
justify-content: center;
}
.beta-content {
display: flex;
flex-wrap: wrap;
gap: 2rem;
max-width: 1000px;
align-items: center;
width: 100%;
}
.beta-image img {
max-width: 300px;
border-radius: 1rem;
}
.beta-text {
flex: 1;
min-width: 280px;
}
.beta-text h1 {
font-size: 2rem;
margin-bottom: 0.5rem;
color: white;
}
.beta-text .lead {
font-size: 1.2rem;
margin-bottom: 1rem;
font-weight: 500;
}
.beta-text p {
margin-bottom: 1rem;
line-height: 1.5;
}
.beta-form {
background: white;
color: #000;
padding: 1.5rem;
border-radius: 10px;
max-width: 400px;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
}
.beta-form label {
display: block;
margin-top: 1rem;
font-weight: bold;
}
.beta-form input {
width: 100%;
padding: 0.6rem;
margin-top: 0.3rem;
border: 1px solid #ccc;
border-radius: 6px;
}
.beta-form button {
margin-top: 1.5rem;
width: 100%;
background-color: #05345f;
color: white;
border: none;
padding: 0.8rem;
font-size: 1rem;
border-radius: 6px;
cursor: pointer;
}
.beta-form button:hover {
background-color: #042b4f;
}
@media (max-width: 768px) {
.beta-content {
flex-direction: column;
align-items: center;
}
.beta-form {
margin: 0 auto;
}
}
</style> </style>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -17,6 +17,9 @@ const config = {
prerender: { prerender: {
origin: 'https://embroideryviewer.xyz', origin: 'https://embroideryviewer.xyz',
}, },
env: {
publicPrefix: 'PUBLIC_',
},
}; };
export default config; export default config;