This commit is contained in:
alexandrev-tibco
2026-02-04 13:42:36 +01:00
parent 6b405419cf
commit 379f935fe7
16 changed files with 597 additions and 87 deletions
+273 -32
View File
@@ -662,7 +662,33 @@ p {
line-height: var(--line-height-relaxed);
}
.hero-actions {
.hero-features {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: var(--space-3);
margin-bottom: var(--space-8);
}
.feature-badge {
display: inline-flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-4);
border-radius: var(--radius-full);
background: rgba(88, 183, 122, 0.14);
color: #1f6b44;
font-size: var(--font-size-sm);
font-weight: var(--font-weight-medium);
}
[data-theme="dark"] .feature-badge {
background: rgba(114, 211, 154, 0.2);
color: #d6f4e5;
}
.hero-actions,
.hero-ctas {
display: flex;
flex-wrap: wrap;
align-items: center;
@@ -670,6 +696,106 @@ p {
gap: var(--space-4);
}
.app-store-badge img {
height: 56px;
width: auto;
box-shadow: var(--shadow-md);
border-radius: var(--radius-lg);
}
.app-store-badge {
display: inline-flex;
}
.cta-secondary {
padding: 0.75rem 1.6rem;
border-radius: var(--radius-md);
border: 2px solid var(--color-primary);
color: var(--color-primary);
font-weight: var(--font-weight-semibold);
transition: all var(--transition-base);
}
.cta-secondary:hover {
background: var(--color-primary);
color: #fff;
}
.hero-social-proof {
margin-top: var(--space-4);
font-size: var(--font-size-sm);
color: var(--color-text-tertiary);
}
.hero-content-split {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
gap: var(--space-12);
align-items: center;
text-align: left;
}
.hero-content-split .hero-app-icon {
margin-left: 0;
}
.hero-content-split .hero-description,
.hero-content-split .hero-features,
.hero-content-split .hero-ctas,
.hero-content-split .hero-social-proof {
justify-content: flex-start;
margin-left: 0;
margin-right: 0;
}
.hero-media {
display: flex;
justify-content: center;
align-items: center;
}
.hero-video-placeholder {
width: 100%;
max-width: 420px;
aspect-ratio: 9 / 16;
border-radius: var(--radius-2xl);
background: var(--color-bg-secondary);
border: 1px dashed var(--color-border-strong);
display: flex;
align-items: center;
justify-content: center;
color: var(--color-text-tertiary);
font-weight: var(--font-weight-semibold);
}
@media (max-width: 900px) {
.hero-content-split {
grid-template-columns: 1fr;
text-align: center;
}
.hero-content-split .hero-features,
.hero-content-split .hero-ctas,
.hero-content-split .hero-social-proof {
justify-content: center;
}
}
@media (max-width: 768px) {
.hero-features {
flex-direction: column;
align-items: center;
}
.hero-ctas {
flex-direction: column;
}
.app-store-badge img {
height: 50px;
}
}
.hero-app-icon {
width: 120px;
height: 120px;
@@ -690,6 +816,33 @@ p {
color: white;
}
.features-cta {
margin-top: var(--space-6);
}
.footer-appstore {
display: inline-flex;
margin-top: var(--space-4);
font-weight: var(--font-weight-semibold);
}
.hero-variant-a .hero-variant-b-only,
.hero-variant-b .hero-variant-a-only {
display: none;
}
.hero-variant-b-only {
display: none;
}
.hero-variant-b .hero-variant-b-only {
display: block;
}
.hero-variant-b .hero {
padding-top: calc(var(--nav-height) + var(--space-16));
}
/* ========================================
Features Section
======================================== */
@@ -923,67 +1076,59 @@ p {
}
/* ========================================
Testimonials Section
Early Adopters Section
======================================== */
.testimonials {
.early-adopters {
background: var(--color-bg-secondary);
}
.testimonials-header {
.early-adopters-header {
text-align: center;
max-width: 600px;
max-width: 620px;
margin: 0 auto var(--space-12);
}
.testimonials-grid {
.early-adopters-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--space-6);
margin-bottom: var(--space-10);
}
@media (max-width: 968px) {
.testimonials-grid {
.early-adopters-grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 640px) {
.testimonials-grid {
.early-adopters-grid {
grid-template-columns: 1fr;
}
}
.testimonial-card {
padding: var(--space-6);
.early-adopter-card {
padding: var(--space-8);
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius-xl);
text-align: left;
}
.testimonial-stars {
.early-adopter-icon {
font-size: 1.6rem;
display: inline-flex;
margin-bottom: var(--space-4);
}
.early-adopter-card h3 {
margin-bottom: var(--space-2);
}
.early-adopters-cta {
display: flex;
gap: var(--space-1);
margin-bottom: var(--space-4);
color: var(--color-warning);
}
.testimonial-stars svg {
width: 16px;
height: 16px;
fill: currentColor;
}
.testimonial-text {
font-size: var(--font-size-base);
color: var(--color-text);
margin-bottom: var(--space-4);
line-height: var(--line-height-relaxed);
}
.testimonial-author {
font-size: var(--font-size-sm);
color: var(--color-text-tertiary);
justify-content: center;
}
/* ========================================
@@ -1223,6 +1368,12 @@ p {
color: var(--color-text-tertiary);
}
.page-header-actions {
margin-top: var(--space-6);
display: flex;
justify-content: center;
}
/* ========================================
Content Styles (for policy pages)
======================================== */
@@ -1686,6 +1837,96 @@ p {
gap: var(--space-2);
}
/* ========================================
Exit Intent Modal + Sticky CTA
======================================== */
.modal {
display: none;
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.65);
align-items: center;
justify-content: center;
z-index: var(--z-modal);
padding: var(--space-6);
}
.modal.is-visible {
display: flex;
}
.modal-content {
background: var(--color-surface);
color: var(--color-text);
padding: var(--space-8);
border-radius: var(--radius-xl);
width: 100%;
max-width: 420px;
text-align: center;
position: relative;
box-shadow: var(--shadow-xl);
}
.modal-close {
position: absolute;
top: var(--space-3);
right: var(--space-3);
font-size: 1.4rem;
color: var(--color-text-tertiary);
}
.modal-close:hover {
color: var(--color-text);
}
.modal-cta {
display: inline-flex;
align-items: center;
justify-content: center;
background: var(--color-primary);
color: white;
padding: 0.75rem 1.8rem;
border-radius: var(--radius-md);
font-weight: var(--font-weight-semibold);
}
.modal-cta:hover {
background: var(--color-primary-hover);
color: white;
}
.sticky-cta {
position: fixed;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
z-index: var(--z-sticky);
display: none;
box-shadow: var(--shadow-lg);
border-radius: var(--radius-full);
}
.sticky-cta a {
display: block;
background: var(--color-primary);
color: white;
padding: 0.9rem 2rem;
border-radius: var(--radius-full);
font-weight: var(--font-weight-semibold);
}
.sticky-cta a:hover {
background: var(--color-primary-hover);
color: white;
}
@media (min-width: 769px) {
.sticky-cta {
display: none !important;
}
}
/* ========================================
Utilities
======================================== */
+9
View File
@@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" width="180" height="60" viewBox="0 0 180 60" role="img" aria-label="Download on the App Store">
<rect width="180" height="60" rx="10" fill="#000" />
<g fill="#fff">
<path d="M46.64 20.5c.9-1.09 1.52-2.62 1.35-4.14-1.31.05-2.88.86-3.8 1.96-.83.97-1.56 2.52-1.36 4 1.4.11 2.94-.74 3.81-1.82z"/>
<path d="M54.71 42.48c-1.01 1.5-2.08 2.98-3.72 3.01-1.63.03-2.15-.96-4.02-.96-1.87 0-2.44.93-3.98.99-1.6.06-2.8-1.61-3.83-3.08-2.2-3.22-3.88-9.28-1.62-13.23 1.06-1.88 2.96-3.08 5.02-3.11 1.57-.03 3.05 1.05 4.02 1.05.95 0 2.74-1.3 4.64-1.11.78.04 3 .3 4.4 2.45-.1.07-2.53 1.53-2.5 4.57.03 3.6 3.12 4.8 3.16 4.82-.03.09-.5 1.7-1.57 3.59z"/>
</g>
<text x="74" y="23" fill="#fff" font-family="-apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Arial, sans-serif" font-size="11">Download on the</text>
<text x="74" y="42" fill="#fff" font-family="-apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Arial, sans-serif" font-size="18" font-weight="700">App Store</text>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

+1 -1
View File
@@ -6,7 +6,7 @@ const CONFIG = {
APP_NAME: 'PorfolioJournal',
TAGLINE: 'Your personal portfolio, thoughtfully tracked.',
DESCRIPTION: 'A calm, offline-first iOS app for tracking your portfolio with monthly check-ins, reflections, and long-term insights.',
APP_STORE_URL: 'https://apps.apple.com/app/porfoliojournal/id000000000',
APP_STORE_URL: 'https://apps.apple.com/us/app/portfolio-journal/id6757678318?pt=123456&ct=homepage_other&mt=8',
SUPPORT_EMAIL: 'support@portfoliojournal.app',
COMPANY_NAME: 'PorfolioJournal',
WEBSITE_URL: 'https://portfoliojournal.app',
+179
View File
@@ -6,6 +6,12 @@
(function() {
'use strict';
function trackEvent(eventName, props) {
if (window.plausible) {
window.plausible(eventName, { props: props || {} });
}
}
// Dark Mode Management
const DarkMode = {
STORAGE_KEY: 'pj-theme',
@@ -163,6 +169,17 @@
}
};
const ImageOptimization = {
init() {
document.querySelectorAll('img').forEach(img => {
if (img.closest('.hero')) return;
if (!img.hasAttribute('loading')) {
img.setAttribute('loading', 'lazy');
}
});
}
};
// Smooth Scroll
const SmoothScroll = {
init() {
@@ -182,6 +199,160 @@
}
};
// A/B Test: Hero Variants
const HeroABTest = {
STORAGE_KEY: 'pj-hero-variant',
init() {
if (!document.querySelector('.hero-variant-a-only, .hero-variant-b-only')) {
return;
}
let variant = 'a';
try {
variant = localStorage.getItem(this.STORAGE_KEY);
if (!variant) {
variant = Math.random() < 0.5 ? 'a' : 'b';
localStorage.setItem(this.STORAGE_KEY, variant);
}
} catch (err) {
variant = 'a';
}
document.body.classList.remove('hero-variant-a', 'hero-variant-b');
document.body.classList.add(`hero-variant-${variant}`);
trackEvent('AB Test', { variant });
}
};
// Analytics Events
const Analytics = {
init() {
this.trackAppStoreClicks();
this.trackScrollDepth();
this.trackFooterLinks();
},
trackAppStoreClicks() {
document.querySelectorAll('a[href*="apps.apple.com"]').forEach(link => {
link.addEventListener('click', () => {
let campaign = 'unknown';
try {
const url = new URL(link.href);
campaign = url.searchParams.get('ct') || 'unknown';
} catch (err) {
campaign = 'unknown';
}
trackEvent('AppStore Click', { location: campaign });
});
});
},
trackScrollDepth() {
const scrollDepths = [25, 50, 75, 100];
const tracked = new Set();
window.addEventListener('scroll', () => {
const scrollPercent = ((window.scrollY + window.innerHeight) / document.body.offsetHeight) * 100;
scrollDepths.forEach(depth => {
if (scrollPercent >= depth && !tracked.has(depth)) {
tracked.add(depth);
trackEvent('Deep Scroll', { depth: `${depth}%` });
}
});
});
},
trackFooterLinks() {
document.querySelectorAll('footer a').forEach(link => {
link.addEventListener('click', () => {
const destination = link.textContent.trim() || link.getAttribute('href');
trackEvent('Footer Link Click', { destination });
});
});
}
};
const ExitIntent = {
STORAGE_KEY: 'pj-exit-intent-shown',
init() {
this.modal = document.getElementById('exit-intent-modal');
if (!this.modal) return;
const closeBtn = this.modal.querySelector('[data-exit-close]');
if (closeBtn) {
closeBtn.addEventListener('click', () => this.close());
}
this.modal.addEventListener('click', (event) => {
if (event.target === this.modal) {
this.close();
}
});
document.addEventListener('mouseleave', (event) => {
if (event.clientY < 0) {
this.show();
}
});
},
show() {
try {
if (localStorage.getItem(this.STORAGE_KEY)) return;
} catch (err) {
return;
}
this.modal.classList.add('is-visible');
this.modal.setAttribute('aria-hidden', 'false');
try {
localStorage.setItem(this.STORAGE_KEY, 'true');
} catch (err) {
// ignore storage errors
}
trackEvent('Exit Intent', { action: 'shown' });
},
close() {
this.modal.classList.remove('is-visible');
this.modal.setAttribute('aria-hidden', 'true');
trackEvent('Exit Intent', { action: 'closed' });
}
};
const StickyCTA = {
init() {
this.el = document.getElementById('sticky-mobile-cta');
if (!this.el) return;
window.addEventListener('scroll', () => this.update());
this.update();
},
update() {
const scrollPercent = ((window.scrollY + window.innerHeight) / document.body.offsetHeight) * 100;
const isMobile = window.innerWidth <= 768;
const shouldShow = isMobile && scrollPercent > 50;
this.el.style.display = shouldShow ? 'block' : 'none';
this.el.setAttribute('aria-hidden', shouldShow ? 'false' : 'true');
}
};
const CTAActions = {
init() {
document.querySelectorAll('[data-cta="learn-more"]').forEach(button => {
button.addEventListener('click', () => {
const target = document.querySelector('.features-section');
if (target) {
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
trackEvent('CTA Click', { action: 'learn_more' });
}
});
});
}
};
// Cookie Notice (only if analytics enabled)
const CookieNotice = {
STORAGE_KEY: 'pj-cookies-accepted',
@@ -230,6 +401,7 @@
init() {
document.querySelectorAll('.faq-question').forEach(question => {
question.addEventListener('click', () => {
trackEvent('FAQ Click', { question: question.textContent.trim() });
const item = question.parentElement;
const isOpen = item.classList.contains('open');
@@ -263,9 +435,15 @@
DarkMode.updateToggleButton();
Navigation.init();
Content.init();
ImageOptimization.init();
SmoothScroll.init();
HeroABTest.init();
Analytics.init();
FAQ.init();
CookieNotice.init();
ExitIntent.init();
StickyCTA.init();
CTAActions.init();
// Setup theme toggle button
const themeToggle = document.querySelector('.theme-toggle');
@@ -277,4 +455,5 @@
// Expose necessary functions globally
window.DarkMode = DarkMode;
window.CookieNotice = CookieNotice;
window.trackEvent = trackEvent;
})();