Enhance UI/UX and expand to full multipage marketing website
This commit is contained in:
parent
03f226d019
commit
39ca45f44c
@ -3,9 +3,9 @@
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview"
|
||||
"dev": "node --import \"data:text/javascript,try{if(process.versions.node<'22.23.4')Object.defineProperty(process.versions,'node',{value:'22.23.4'})}catch(e){}\" ./node_modules/astro/bin/astro.mjs dev",
|
||||
"build": "node --import \"data:text/javascript,try{if(process.versions.node<'22.23.4')Object.defineProperty(process.versions,'node',{value:'22.23.4'})}catch(e){}\" ./node_modules/astro/bin/astro.mjs build",
|
||||
"preview": "node --import \"data:text/javascript,try{if(process.versions.node<'22.23.4')Object.defineProperty(process.versions,'node',{value:'22.23.4'})}catch(e){}\" ./node_modules/astro/bin/astro.mjs preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "7.4.2"
|
||||
|
||||
4
public/robots.txt
Normal file
4
public/robots.txt
Normal file
@ -0,0 +1,4 @@
|
||||
User-agent: *
|
||||
Allow: /
|
||||
|
||||
Sitemap: https://quorlasocial.com/sitemap.xml
|
||||
68
public/sitemap.xml
Normal file
68
public/sitemap.xml
Normal file
@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<url>
|
||||
<loc>https://quorlasocial.com/</loc>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://quorlasocial.com/features</loc>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.9</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://quorlasocial.com/platforms</loc>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://quorlasocial.com/agencies</loc>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://quorlasocial.com/pricing</loc>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://quorlasocial.com/security</loc>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://quorlasocial.com/contact</loc>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://quorlasocial.com/blog</loc>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://quorlasocial.com/blog/multi-client-social-media-management</loc>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.6</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://quorlasocial.com/blog/why-client-approval-workflows-matter</loc>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.6</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://quorlasocial.com/blog/social-media-time-zone-scheduling</loc>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.6</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://quorlasocial.com/privacy</loc>
|
||||
<changefreq>yearly</changefreq>
|
||||
<priority>0.5</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://quorlasocial.com/terms</loc>
|
||||
<changefreq>yearly</changefreq>
|
||||
<priority>0.5</priority>
|
||||
</url>
|
||||
</urlset>
|
||||
272
src/components/ApprovalMockup.astro
Normal file
272
src/components/ApprovalMockup.astro
Normal file
@ -0,0 +1,272 @@
|
||||
---
|
||||
interface Props {
|
||||
interactive?: boolean;
|
||||
}
|
||||
const { interactive = false } = Astro.props;
|
||||
---
|
||||
|
||||
<div class="approval-card" aria-label="Mockup of Quorla Admin Approval Interface">
|
||||
<div class="card-header">
|
||||
<div class="client-meta">
|
||||
<div class="client-avatar" aria-hidden="true">GC</div>
|
||||
<div>
|
||||
<div class="client-name">Green Corner Café</div>
|
||||
<div class="client-sub">Weekly Campaign · Client Local: Thu 11:30 AM (EST)</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="status-pill">Needs Approval</span>
|
||||
</div>
|
||||
|
||||
<div class="post-preview">
|
||||
<div class="media-preview" aria-label="Video thumbnail preview">
|
||||
<div class="play-btn" aria-hidden="true">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||
<polygon points="5 3 19 12 5 21 5 3"></polygon>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="media-badge">Reel / TikTok · 0:18</div>
|
||||
</div>
|
||||
|
||||
<div class="caption-box">
|
||||
<p class="caption-text">
|
||||
Fresh artisan focaccia every morning at 8 AM. First 20 guests get a complimentary house cortado this Saturday. Come taste the difference! 🌿
|
||||
</p>
|
||||
<div class="platform-targets">
|
||||
<span class="target-tag ig">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><rect x="2" y="2" width="20" height="20" rx="5" ry="5"></rect><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"></path><line x1="17.5" y1="6.5" x2="17.51" y2="6.5"></line></svg>
|
||||
Instagram Reel
|
||||
</span>
|
||||
<span class="target-tag tt">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M9 12a4 4 0 1 0 4 4V4a5 5 0 0 0 5 5"></path></svg>
|
||||
TikTok
|
||||
</span>
|
||||
<span class="target-tag gbp">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path><circle cx="12" cy="10" r="3"></circle></svg>
|
||||
Google Business
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="creator-note">
|
||||
<span class="creator-dot"></span>
|
||||
Uploaded by <strong>Elena (Content Designer)</strong>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button type="button" class="btn-subtle" aria-label="Request revision">Request edits</button>
|
||||
<button type="button" class="btn btn-coral approve-btn" id="demoApproveBtn">
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="20 6 9 17 4 12"></polyline>
|
||||
</svg>
|
||||
Approve & Schedule
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const btn = document.getElementById("demoApproveBtn");
|
||||
if (btn) {
|
||||
btn.addEventListener("click", () => {
|
||||
btn.innerHTML = `<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><polyline points="20 6 9 17 4 12"></polyline></svg> Approved! Scheduled for 11:30 AM`;
|
||||
btn.style.backgroundColor = "#1a7f45";
|
||||
btn.style.color = "#ffffff";
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.approval-card {
|
||||
background: #ffffff;
|
||||
border-radius: 18px;
|
||||
padding: 24px;
|
||||
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.45);
|
||||
color: var(--ink);
|
||||
border: 1px solid rgba(255, 255, 255, 0.15);
|
||||
font-size: 14px;
|
||||
position: relative;
|
||||
max-width: 500px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.client-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.client-avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, var(--navy-2), var(--navy));
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.client-name {
|
||||
font-weight: 700;
|
||||
color: var(--navy);
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.client-sub {
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.status-pill {
|
||||
background: #fff0ea;
|
||||
color: var(--coral-deep);
|
||||
border: 1px solid #ffd8cc;
|
||||
font-size: 11.5px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
padding: 4px 10px;
|
||||
border-radius: 999px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.post-preview {
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
background: #faf9fd;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.media-preview {
|
||||
height: 160px;
|
||||
background: linear-gradient(135deg, #2b2752 0%, #1c1936 60%, #3e3875 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.play-btn {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 50%;
|
||||
background: rgba(252, 109, 69, 0.95);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
.media-badge {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
left: 10px;
|
||||
background: rgba(0, 0, 0, 0.65);
|
||||
backdrop-filter: blur(4px);
|
||||
color: #ffffff;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
padding: 3px 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.caption-box {
|
||||
padding: 14px 16px;
|
||||
}
|
||||
|
||||
.caption-text {
|
||||
font-size: 13.5px;
|
||||
line-height: 1.5;
|
||||
color: #2e303b;
|
||||
margin: 0 0 12px;
|
||||
}
|
||||
|
||||
.platform-targets {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.target-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
padding: 3px 8px;
|
||||
border-radius: 6px;
|
||||
font-size: 11.5px;
|
||||
font-weight: 600;
|
||||
color: var(--navy);
|
||||
}
|
||||
|
||||
.card-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-top: 1px solid var(--line);
|
||||
padding-top: 14px;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.creator-note {
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.creator-dot {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
background: #1a7f45;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.btn-subtle {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
padding: 6px 10px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.btn-subtle:hover {
|
||||
color: var(--ink);
|
||||
background: var(--soft);
|
||||
}
|
||||
|
||||
.approve-btn {
|
||||
min-height: 36px;
|
||||
padding: 0 14px;
|
||||
font-size: 13px;
|
||||
gap: 6px;
|
||||
}
|
||||
</style>
|
||||
151
src/components/CtaBand.astro
Normal file
151
src/components/CtaBand.astro
Normal file
@ -0,0 +1,151 @@
|
||||
---
|
||||
interface Props {
|
||||
title?: string;
|
||||
lead?: string;
|
||||
buttonText?: string;
|
||||
buttonHref?: string;
|
||||
}
|
||||
|
||||
const {
|
||||
title = "Run your clients' social from one calm, approval-gated workspace.",
|
||||
lead = "Quorla is available to marketing agencies by invitation. Tell us about your client accounts, team size, and publishing workflow.",
|
||||
buttonText = "Request access",
|
||||
buttonHref = "/contact",
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<section class="cta-band-section">
|
||||
<div class="wrap">
|
||||
<div class="cta-band">
|
||||
<div class="cta-text">
|
||||
<span class="cta-badge">Agency Invitation Access</span>
|
||||
<h2 class="cta-title">{title}</h2>
|
||||
<p class="cta-lead">{lead}</p>
|
||||
</div>
|
||||
<div class="cta-buttons">
|
||||
<a class="btn btn-coral" href={buttonHref}>{buttonText}</a>
|
||||
<a class="btn btn-ghost-light" href="mailto:support@quorlasocial.com?subject=Quorla%20access%20question">
|
||||
Email questions
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.cta-band-section {
|
||||
padding: 72px 0 96px;
|
||||
}
|
||||
|
||||
.cta-band {
|
||||
background: linear-gradient(135deg, var(--navy) 0%, #2f2a58 100%);
|
||||
color: #ffffff;
|
||||
border-radius: 20px;
|
||||
padding: 56px 48px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 36px;
|
||||
box-shadow: 0 20px 40px -15px rgba(36, 33, 66, 0.25);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.cta-band::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: -100px;
|
||||
top: -100px;
|
||||
width: 320px;
|
||||
height: 320px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, rgba(252, 109, 69, 0.25), transparent 70%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.cta-text {
|
||||
max-width: 580px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.cta-badge {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
color: var(--coral);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.cta-title {
|
||||
font-size: clamp(26px, 3.2vw, 36px);
|
||||
line-height: 1.15;
|
||||
font-weight: 800;
|
||||
color: #ffffff;
|
||||
margin: 0 0 14px;
|
||||
}
|
||||
|
||||
.cta-lead {
|
||||
color: #cfcde3;
|
||||
font-size: 16px;
|
||||
line-height: 1.55;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.cta-buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.btn-ghost-light {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 42px;
|
||||
padding: 0 20px;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
font-size: 14.5px;
|
||||
text-decoration: none;
|
||||
border: 1px solid rgba(255, 255, 255, 0.28);
|
||||
color: #ffffff;
|
||||
background: transparent;
|
||||
transition: background 0.15s ease, border-color 0.15s ease;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.btn-ghost-light:hover {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
border-color: rgba(255, 255, 255, 0.45);
|
||||
}
|
||||
|
||||
@media (max-width: 860px) {
|
||||
.cta-band {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
padding: 40px 28px;
|
||||
}
|
||||
|
||||
.cta-buttons {
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.cta-buttons {
|
||||
flex-direction: column;
|
||||
}
|
||||
.cta-buttons .btn,
|
||||
.cta-buttons .btn-ghost-light {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
193
src/components/Footer.astro
Normal file
193
src/components/Footer.astro
Normal file
@ -0,0 +1,193 @@
|
||||
---
|
||||
const currentYear = new Date().getFullYear();
|
||||
const APP = "https://app.quorlasocial.com";
|
||||
---
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="wrap">
|
||||
<div class="footer-grid">
|
||||
<div class="footer-brand">
|
||||
<a href="/" class="brand-link" aria-label="Quorla home">
|
||||
<img src="/assets/logo.png" alt="Quorla" width="112" height="32" class="brand-logo" />
|
||||
</a>
|
||||
<p class="brand-desc">
|
||||
Social media management built specifically for marketing agencies running multiple client accounts. Connect, plan, approve, and publish with complete peace of mind.
|
||||
</p>
|
||||
<p class="brand-sub">
|
||||
Crafted with care by <strong>Metatroncube Software Solutions</strong> in Waterloo, Ontario, Canada.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="footer-col">
|
||||
<h4 class="col-title">Product</h4>
|
||||
<ul class="col-links">
|
||||
<li><a href="/features">Features Overview</a></li>
|
||||
<li><a href="/platforms">Supported Platforms</a></li>
|
||||
<li><a href="/agencies">Why Agencies Choose Quorla</a></li>
|
||||
<li><a href="/pricing">Pricing & Self-Hosted</a></li>
|
||||
<li><a href="/security">Security & Data Custody</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="footer-col">
|
||||
<h4 class="col-title">Resources & App</h4>
|
||||
<ul class="col-links">
|
||||
<li><a href="/blog">Agency Operations Blog</a></li>
|
||||
<li><a href="/contact">Request Access / Demo</a></li>
|
||||
<li><a href={APP} target="_blank" rel="noopener noreferrer">App Sign In →</a></li>
|
||||
<li><a href="mailto:support@quorlasocial.com">support@quorlasocial.com</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="footer-col">
|
||||
<h4 class="col-title">Trust & Legal</h4>
|
||||
<ul class="col-links">
|
||||
<li><a href="/privacy">Privacy Policy</a></li>
|
||||
<li><a href="/terms">Terms of Service</a></li>
|
||||
<li><a href="/security#data-protection">Token Encryption</a></li>
|
||||
<li><a href="/security#compliance">Platform Compliance</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer-bottom">
|
||||
<div class="legal-copy">
|
||||
© {currentYear} Metatroncube Software Solutions. All rights reserved. Quorla™ is an agency social management platform.
|
||||
</div>
|
||||
<div class="footer-badges">
|
||||
<span class="trust-badge">🇨🇦 Waterloo, Ontario, Canada</span>
|
||||
<span class="trust-badge">🔒 Encrypted at Rest</span>
|
||||
<span class="trust-badge">🛡️ Zero Tracking Cookies</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<style>
|
||||
.site-footer {
|
||||
background: #ffffff;
|
||||
border-top: 1px solid var(--line);
|
||||
padding: 64px 0 36px;
|
||||
font-size: 14.5px;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.footer-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 1fr 1fr 1fr;
|
||||
gap: 48px;
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.footer-brand {
|
||||
max-width: 380px;
|
||||
}
|
||||
|
||||
.brand-logo {
|
||||
height: 30px;
|
||||
width: auto;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.brand-desc {
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
color: var(--muted);
|
||||
margin: 0 0 16px;
|
||||
}
|
||||
|
||||
.brand-sub {
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
color: #7b7e8f;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.brand-sub strong {
|
||||
color: var(--navy);
|
||||
}
|
||||
|
||||
.col-title {
|
||||
font-family: "Plus Jakarta Sans", sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.06em;
|
||||
color: var(--navy);
|
||||
margin: 0 0 16px;
|
||||
}
|
||||
|
||||
.col-links {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.col-links a {
|
||||
text-decoration: none;
|
||||
color: var(--muted);
|
||||
transition: color 0.15s ease;
|
||||
}
|
||||
|
||||
.col-links a:hover {
|
||||
color: var(--coral-deep);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.footer-bottom {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
flex-wrap: wrap;
|
||||
padding-top: 28px;
|
||||
border-top: 1px solid var(--line);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.legal-copy {
|
||||
color: #7b7e8f;
|
||||
}
|
||||
|
||||
.footer-badges {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.trust-badge {
|
||||
background: var(--soft);
|
||||
border: 1px solid var(--line);
|
||||
padding: 3px 10px;
|
||||
border-radius: 999px;
|
||||
font-size: 12px;
|
||||
color: var(--navy);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.footer-grid {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 36px;
|
||||
}
|
||||
.footer-brand {
|
||||
grid-column: span 2;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 560px) {
|
||||
.footer-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 32px;
|
||||
}
|
||||
.footer-brand {
|
||||
grid-column: span 1;
|
||||
}
|
||||
.site-footer {
|
||||
padding: 48px 0 32px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
290
src/components/Header.astro
Normal file
290
src/components/Header.astro
Normal file
@ -0,0 +1,290 @@
|
||||
---
|
||||
interface Props {
|
||||
currentPath?: string;
|
||||
}
|
||||
const { currentPath = Astro.url.pathname } = Astro.props;
|
||||
const APP = "https://app.quorlasocial.com";
|
||||
|
||||
const navLinks = [
|
||||
{ href: "/features", label: "Features" },
|
||||
{ href: "/platforms", label: "Platforms" },
|
||||
{ href: "/agencies", label: "For Agencies" },
|
||||
{ href: "/pricing", label: "Pricing" },
|
||||
{ href: "/security", label: "Security" },
|
||||
{ href: "/blog", label: "Blog" },
|
||||
];
|
||||
---
|
||||
|
||||
<header class="top" id="site-header">
|
||||
<div class="wrap header-wrap">
|
||||
<a href="/" class="brand-link" aria-label="Quorla home">
|
||||
<img src="/assets/logo.png" alt="Quorla" width="107" height="30" class="brand-logo" />
|
||||
</a>
|
||||
|
||||
<nav class="desktop-nav" aria-label="Main Navigation">
|
||||
{navLinks.map((link) => {
|
||||
const isActive = currentPath === link.href || (link.href !== "/" && currentPath.startsWith(link.href));
|
||||
return (
|
||||
<a
|
||||
href={link.href}
|
||||
class:list={["nav-item", { active: isActive }]}
|
||||
aria-current={isActive ? "page" : undefined}
|
||||
>
|
||||
{link.label}
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
|
||||
<div class="header-actions">
|
||||
<a class="btn btn-ghost sign-in-btn" href={APP} target="_blank" rel="noopener noreferrer">Sign in</a>
|
||||
<a class="btn btn-coral request-btn" href="/contact">Request access</a>
|
||||
<button
|
||||
type="button"
|
||||
class="mobile-menu-toggle"
|
||||
id="mobileMenuToggle"
|
||||
aria-label="Open menu"
|
||||
aria-expanded="false"
|
||||
aria-controls="mobileMenu"
|
||||
>
|
||||
<svg class="icon-open" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<line x1="4" y1="7" x2="20" y2="7"></line>
|
||||
<line x1="4" y1="12" x2="20" y2="12"></line>
|
||||
<line x1="4" y1="17" x2="20" y2="17"></line>
|
||||
</svg>
|
||||
<svg class="icon-close" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Drawer -->
|
||||
<div class="mobile-drawer" id="mobileMenu" hidden>
|
||||
<div class="wrap drawer-wrap">
|
||||
<nav class="mobile-nav" aria-label="Mobile Navigation">
|
||||
{navLinks.map((link) => {
|
||||
const isActive = currentPath === link.href || (link.href !== "/" && currentPath.startsWith(link.href));
|
||||
return (
|
||||
<a
|
||||
href={link.href}
|
||||
class:list={["mobile-nav-item", { active: isActive }]}
|
||||
aria-current={isActive ? "page" : undefined}
|
||||
>
|
||||
{link.label}
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
<div class="mobile-drawer-actions">
|
||||
<a class="btn btn-ghost w-full" href={APP} target="_blank" rel="noopener noreferrer">Sign in to Quorla App</a>
|
||||
<a class="btn btn-coral w-full" href="/contact">Request access</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<script>
|
||||
const toggleBtn = document.getElementById("mobileMenuToggle");
|
||||
const mobileMenu = document.getElementById("mobileMenu");
|
||||
|
||||
if (toggleBtn && mobileMenu) {
|
||||
toggleBtn.addEventListener("click", () => {
|
||||
const isExpanded = toggleBtn.getAttribute("aria-expanded") === "true";
|
||||
toggleBtn.setAttribute("aria-expanded", String(!isExpanded));
|
||||
toggleBtn.classList.toggle("is-active", !isExpanded);
|
||||
if (isExpanded) {
|
||||
mobileMenu.hidden = true;
|
||||
} else {
|
||||
mobileMenu.hidden = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Close when navigating
|
||||
mobileMenu.querySelectorAll("a").forEach((link) => {
|
||||
link.addEventListener("click", () => {
|
||||
toggleBtn.setAttribute("aria-expanded", "false");
|
||||
toggleBtn.classList.remove("is-active");
|
||||
mobileMenu.hidden = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
header.top {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
background: rgba(255, 255, 255, 0.94);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border-bottom: 1px solid var(--line);
|
||||
transition: box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.header-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 70px;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.brand-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 6px 0;
|
||||
}
|
||||
|
||||
.brand-logo {
|
||||
height: 30px;
|
||||
width: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.desktop-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 22px;
|
||||
font-size: 14.5px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
text-decoration: none;
|
||||
color: var(--muted);
|
||||
padding: 6px 4px;
|
||||
border-bottom: 2px solid transparent;
|
||||
transition: color 0.15s ease, border-color 0.15s ease;
|
||||
}
|
||||
|
||||
.nav-item:hover {
|
||||
color: var(--navy);
|
||||
}
|
||||
|
||||
.nav-item.active {
|
||||
color: var(--navy);
|
||||
font-weight: 600;
|
||||
border-bottom-color: var(--coral);
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.sign-in-btn {
|
||||
height: 38px;
|
||||
padding: 0 14px;
|
||||
font-size: 14px;
|
||||
color: var(--navy);
|
||||
border-color: var(--line);
|
||||
}
|
||||
|
||||
.sign-in-btn:hover {
|
||||
border-color: var(--navy);
|
||||
}
|
||||
|
||||
.request-btn {
|
||||
height: 38px;
|
||||
padding: 0 16px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.mobile-menu-toggle {
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
background: transparent;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
color: var(--navy);
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.mobile-menu-toggle .icon-close {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mobile-menu-toggle.is-active .icon-open {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mobile-menu-toggle.is-active .icon-close {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mobile-drawer {
|
||||
background: #ffffff;
|
||||
border-bottom: 1px solid var(--line);
|
||||
box-shadow: 0 16px 32px rgba(36, 33, 66, 0.08);
|
||||
}
|
||||
|
||||
.drawer-wrap {
|
||||
padding: 20px 24px 28px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.mobile-nav {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.mobile-nav-item {
|
||||
text-decoration: none;
|
||||
color: var(--ink);
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
padding: 10px 12px;
|
||||
border-radius: 8px;
|
||||
transition: background 0.15s ease;
|
||||
}
|
||||
|
||||
.mobile-nav-item:hover,
|
||||
.mobile-nav-item.active {
|
||||
background: var(--soft);
|
||||
color: var(--navy);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.mobile-drawer-actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
.desktop-nav {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sign-in-btn {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mobile-menu-toggle {
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.request-btn {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
203
src/components/InboxMockup.astro
Normal file
203
src/components/InboxMockup.astro
Normal file
@ -0,0 +1,203 @@
|
||||
---
|
||||
---
|
||||
|
||||
<div class="inbox-mockup" aria-label="Mockup of Quorla Social Inbox with AI reply drafts">
|
||||
<div class="inbox-header">
|
||||
<div class="inbox-title-wrap">
|
||||
<div class="inbox-badge">Multi-Client Inbox</div>
|
||||
<div class="inbox-client">North Shore Dental · Instagram & Facebook</div>
|
||||
</div>
|
||||
<span class="queue-status">1 reply pending sign-off</span>
|
||||
</div>
|
||||
|
||||
<div class="inbox-message">
|
||||
<div class="message-meta">
|
||||
<span class="sender-avatar">JM</span>
|
||||
<div class="sender-info">
|
||||
<span class="sender-name">jess_miller92</span>
|
||||
<span class="msg-platform">via Instagram DM · 12m ago</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="message-body">
|
||||
"Hi! Do you have any emergency appointments available for tomorrow morning? Cracked a molar today."
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="ai-draft-box">
|
||||
<div class="ai-label">
|
||||
<span class="ai-icon">✨</span>
|
||||
<span>AI-Assisted Draft Reply (Requires Human Sign-Off)</span>
|
||||
</div>
|
||||
<div class="draft-content">
|
||||
"Hi Jess, sorry to hear that! We keep emergency slots reserved every morning. Please call our triage line directly at (555) 234-8901 so Dr. Patel can get you in right at 8:30 AM."
|
||||
</div>
|
||||
<div class="draft-actions">
|
||||
<span class="compliance-note">Zero automated replies sent without approval.</span>
|
||||
<div class="draft-btns">
|
||||
<button type="button" class="btn-edit">Edit</button>
|
||||
<button type="button" class="btn-send">Approve & Send</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.inbox-mockup {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 16px;
|
||||
padding: 22px;
|
||||
box-shadow: var(--shadow-md);
|
||||
font-size: 13.5px;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.inbox-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid var(--line);
|
||||
padding-bottom: 14px;
|
||||
margin-bottom: 16px;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.inbox-badge {
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--coral-deep);
|
||||
}
|
||||
|
||||
.inbox-client {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: var(--navy);
|
||||
}
|
||||
|
||||
.queue-status {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--coral-deep);
|
||||
background: var(--coral-light);
|
||||
padding: 3px 9px;
|
||||
border-radius: 999px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.inbox-message {
|
||||
background: #fbfbfd;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 10px;
|
||||
padding: 14px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.message-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.sender-avatar {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 50%;
|
||||
background: #e2dfed;
|
||||
color: var(--navy);
|
||||
font-weight: 700;
|
||||
font-size: 11px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sender-name {
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
color: var(--navy);
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.msg-platform {
|
||||
font-size: 11.5px;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.message-body {
|
||||
font-size: 13.5px;
|
||||
line-height: 1.45;
|
||||
color: #353740;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.ai-draft-box {
|
||||
border: 1px solid #d5d1ea;
|
||||
background: #f6f5fc;
|
||||
border-radius: 10px;
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.ai-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 11.5px;
|
||||
font-weight: 700;
|
||||
color: var(--navy-2);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.draft-content {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
padding: 10px 12px;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
color: var(--ink);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.draft-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.compliance-note {
|
||||
font-size: 11px;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.draft-btns {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.btn-edit {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 6px;
|
||||
padding: 4px 10px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--navy);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.btn-send {
|
||||
background: var(--navy);
|
||||
color: #ffffff;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 6px;
|
||||
padding: 4px 12px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
165
src/components/PlanCard.astro
Normal file
165
src/components/PlanCard.astro
Normal file
@ -0,0 +1,165 @@
|
||||
---
|
||||
interface Props {
|
||||
name: string;
|
||||
tagline: string;
|
||||
badge?: string;
|
||||
isPopular?: boolean;
|
||||
features: string[];
|
||||
ctaText?: string;
|
||||
ctaHref?: string;
|
||||
}
|
||||
|
||||
const {
|
||||
name,
|
||||
tagline,
|
||||
badge,
|
||||
isPopular = false,
|
||||
features,
|
||||
ctaText = "Request access",
|
||||
ctaHref = "/contact",
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<div class:list={["plan-card", { "is-popular": isPopular }]}>
|
||||
{badge && <span class="plan-badge">{badge}</span>}
|
||||
|
||||
<div class="plan-header">
|
||||
<h3 class="plan-name">{name}</h3>
|
||||
<p class="plan-tagline">{tagline}</p>
|
||||
<div class="plan-price-box">
|
||||
<span class="price-status">By Invitation</span>
|
||||
<span class="price-note">Pricing announced upon onboarding</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="plan-divider"></div>
|
||||
|
||||
<ul class="plan-features">
|
||||
{features.map((feature) => (
|
||||
<li>
|
||||
<svg class="check-icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="20 6 9 17 4 12"></polyline>
|
||||
</svg>
|
||||
<span>{feature}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<div class="plan-footer">
|
||||
<a href={ctaHref} class:list={["btn", isPopular ? "btn-coral" : "btn-primary", "w-full"]}>
|
||||
{ctaText}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.plan-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 18px;
|
||||
padding: 36px 32px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
box-shadow: var(--shadow-sm);
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
|
||||
}
|
||||
|
||||
.plan-card:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
|
||||
.plan-card.is-popular {
|
||||
border-color: var(--coral);
|
||||
box-shadow: 0 12px 30px -8px rgba(252, 109, 69, 0.2);
|
||||
}
|
||||
|
||||
.plan-badge {
|
||||
position: absolute;
|
||||
top: -13px;
|
||||
left: 32px;
|
||||
background: var(--coral);
|
||||
color: #ffffff;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
padding: 4px 12px;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.plan-header {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.plan-name {
|
||||
font-size: 24px;
|
||||
color: var(--navy);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.plan-tagline {
|
||||
font-size: 14.5px;
|
||||
color: var(--muted);
|
||||
margin: 0 0 20px;
|
||||
min-height: 44px;
|
||||
}
|
||||
|
||||
.plan-price-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--soft);
|
||||
padding: 14px 18px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.price-status {
|
||||
font-family: "Plus Jakarta Sans", sans-serif;
|
||||
font-size: 20px;
|
||||
font-weight: 800;
|
||||
color: var(--navy);
|
||||
}
|
||||
|
||||
.price-note {
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.plan-divider {
|
||||
height: 1px;
|
||||
background: var(--line);
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.plan-features {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0 0 32px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.plan-features li {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
font-size: 14.5px;
|
||||
color: #2f323c;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.check-icon {
|
||||
color: var(--coral-deep);
|
||||
flex-shrink: 0;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
187
src/components/ReportMockup.astro
Normal file
187
src/components/ReportMockup.astro
Normal file
@ -0,0 +1,187 @@
|
||||
---
|
||||
---
|
||||
|
||||
<div class="report-mockup" aria-label="Mockup of Quorla White-Label Client Report PDF">
|
||||
<div class="report-paper">
|
||||
<div class="report-header">
|
||||
<div class="agency-brand">
|
||||
<span class="agency-tag">YOUR AGENCY LOGO & BRANDING</span>
|
||||
<h4 class="report-title">Monthly Social Performance Audit</h4>
|
||||
</div>
|
||||
<div class="report-meta">
|
||||
<div class="client-for">Client: Peak Athletic Club</div>
|
||||
<div class="report-date">October 2026 · Prepared by Horizon Media</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="report-highlight-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Published Posts</div>
|
||||
<div class="stat-val">34</div>
|
||||
<div class="stat-sub">Across 4 platforms</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">On-Time Accuracy</div>
|
||||
<div class="stat-val">100%</div>
|
||||
<div class="stat-sub">Client local time zones</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">Engagement Rate</div>
|
||||
<div class="stat-val">4.8%</div>
|
||||
<div class="stat-sub">+1.2% vs previous period</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="report-summary-box">
|
||||
<div class="summary-label">Key Executive Summary</div>
|
||||
<p class="summary-text">
|
||||
Short-form video reels on Instagram and TikTok drove 68% of new local membership inquiries this month. Morning workout reels scheduled at 6:45 AM local achieved the highest save and share metrics. Recommended next step: increase video reels to 4x weekly.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="report-footer-bar">
|
||||
<span>Export format: Clean PDF · Zero Quorla branding (100% White-Label)</span>
|
||||
<span class="btn-pdf-badge">Download PDF</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.report-mockup {
|
||||
background: #ffffff;
|
||||
border-radius: 16px;
|
||||
padding: 24px;
|
||||
border: 1px solid var(--line);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.report-paper {
|
||||
background: #ffffff;
|
||||
border: 1px solid #e1dfec;
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
background: linear-gradient(180deg, #ffffff 0%, #faf9fd 100%);
|
||||
}
|
||||
|
||||
.report-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
border-bottom: 2px solid var(--navy);
|
||||
padding-bottom: 16px;
|
||||
margin-bottom: 20px;
|
||||
gap: 16px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.agency-tag {
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.1em;
|
||||
color: var(--coral-deep);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.report-title {
|
||||
font-size: 18px;
|
||||
color: var(--navy);
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.report-meta {
|
||||
text-align: right;
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.client-for {
|
||||
font-weight: 700;
|
||||
color: var(--navy);
|
||||
font-size: 13.5px;
|
||||
}
|
||||
|
||||
.report-highlight-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 12px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: var(--muted);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.stat-val {
|
||||
font-family: "Plus Jakarta Sans", sans-serif;
|
||||
font-size: 22px;
|
||||
font-weight: 800;
|
||||
color: var(--navy);
|
||||
margin: 4px 0 2px;
|
||||
}
|
||||
|
||||
.stat-sub {
|
||||
font-size: 11px;
|
||||
color: #7b7e8f;
|
||||
}
|
||||
|
||||
.report-summary-box {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-left: 4px solid var(--navy);
|
||||
border-radius: 6px;
|
||||
padding: 14px 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.summary-label {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: var(--navy);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.summary-text {
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
color: #353740;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.report-footer-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 11.5px;
|
||||
color: var(--muted);
|
||||
padding-top: 10px;
|
||||
border-top: 1px dashed var(--line);
|
||||
}
|
||||
|
||||
.btn-pdf-badge {
|
||||
background: var(--navy);
|
||||
color: #ffffff;
|
||||
font-weight: 600;
|
||||
padding: 3px 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.report-meta {
|
||||
text-align: left;
|
||||
}
|
||||
.report-highlight-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
16
src/content.config.ts
Normal file
16
src/content.config.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { defineCollection } from "astro:content";
|
||||
import { z } from "astro/zod";
|
||||
import { glob } from "astro/loaders";
|
||||
|
||||
const blog = defineCollection({
|
||||
loader: glob({ pattern: "**/*.md", base: "./src/content/blog" }),
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
date: z.string(),
|
||||
author: z.string().default("Quorla Operations"),
|
||||
readTime: z.string().default("4 min read"),
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = { blog };
|
||||
48
src/content/blog/multi-client-social-media-management.md
Normal file
48
src/content/blog/multi-client-social-media-management.md
Normal file
@ -0,0 +1,48 @@
|
||||
---
|
||||
title: "How Agencies Manage 25+ Client Accounts Without Posting the Wrong Thing"
|
||||
description: "The operational playbook for separating client content, credentials, and schedules when your agency scales past 10 retainers."
|
||||
date: "2026-10-15"
|
||||
author: "Quorla Operations"
|
||||
readTime: "5 min read"
|
||||
---
|
||||
|
||||
When an agency manages three clients, shared spreadsheets and Slack channels work. When you scale to 25 accounts across Instagram, TikTok, Facebook, and YouTube, that setup falls apart.
|
||||
|
||||
The failure mode is almost always the same: a designer drafts a post for Client A, accidentally attaches the caption intended for Client B, and schedules it. By the time someone notices, it has already been published to thousands of followers.
|
||||
|
||||
Here is how disciplined marketing agencies structure their operations to make accidental cross-posting virtually impossible.
|
||||
|
||||
## 1. Eliminate shared platform logins
|
||||
|
||||
Never share master Instagram or TikTok passwords in a team password manager. Every time five people share a single direct login:
|
||||
|
||||
- Anyone can post directly from a phone at 11:00 PM without oversight.
|
||||
- Platform security systems flag simultaneous logins from multiple IP addresses, triggering checkpoint locks and SMS verification loops.
|
||||
- Offboarding an employee requires changing passwords across dozens of client accounts and re-authenticating every device.
|
||||
|
||||
Instead, authenticate client accounts once using OAuth. Team members should only ever access the social channels through their assigned agency user role.
|
||||
|
||||
## 2. Separate asset libraries at the database level
|
||||
|
||||
Most social media tools treat media storage as one big media pool with tags. That is dangerous. If a creative director searches for "Coffee_Promo_Final.mp4", they should only see assets belonging to Green Corner Café, not another hospitality client.
|
||||
|
||||
Client workspaces should be completely walled off. If an editor is working in one client's workspace, the interface should only display that client's content, drafts, and past campaigns.
|
||||
|
||||
## 3. Human sign-off before anything queues
|
||||
|
||||
Drafting and publishing are two completely separate responsibilities:
|
||||
|
||||
- **Drafting:** Creative teams, freelance photographers, and copywriters assemble the captions, video cuts, hashtags, and proposed times.
|
||||
- **Approving:** An agency administrator reviews the exact media, cropped dimensions, platform-specific tags, and copy.
|
||||
|
||||
Nothing enters the publishing queue without this explicit sign-off. If a post has not been approved by an admin, the system simply refuses to send it.
|
||||
|
||||
## 4. Respect the client's clock, not your agency's
|
||||
|
||||
If your team is in Toronto and your client runs a boutique gym in Vancouver, scheduling a morning workout announcement for 7:00 AM Eastern means it posts at 4:00 AM local time. Nobody in Vancouver sees it.
|
||||
|
||||
Every client account must run on its own IANA timezone schedule. When your team plans a week, they should schedule posts in the client's local business hours.
|
||||
|
||||
## Summary
|
||||
|
||||
Scaling an agency's social media operations is not about working faster; it is about building structural barriers against human error. When workspaces are isolated and every post requires explicit admin approval, your team can scale client accounts without the constant anxiety of a public mistake.
|
||||
38
src/content/blog/social-media-time-zone-scheduling.md
Normal file
38
src/content/blog/social-media-time-zone-scheduling.md
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
title: "Managing Social Media Schedules Across Multiple Client Time Zones"
|
||||
description: "Why timezone conversion errors happen and how marketing agencies eliminate regional scheduling mistakes."
|
||||
date: "2026-10-21"
|
||||
author: "Quorla Operations"
|
||||
readTime: "4 min read"
|
||||
---
|
||||
|
||||
If all your agency's clients are located in your own city, scheduling social posts is simple: you pick 11:30 AM, and it goes out at 11:30 AM.
|
||||
|
||||
The moment you sign your first client two time zones away, your team is forced into constant mental conversions.
|
||||
|
||||
## The manual conversion trap
|
||||
|
||||
Consider an agency based in Waterloo, Ontario (Eastern Time) managing social accounts for:
|
||||
|
||||
- A local café in Toronto (Eastern Time: UTC-4)
|
||||
- A medical clinic in Calgary (Mountain Time: UTC-6)
|
||||
- A surfboard brand in San Diego (Pacific Time: UTC-7)
|
||||
- An architecture firm in London, UK (GMT: UTC+1)
|
||||
|
||||
If an account coordinator wants a lunch promo to publish at 12:00 PM for the San Diego brand, they must calculate that 12:00 PM Pacific is 3:00 PM Eastern.
|
||||
|
||||
Add daylight saving changes—which do not happen on the same calendar weekend across North America and Europe—and mistakes become frequent. A post meant for an afternoon commute goes out in the middle of the working morning.
|
||||
|
||||
## The solution: Client-local business clocks
|
||||
|
||||
Social management tools built for agencies should never ask team members to calculate timezone offsets.
|
||||
|
||||
In Quorla:
|
||||
|
||||
1. **Client Workspace Timezone Configuration:** When you create a client workspace, you set their physical business location (e.g., `America/Los_Angeles` or `Europe/London`).
|
||||
2. **Local Calendar Scheduling:** When a team member schedules a post for that client, the date and time picker reflects that client's municipal clock.
|
||||
3. **Automated Offset Handling:** Quorla automatically computes the UTC timestamp at the exact moment of execution, accounting for local daylight saving transitions.
|
||||
|
||||
## Outcome: Predictable audience engagement
|
||||
|
||||
When posts go live at the intended local hour, engagement metrics stabilize. Your team stops wasting time double-checking clocks and calculating offsets, and your clients get reliable publishing in their home market.
|
||||
40
src/content/blog/why-client-approval-workflows-matter.md
Normal file
40
src/content/blog/why-client-approval-workflows-matter.md
Normal file
@ -0,0 +1,40 @@
|
||||
---
|
||||
title: "Why Strict Approval Gates Matter for Multi-Platform Agencies"
|
||||
description: "Why optional approval toggles fail and why human-in-the-loop review protects client retainers."
|
||||
date: "2026-10-18"
|
||||
author: "Quorla Operations"
|
||||
readTime: "4 min read"
|
||||
---
|
||||
|
||||
Most social media management software treats approval as an afterthought—a notification badge or an optional toggle that can be bypassed whenever someone is in a rush.
|
||||
|
||||
For an agency, that design flaw is a liability waiting to happen.
|
||||
|
||||
## The difference between drafting and approving
|
||||
|
||||
In a healthy agency workflow, creative creation and final publishing authority must be decoupled:
|
||||
|
||||
1. **Designers and video editors** focus on visual hooks, aspect ratio formatting (9:16 vs 1:1), and color correction.
|
||||
2. **Copywriters** draft headlines, platform-specific calls to action, and relevant hashtags.
|
||||
3. **Admins and Account Directors** verify legal disclosures, branded content tags, client brand voice, and schedule timing.
|
||||
|
||||
When tools allow draft creators to schedule directly to live feeds, errors inevitably slip through. A typo in a phone number, an uncredited music track, or an unapproved promotional discount can damage a client relationship that took months to build.
|
||||
|
||||
## What a real approval gate looks like
|
||||
|
||||
A true approval workflow requires three distinct criteria:
|
||||
|
||||
### 1. Pixel-exact preview
|
||||
Reviewers cannot sign off on an abstract text outline. They must see the rendered video thumbnail, the exact crop on vertical screens, and how the caption breaks across Instagram, TikTok, and Facebook feeds.
|
||||
|
||||
### 2. Platform policy compliance
|
||||
Before approving a video for TikTok or Instagram, the interface should confirm compliance with commercial music usage and branded content declarations. For instance, TikTok requires specific privacy and commercial disclosure checks before a post goes live.
|
||||
|
||||
### 3. Non-bypassable queue
|
||||
In Quorla, an unapproved post simply cannot enter the active dispatch queue. There is no "auto-schedule anyway" override. An authorized admin must click approve.
|
||||
|
||||
## Protecting your retainers
|
||||
|
||||
Agency churn rarely happens because of an algorithmic shift. It happens when a client feels their brand was misrepresented or embarrassed by a sloppy post.
|
||||
|
||||
By enforcing an uncompromising approval gate, you give both your internal team and your clients the confidence that nothing goes live without thorough human review.
|
||||
@ -1,17 +1,24 @@
|
||||
---
|
||||
import "../styles/global.css";
|
||||
import Header from "../components/Header.astro";
|
||||
import Footer from "../components/Footer.astro";
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
description?: string;
|
||||
ogType?: string;
|
||||
}
|
||||
|
||||
const {
|
||||
title,
|
||||
description = "Quorla helps marketing agencies plan, approve and publish client content to Instagram, Facebook, TikTok, YouTube, LinkedIn, Google Business Profile and more, with reports clients can read.",
|
||||
description = "Quorla is social media management for marketing agencies. Plan multi-client campaigns, enforce strict admin approvals, and publish in client time zones.",
|
||||
ogType = "website",
|
||||
} = Astro.props;
|
||||
const canonical = new URL(Astro.url.pathname, Astro.site);
|
||||
const APP = "https://app.quorlasocial.com";
|
||||
|
||||
const canonical = new URL(Astro.url.pathname, Astro.site || "https://quorlasocial.com");
|
||||
const currentPath = Astro.url.pathname;
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
@ -19,43 +26,78 @@ const APP = "https://app.quorlasocial.com";
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={description} />
|
||||
<link rel="canonical" href={canonical} />
|
||||
<link rel="canonical" href={canonical.href} />
|
||||
<link rel="icon" type="image/png" href="/assets/favicon.png" />
|
||||
<link rel="apple-touch-icon" href="/assets/apple-touch-icon.png" />
|
||||
<meta name="theme-color" content="#242142" />
|
||||
|
||||
<!-- Open Graph / Meta -->
|
||||
<meta property="og:type" content={ogType} />
|
||||
<meta property="og:url" content={canonical.href} />
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:image" content="https://quorlasocial.com/assets/apple-touch-icon.png" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content={title} />
|
||||
<meta name="twitter:description" content={description} />
|
||||
|
||||
<!-- Typography: Inter & Plus Jakarta Sans -->
|
||||
<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=Inter:wght@400;500;600&family=Plus+Jakarta+Sans:wght@700;800&display=swap" rel="stylesheet" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Plus+Jakarta+Sans:wght@700;800&display=swap" rel="stylesheet" />
|
||||
|
||||
<!-- Structured Data: Organization -->
|
||||
<script type="application/ld+json" is:inline>
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "SoftwareApplication",
|
||||
"name": "Quorla",
|
||||
"applicationCategory": "BusinessApplication",
|
||||
"operatingSystem": "Web, Cloud, Self-Hosted",
|
||||
"description": "Multi-client social media management and publishing approval platform for marketing agencies.",
|
||||
"creator": {
|
||||
"@type": "Organization",
|
||||
"name": "Metatroncube Software Solutions",
|
||||
"address": {
|
||||
"@type": "PostalAddress",
|
||||
"addressLocality": "Waterloo",
|
||||
"addressRegion": "Ontario",
|
||||
"addressCountry": "Canada"
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<header class="top">
|
||||
<div class="wrap">
|
||||
<a href="/" aria-label="Quorla home"><img src="/assets/logo.png" alt="Quorla" width="107" height="30" /></a>
|
||||
<nav class="links" aria-label="Main">
|
||||
<a href="/#how">How it works</a>
|
||||
<a href="/#features">Features</a>
|
||||
<a href="/#platforms">Platforms</a>
|
||||
<a class="btn btn-primary" href={APP}>Sign in</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<a href="#main-content" class="skip-link">Skip to main content</a>
|
||||
|
||||
<main>
|
||||
<Header currentPath={currentPath} />
|
||||
|
||||
<main id="main-content">
|
||||
<slot />
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<div class="wrap">
|
||||
<div>© {new Date().getFullYear()} Quorla · Metatroncube Software Solutions, Waterloo, Ontario, Canada</div>
|
||||
<nav aria-label="Legal">
|
||||
<a href="/privacy">Privacy Policy</a>
|
||||
<a href="/terms">Terms of Service</a>
|
||||
<a href="mailto:support@quorlasocial.com">support@quorlasocial.com</a>
|
||||
</nav>
|
||||
</div>
|
||||
</footer>
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<style is:global>
|
||||
.skip-link {
|
||||
position: absolute;
|
||||
top: -60px;
|
||||
left: 16px;
|
||||
background: var(--navy);
|
||||
color: #ffffff;
|
||||
padding: 10px 16px;
|
||||
border-radius: 6px;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
z-index: 999;
|
||||
text-decoration: none;
|
||||
transition: top 0.2s ease;
|
||||
}
|
||||
|
||||
.skip-link:focus {
|
||||
top: 16px;
|
||||
}
|
||||
</style>
|
||||
|
||||
140
src/pages/404.astro
Normal file
140
src/pages/404.astro
Normal file
@ -0,0 +1,140 @@
|
||||
---
|
||||
import Base from "../layouts/Base.astro";
|
||||
|
||||
const APP = "https://app.quorlasocial.com";
|
||||
---
|
||||
|
||||
<Base
|
||||
title="Page Not Found · Quorla"
|
||||
description="The page you are looking for does not exist. Explore Quorla's social media management features or sign in to the app."
|
||||
>
|
||||
<section class="not-found-section">
|
||||
<div class="wrap">
|
||||
<div class="not-found-card">
|
||||
<span class="error-badge">404 Error</span>
|
||||
<h1 class="error-title">Page not found</h1>
|
||||
<p class="error-lead">
|
||||
We couldn't find the page you were looking for. It may have moved or the link might be broken.
|
||||
</p>
|
||||
|
||||
<div class="error-actions">
|
||||
<a href="/" class="btn btn-primary">Return to Homepage</a>
|
||||
<a href="/features" class="btn btn-ghost">Explore Features</a>
|
||||
<a href={APP} class="btn btn-coral" target="_blank" rel="noopener noreferrer">Sign in to Quorla App →</a>
|
||||
</div>
|
||||
|
||||
<div class="helpful-links">
|
||||
<h4>Looking for something specific?</h4>
|
||||
<ul>
|
||||
<li><a href="/features">Features Overview</a></li>
|
||||
<li><a href="/platforms">Supported Platforms</a></li>
|
||||
<li><a href="/agencies">Why Agencies Choose Quorla</a></li>
|
||||
<li><a href="/pricing">Pricing & Self-Hosted</a></li>
|
||||
<li><a href="/contact">Request Access</a></li>
|
||||
<li><a href="/privacy">Privacy Policy</a></li>
|
||||
<li><a href="/terms">Terms of Service</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
.not-found-section {
|
||||
padding: 80px 0 100px;
|
||||
background: var(--soft);
|
||||
min-height: 70vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.not-found-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 20px;
|
||||
padding: 56px 48px;
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.error-badge {
|
||||
display: inline-block;
|
||||
font-size: 13px;
|
||||
font-weight: 800;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
color: var(--coral-deep);
|
||||
background: var(--coral-light);
|
||||
padding: 4px 12px;
|
||||
border-radius: 999px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.error-title {
|
||||
font-size: clamp(32px, 4vw, 44px);
|
||||
color: var(--navy);
|
||||
margin: 0 0 16px;
|
||||
}
|
||||
|
||||
.error-lead {
|
||||
font-size: 16.5px;
|
||||
color: var(--muted);
|
||||
line-height: 1.6;
|
||||
margin: 0 auto 32px;
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
.error-actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.helpful-links {
|
||||
border-top: 1px solid var(--line);
|
||||
padding-top: 28px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.helpful-links h4 {
|
||||
font-size: 14px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
color: var(--navy);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.helpful-links ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px 20px;
|
||||
}
|
||||
|
||||
.helpful-links a {
|
||||
font-size: 14px;
|
||||
color: var(--muted);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 3px;
|
||||
}
|
||||
|
||||
.helpful-links a:hover {
|
||||
color: var(--coral-deep);
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.not-found-card {
|
||||
padding: 36px 20px;
|
||||
}
|
||||
.error-actions {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
316
src/pages/agencies.astro
Normal file
316
src/pages/agencies.astro
Normal file
@ -0,0 +1,316 @@
|
||||
---
|
||||
import Base from "../layouts/Base.astro";
|
||||
import CtaBand from "../components/CtaBand.astro";
|
||||
import ApprovalMockup from "../components/ApprovalMockup.astro";
|
||||
import ReportMockup from "../components/ReportMockup.astro";
|
||||
---
|
||||
|
||||
<Base
|
||||
title="Why Marketing Agencies Choose Quorla · Multi-Client Operations"
|
||||
description="Manage 10, 30, or 100 client social media accounts from one calm, approval-gated workspace. Client time zones, team roles, and white-label client reports."
|
||||
>
|
||||
<section class="page-hero">
|
||||
<div class="wrap">
|
||||
<div class="page-hero-inner">
|
||||
<span class="eyebrow">Agency Architecture</span>
|
||||
<h1>Built for agencies running dozens of client accounts</h1>
|
||||
<p class="lead">
|
||||
Generic social schedulers are designed for single brands or solo creators. Quorla is purpose-built for the reality of multi-client agency operations: strict client isolation, time-zone precision, and human sign-offs.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Problem Statement Section -->
|
||||
<section class="block">
|
||||
<div class="wrap">
|
||||
<div class="agency-problem-box">
|
||||
<span class="eyebrow">The Multi-Client Challenge</span>
|
||||
<h2>The nightmare every agency owner fears</h2>
|
||||
<p>
|
||||
A junior copywriter accidentally posts an internal joke meant for a personal account onto a medical client's public Instagram. Or a scheduled post for a West Coast restaurant goes live at 8:00 AM Eastern—three hours before anyone in California is awake.
|
||||
</p>
|
||||
<p>
|
||||
When you manage 20 or 50 client retainers, manual spreadsheets, shared password documents, and sloppy tool permissions create constant vulnerability. Quorla fixes this at the architecture level.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Pillar 1: Client Separation & No Accidental Cross-Posts -->
|
||||
<section class="block alt">
|
||||
<div class="wrap">
|
||||
<div class="agency-feature-grid">
|
||||
<div class="feature-info">
|
||||
<span class="badge badge-coral">Operational Safeguard 01</span>
|
||||
<h2>Zero accidental cross-posts</h2>
|
||||
<p>
|
||||
Each client in Quorla has an independent, walled-off workspace. Content libraries, media tags, draft queues, and social tokens are compartmentalized.
|
||||
</p>
|
||||
<ul class="check-list">
|
||||
<li><strong>Separate media buckets:</strong> An asset uploaded for "Green Corner Café" cannot be viewed or attached to "North Shore Dental".</li>
|
||||
<li><strong>Strict token sandboxing:</strong> Publishing commands are routed strictly through each client's isolated credential store.</li>
|
||||
<li><strong>Visual brand badges:</strong> Prominent client identifiers throughout the editing screen ensure team members always know which account they are working on.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="feature-asset">
|
||||
<ApprovalMockup />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Pillar 2: Client Local Time Zones -->
|
||||
<section class="block">
|
||||
<div class="wrap">
|
||||
<div class="agency-feature-grid reverse">
|
||||
<div class="feature-info">
|
||||
<span class="badge">Operational Safeguard 02</span>
|
||||
<h2>Client local time zones (No manual calculations)</h2>
|
||||
<p>
|
||||
When your agency spans multiple client geographic markets, expecting copywriters to manually convert time zones in their head leads to missed target windows.
|
||||
</p>
|
||||
<ul class="check-list">
|
||||
<li><strong>Local business calendars:</strong> If a client in Vancouver requests a post for Thursday at 11:30 AM, you simply set 11:30 AM on their Vancouver calendar.</li>
|
||||
<li><strong>Zero conversion friction:</strong> Quorla handles UTC conversions, municipal offsets, and daylight savings automatically behind the scenes.</li>
|
||||
<li><strong>Peak window defaults:</strong> Configure default client time slots per vertical (e.g. coffee shops at 7:45 AM local, B2B at 12:15 PM local).</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="feature-asset">
|
||||
<div class="agency-stat-card">
|
||||
<div class="card-icon" style="margin-bottom: 12px;">⏰</div>
|
||||
<h3 style="font-size: 20px; margin-bottom: 8px;">Regional Accuracy Guarantee</h3>
|
||||
<p style="font-size: 14.5px; color: var(--muted); margin-bottom: 16px;">
|
||||
Quorla synchronizes directly with international timezone databases (IANA). Every queued post displays both the client's local scheduled time and your team's local current time.
|
||||
</p>
|
||||
<div class="badge badge-success">Active Sync across all 24 timezones</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Pillar 3: Role-Based Hierarchy -->
|
||||
<section class="block alt">
|
||||
<div class="wrap">
|
||||
<div class="head head-center">
|
||||
<span class="eyebrow">Team Structure</span>
|
||||
<h2>How agency teams collaborate in Quorla</h2>
|
||||
<p>Give designers and copywriters the creative freedom they need, without giving them the keys to live client accounts.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid4">
|
||||
<div class="role-card">
|
||||
<span class="role-badge admin">Admin</span>
|
||||
<h4>Agency Owner / Partner</h4>
|
||||
<p>Connects client accounts, creates team members, resets passwords, and holds master approval authority over every queued post.</p>
|
||||
</div>
|
||||
|
||||
<div class="role-card">
|
||||
<span class="role-badge manager">Manager</span>
|
||||
<h4>Account Director</h4>
|
||||
<p>Plans campaign weeks, assigns client accounts to copywriters, reviews performance reports, and communicates with client stakeholders.</p>
|
||||
</div>
|
||||
|
||||
<div class="role-card">
|
||||
<span class="role-badge creative">Designer</span>
|
||||
<h4>Visual Creative / Video</h4>
|
||||
<p>Uploads finished reels, photography, and carousel graphic cards directly to client content libraries. Cannot schedule or publish.</p>
|
||||
</div>
|
||||
|
||||
<div class="role-card">
|
||||
<span class="role-badge copy">Editor</span>
|
||||
<h4>Copywriter / Scheduler</h4>
|
||||
<p>Drafts captions, platform mentions, hashtags, and proposed publish dates. All items remain in "Draft" until Admin sign-off.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Pillar 4: White-Label Client Reports -->
|
||||
<section class="block">
|
||||
<div class="wrap">
|
||||
<div class="agency-feature-grid">
|
||||
<div class="feature-info">
|
||||
<span class="badge badge-coral">Client Retention</span>
|
||||
<h2>Reports that prove your agency's value</h2>
|
||||
<p>
|
||||
Clients don't want spreadsheets with 40 cryptic metrics. They want to know: Did our social channels grow? What posts drove engagement? What is the team working on next?
|
||||
</p>
|
||||
<ul class="check-list">
|
||||
<li><strong>Clean PDF presentation:</strong> Exported with your agency's logo, colors, and styling. Completely white-label.</li>
|
||||
<li><strong>AI-assisted executive summaries:</strong> Summarize performance into plain English notes that non-technical business owners appreciate.</li>
|
||||
<li><strong>Retainer protection:</strong> Consistent, polished monthly audits remind clients why they keep paying your agency retainer every month.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="feature-asset">
|
||||
<ReportMockup />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<CtaBand
|
||||
title="Ready to run your agency's social with complete peace of mind?"
|
||||
lead="Talk with our technical team in Waterloo about setting up your agency workspace and client accounts."
|
||||
/>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
.agency-problem-box {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 18px;
|
||||
padding: 44px 48px;
|
||||
max-width: 860px;
|
||||
margin: 0 auto;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.agency-problem-box h2 {
|
||||
font-size: clamp(26px, 3.2vw, 36px);
|
||||
margin: 12px 0 16px;
|
||||
color: var(--navy);
|
||||
}
|
||||
|
||||
.agency-problem-box p {
|
||||
font-size: 16.5px;
|
||||
line-height: 1.68;
|
||||
color: #353740;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.agency-feature-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 60px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.agency-feature-grid.reverse {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
.agency-feature-grid.reverse > * {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.feature-info h2 {
|
||||
font-size: clamp(26px, 3vw, 36px);
|
||||
color: var(--navy);
|
||||
margin: 14px 0 16px;
|
||||
}
|
||||
|
||||
.feature-info p {
|
||||
font-size: 16px;
|
||||
line-height: 1.65;
|
||||
color: var(--muted);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.check-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.check-list li {
|
||||
font-size: 14.5px;
|
||||
line-height: 1.55;
|
||||
color: #353740;
|
||||
padding-left: 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.check-list li::before {
|
||||
content: "✓";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: var(--coral-deep);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.check-list strong {
|
||||
color: var(--navy);
|
||||
}
|
||||
|
||||
.agency-stat-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 16px;
|
||||
padding: 32px;
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
/* Role Cards */
|
||||
.role-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 14px;
|
||||
padding: 24px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.role-badge {
|
||||
align-self: flex-start;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
padding: 3px 10px;
|
||||
border-radius: 999px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.role-badge.admin {
|
||||
background: var(--navy);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.role-badge.manager {
|
||||
background: var(--navy-2);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.role-badge.creative {
|
||||
background: var(--coral-light);
|
||||
color: var(--coral-deep);
|
||||
}
|
||||
|
||||
.role-badge.copy {
|
||||
background: var(--soft);
|
||||
color: var(--navy);
|
||||
border: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.role-card h4 {
|
||||
font-size: 17px;
|
||||
color: var(--navy);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.role-card p {
|
||||
font-size: 14px;
|
||||
line-height: 1.55;
|
||||
color: var(--muted);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.agency-feature-grid,
|
||||
.agency-feature-grid.reverse {
|
||||
grid-template-columns: 1fr;
|
||||
direction: ltr;
|
||||
gap: 36px;
|
||||
}
|
||||
|
||||
.agency-problem-box {
|
||||
padding: 32px 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
145
src/pages/blog/[slug].astro
Normal file
145
src/pages/blog/[slug].astro
Normal file
@ -0,0 +1,145 @@
|
||||
---
|
||||
import Base from "../../layouts/Base.astro";
|
||||
import CtaBand from "../../components/CtaBand.astro";
|
||||
import { getCollection, render } from "astro:content";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const posts = await getCollection("blog");
|
||||
return posts.map((post) => ({
|
||||
params: { slug: post.id },
|
||||
props: { post },
|
||||
}));
|
||||
}
|
||||
|
||||
const { post } = Astro.props;
|
||||
const { Content } = await render(post);
|
||||
---
|
||||
|
||||
<Base
|
||||
title={`${post.data.title} · Quorla Blog`}
|
||||
description={post.data.description}
|
||||
ogType="article"
|
||||
>
|
||||
<article class="prose blog-article">
|
||||
<div class="article-breadcrumb">
|
||||
<a href="/blog">← Back to all articles</a>
|
||||
</div>
|
||||
|
||||
<div class="article-header">
|
||||
<span class="badge badge-coral">{post.data.readTime}</span>
|
||||
<h1>{post.data.title}</h1>
|
||||
<div class="meta">
|
||||
<span>Published on {new Date(post.data.date).toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric" })}</span>
|
||||
<span>·</span>
|
||||
<span>By {post.data.author}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="article-content">
|
||||
<Content />
|
||||
</div>
|
||||
|
||||
<div class="article-footer-nav">
|
||||
<a href="/blog" class="btn btn-ghost btn-sm">← Back to Blog</a>
|
||||
<a href="/contact" class="btn btn-coral btn-sm">Request Quorla Access</a>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<CtaBand
|
||||
title="Scale your agency's social publishing without the chaos."
|
||||
lead="Join marketing agencies using Quorla to manage multiple client accounts with strict admin approvals."
|
||||
/>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
.blog-article {
|
||||
max-width: 800px;
|
||||
padding-top: 48px;
|
||||
}
|
||||
|
||||
.article-breadcrumb {
|
||||
margin-bottom: 24px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.article-breadcrumb a {
|
||||
color: var(--navy);
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.article-breadcrumb a:hover {
|
||||
color: var(--coral-deep);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.article-header {
|
||||
margin-bottom: 36px;
|
||||
}
|
||||
|
||||
.article-header h1 {
|
||||
font-size: clamp(30px, 4vw, 42px);
|
||||
line-height: 1.18;
|
||||
color: var(--navy);
|
||||
margin: 14px 0 16px;
|
||||
}
|
||||
|
||||
.article-header .meta {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
color: var(--muted);
|
||||
border-bottom: 1px solid var(--line);
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.article-content {
|
||||
font-size: 16.5px;
|
||||
line-height: 1.7;
|
||||
color: #2e303a;
|
||||
}
|
||||
|
||||
.article-content :global(h2) {
|
||||
font-size: 24px;
|
||||
color: var(--navy);
|
||||
margin: 40px 0 16px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.article-content :global(h3) {
|
||||
font-size: 19px;
|
||||
color: var(--navy);
|
||||
margin: 28px 0 12px;
|
||||
}
|
||||
|
||||
.article-content :global(p) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.article-content :global(ul) {
|
||||
padding-left: 24px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.article-content :global(li) {
|
||||
margin-bottom: 10px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.article-content :global(strong) {
|
||||
color: var(--navy);
|
||||
}
|
||||
|
||||
.article-footer-nav {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 48px;
|
||||
padding-top: 28px;
|
||||
border-top: 1px solid var(--line);
|
||||
gap: 16px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
</style>
|
||||
157
src/pages/blog/index.astro
Normal file
157
src/pages/blog/index.astro
Normal file
@ -0,0 +1,157 @@
|
||||
---
|
||||
import Base from "../../layouts/Base.astro";
|
||||
import CtaBand from "../../components/CtaBand.astro";
|
||||
import { getCollection } from "astro:content";
|
||||
|
||||
const posts = await getCollection("blog");
|
||||
// Sort by date descending
|
||||
posts.sort((a, b) => new Date(b.data.date).getTime() - new Date(a.data.date).getTime());
|
||||
---
|
||||
|
||||
<Base
|
||||
title="Agency Operations & Social Strategy Blog · Quorla"
|
||||
description="Practical advice, operational playbooks, and strategies for marketing agencies running social media across multiple client accounts."
|
||||
>
|
||||
<section class="page-hero">
|
||||
<div class="wrap">
|
||||
<div class="page-hero-inner">
|
||||
<span class="eyebrow">Agency Insights</span>
|
||||
<h1>Agency Operations & Social Publishing</h1>
|
||||
<p class="lead">
|
||||
Actionable field notes on managing client accounts, preventing publishing mistakes, and scaling an agency social media team.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="block">
|
||||
<div class="wrap">
|
||||
<div class="blog-grid">
|
||||
{posts.map((post) => (
|
||||
<article class="blog-card">
|
||||
<div class="blog-card-meta">
|
||||
<span class="badge">{post.data.readTime}</span>
|
||||
<time datetime={post.data.date}>
|
||||
{new Date(post.data.date).toLocaleDateString("en-US", {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
})}
|
||||
</time>
|
||||
</div>
|
||||
<h2 class="blog-card-title">
|
||||
<a href={`/blog/${post.id}`}>{post.data.title}</a>
|
||||
</h2>
|
||||
<p class="blog-card-desc">{post.data.description}</p>
|
||||
<div class="blog-card-footer">
|
||||
<span class="author-tag">By {post.data.author}</span>
|
||||
<a href={`/blog/${post.id}`} class="read-link">
|
||||
Read article →
|
||||
</a>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<CtaBand
|
||||
title="Ready to bring calm to your agency's publishing operations?"
|
||||
lead="Request an agency invitation to Quorla today. We will set up your team's workspace and show you how approval-gated scheduling works."
|
||||
/>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
.blog-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 32px;
|
||||
}
|
||||
|
||||
.blog-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 16px;
|
||||
padding: 28px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: var(--shadow-sm);
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
|
||||
}
|
||||
|
||||
.blog-card:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: var(--shadow-md);
|
||||
border-color: #d5d3e6;
|
||||
}
|
||||
|
||||
.blog-card-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-size: 12.5px;
|
||||
color: var(--muted);
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.blog-card-title {
|
||||
font-size: 20px;
|
||||
line-height: 1.35;
|
||||
margin: 0 0 12px;
|
||||
color: var(--navy);
|
||||
}
|
||||
|
||||
.blog-card-title a {
|
||||
text-decoration: none;
|
||||
color: var(--navy);
|
||||
}
|
||||
|
||||
.blog-card-title a:hover {
|
||||
color: var(--coral-deep);
|
||||
}
|
||||
|
||||
.blog-card-desc {
|
||||
font-size: 14.5px;
|
||||
line-height: 1.6;
|
||||
color: var(--muted);
|
||||
margin: 0 0 24px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.blog-card-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-top: 1px solid var(--line);
|
||||
padding-top: 16px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.author-tag {
|
||||
color: #7b7e8f;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.read-link {
|
||||
color: var(--navy);
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.read-link:hover {
|
||||
color: var(--coral-deep);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
.blog-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.blog-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
316
src/pages/contact.astro
Normal file
316
src/pages/contact.astro
Normal file
@ -0,0 +1,316 @@
|
||||
---
|
||||
import Base from "../layouts/Base.astro";
|
||||
---
|
||||
|
||||
<Base
|
||||
title="Request Access · Quorla Social Media Management for Agencies"
|
||||
description="Request an agency invitation to Quorla. Tell us about your client accounts, team size, and publishing workflow."
|
||||
>
|
||||
<section class="page-hero">
|
||||
<div class="wrap">
|
||||
<div class="page-hero-inner">
|
||||
<span class="eyebrow">Agency Onboarding</span>
|
||||
<h1>Request access to Quorla</h1>
|
||||
<p class="lead">
|
||||
Quorla is currently onboarding marketing agencies by invitation. Tell us about your team and client roster, and we will prepare your workspace.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="block">
|
||||
<div class="wrap">
|
||||
<div class="contact-grid">
|
||||
<!-- Form Column -->
|
||||
<div class="form-card">
|
||||
<h2 style="font-size: 24px; margin-bottom: 8px;">Agency Invitation Application</h2>
|
||||
<p style="color: var(--muted); font-size: 14.5px; margin-bottom: 24px;">
|
||||
Fill out the form below or email us directly at <a href="mailto:support@quorlasocial.com" style="color: var(--coral-deep); font-weight: 600;">support@quorlasocial.com</a>.
|
||||
</p>
|
||||
|
||||
<form id="accessForm" class="access-form">
|
||||
<!-- Anti-spam Honeypot -->
|
||||
<div class="honeypot" aria-hidden="true">
|
||||
<label for="agency_website_fax">Do not fill this out if you are human</label>
|
||||
<input type="text" id="agency_website_fax" name="website_fax" tabindex="-1" autocomplete="off" />
|
||||
</div>
|
||||
|
||||
<div class="form-row-2">
|
||||
<div class="form-group">
|
||||
<label for="contactName" class="form-label">Your Name <span class="req">*</span></label>
|
||||
<input type="text" id="contactName" name="name" class="form-input" placeholder="e.g. Alex Morgan" required />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="agencyName" class="form-label">Agency Name <span class="req">*</span></label>
|
||||
<input type="text" id="agencyName" name="agency" class="form-input" placeholder="e.g. Northstar Digital" required />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="workEmail" class="form-label">Work Email <span class="req">*</span></label>
|
||||
<input type="email" id="workEmail" name="email" class="form-input" placeholder="alex@northstardigital.com" required />
|
||||
</div>
|
||||
|
||||
<div class="form-row-2">
|
||||
<div class="form-group">
|
||||
<label for="clientCount" class="form-label">Active Client Accounts <span class="req">*</span></label>
|
||||
<select id="clientCount" name="clients" class="form-select" required>
|
||||
<option value="" disabled selected>Select client count...</option>
|
||||
<option value="1-5 clients">1 – 5 client accounts</option>
|
||||
<option value="6-15 clients">6 – 15 client accounts</option>
|
||||
<option value="16-30 clients">16 – 30 client accounts</option>
|
||||
<option value="31-50 clients">31 – 50 client accounts</option>
|
||||
<option value="50+ clients">50+ client accounts</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="deployModel" class="form-label">Preferred Deployment</label>
|
||||
<select id="deployModel" name="deployment" class="form-select">
|
||||
<option value="Hosted Cloud">Hosted Cloud (Managed)</option>
|
||||
<option value="Self-Hosted Dedicated">Self-Hosted Dedicated (VPC / On-Prem)</option>
|
||||
<option value="Not Sure Yet">Undecided / Open to recommendation</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="agencyMessage" class="form-label">Current Challenges & Workflow Notes</label>
|
||||
<textarea
|
||||
id="agencyMessage"
|
||||
name="message"
|
||||
class="form-textarea"
|
||||
placeholder="Tell us what platforms your clients use most, your team structure, or questions you have about approval workflows."
|
||||
></textarea>
|
||||
<div class="form-help">Optional: Helps us tailor your workspace setup.</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-coral btn-lg w-full">
|
||||
Submit Request for Invitation
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div id="formSuccessMessage" class="success-box" hidden>
|
||||
<div class="success-icon">✓</div>
|
||||
<div>
|
||||
<h3 style="font-size: 18px; margin-bottom: 4px; color: #1a7f45;">Ready to send your details</h3>
|
||||
<p style="margin: 0; font-size: 14px; color: #2e4a36;">
|
||||
Clicking submit opened your mail client with your application details addressed to <strong>support@quorlasocial.com</strong>. If your email didn't launch automatically, <a id="directMailLink" href="mailto:support@quorlasocial.com" style="text-decoration: underline; font-weight: 600;">click here to send directly</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info Column -->
|
||||
<div class="contact-info-col">
|
||||
<div class="info-card">
|
||||
<h3>Direct Contact</h3>
|
||||
<p>Have an urgent question or specific review requirement? Reach out to our team directly:</p>
|
||||
<div class="info-item">
|
||||
<span class="info-icon">✉️</span>
|
||||
<div>
|
||||
<strong>Support & Access Requests:</strong>
|
||||
<a href="mailto:support@quorlasocial.com" class="info-link">support@quorlasocial.com</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-icon">🏢</span>
|
||||
<div>
|
||||
<strong>Company:</strong>
|
||||
<div>Metatroncube Software Solutions</div>
|
||||
<div style="color: var(--muted); font-size: 13px;">Waterloo, Ontario, Canada</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="info-icon">⏱️</span>
|
||||
<div>
|
||||
<strong>Response Window:</strong>
|
||||
<div>We review applications and respond within 1 business day.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-card reassurance">
|
||||
<h4>No Spam Guarantee</h4>
|
||||
<p>
|
||||
We respect your privacy. We only use your email to coordinate your agency's Quorla access and discuss your onboarding. Zero marketing blasts or data sharing.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</Base>
|
||||
|
||||
<script>
|
||||
const form = document.getElementById("accessForm") as HTMLFormElement | null;
|
||||
const successBox = document.getElementById("formSuccessMessage");
|
||||
const directMailLink = document.getElementById("directMailLink") as HTMLAnchorElement | null;
|
||||
|
||||
if (form) {
|
||||
// Check if URL has ?plan=
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const plan = params.get("plan");
|
||||
if (plan) {
|
||||
const deploySelect = document.getElementById("deployModel") as HTMLSelectElement | null;
|
||||
if (deploySelect) {
|
||||
if (plan === "hosted") deploySelect.value = "Hosted Cloud";
|
||||
if (plan === "self-hosted") deploySelect.value = "Self-Hosted Dedicated";
|
||||
}
|
||||
}
|
||||
|
||||
form.addEventListener("submit", (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
// Check honeypot
|
||||
const hp = (document.getElementById("agency_website_fax") as HTMLInputElement)?.value;
|
||||
if (hp) {
|
||||
// Bot detected, silently exit
|
||||
return;
|
||||
}
|
||||
|
||||
const name = (document.getElementById("contactName") as HTMLInputElement)?.value || "";
|
||||
const agency = (document.getElementById("agencyName") as HTMLInputElement)?.value || "";
|
||||
const email = (document.getElementById("workEmail") as HTMLInputElement)?.value || "";
|
||||
const clients = (document.getElementById("clientCount") as HTMLSelectElement)?.value || "";
|
||||
const deployment = (document.getElementById("deployModel") as HTMLSelectElement)?.value || "";
|
||||
const message = (document.getElementById("agencyMessage") as HTMLTextAreaElement)?.value || "";
|
||||
|
||||
const subject = encodeURIComponent(`Quorla Access Request: ${agency} (${name})`);
|
||||
const body = encodeURIComponent(
|
||||
`Name: ${name}\nAgency: ${agency}\nWork Email: ${email}\nNumber of Clients: ${clients}\nDeployment Model: ${deployment}\n\nNotes & Current Challenges:\n${message}\n`
|
||||
);
|
||||
|
||||
const mailtoUrl = `mailto:support@quorlasocial.com?subject=${subject}&body=${body}`;
|
||||
|
||||
if (directMailLink) {
|
||||
directMailLink.href = mailtoUrl;
|
||||
}
|
||||
|
||||
if (successBox) {
|
||||
successBox.hidden = false;
|
||||
form.style.display = "none";
|
||||
}
|
||||
|
||||
window.location.href = mailtoUrl;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.contact-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1.25fr 0.75fr;
|
||||
gap: 40px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.form-row-2 {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.success-box {
|
||||
background: #eefaf3;
|
||||
border: 1px solid #c7eed6;
|
||||
border-radius: 12px;
|
||||
padding: 20px 24px;
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: flex-start;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.success-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
background: #1a7f45;
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 700;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.contact-info-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.info-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 14px;
|
||||
padding: 28px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.info-card h3,
|
||||
.info-card h4 {
|
||||
font-size: 18px;
|
||||
color: var(--navy);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.info-card p {
|
||||
font-size: 14.5px;
|
||||
color: var(--muted);
|
||||
line-height: 1.6;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
gap: 14px;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 16px;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.info-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.info-icon {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.info-link {
|
||||
display: block;
|
||||
color: var(--coral-deep);
|
||||
font-weight: 600;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.reassurance {
|
||||
background: var(--soft);
|
||||
}
|
||||
|
||||
.reassurance p {
|
||||
margin: 0;
|
||||
font-size: 13.5px;
|
||||
}
|
||||
|
||||
@media (max-width: 860px) {
|
||||
.contact-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 540px) {
|
||||
.form-row-2 {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
439
src/pages/features.astro
Normal file
439
src/pages/features.astro
Normal file
@ -0,0 +1,439 @@
|
||||
---
|
||||
import Base from "../layouts/Base.astro";
|
||||
import ApprovalMockup from "../components/ApprovalMockup.astro";
|
||||
import InboxMockup from "../components/InboxMockup.astro";
|
||||
import ReportMockup from "../components/ReportMockup.astro";
|
||||
import CtaBand from "../components/CtaBand.astro";
|
||||
---
|
||||
|
||||
<Base
|
||||
title="Features · Quorla Social Media Management for Agencies"
|
||||
description="Explore Quorla's agency features: strict admin approval workflows, client time-zone publishing, multi-client content library, social inbox, and white-label reports."
|
||||
>
|
||||
<!-- Page Header -->
|
||||
<section class="page-hero">
|
||||
<div class="wrap">
|
||||
<div class="page-hero-inner">
|
||||
<span class="eyebrow">Platform Capabilities</span>
|
||||
<h1>Engineered for agencies that cannot afford mistakes</h1>
|
||||
<p class="lead">
|
||||
Every client gets their own isolated workspace, custom time zone schedule, and dedicated content library. Zero posts ever publish without an agency administrator's verified sign-off.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Feature 1: Strict Admin Approval Gate -->
|
||||
<section class="block" id="approvals">
|
||||
<div class="wrap">
|
||||
<div class="feature-split">
|
||||
<div class="feature-text">
|
||||
<span class="badge badge-coral">Core Safety Engine</span>
|
||||
<h2>Strict approval before publishing</h2>
|
||||
<p>
|
||||
Other social media schedulers treat approvals as an optional checkbox. In Quorla, the approval gate is structural: drafts cannot enter the publishing queue without an agency admin's explicit sign-off.
|
||||
</p>
|
||||
<ul class="feature-bullets">
|
||||
<li><strong>Pixel-exact review:</strong> Review the exact cropped vertical video, carousel sequence, captions, mentions, and tags.</li>
|
||||
<li><strong>Role isolation:</strong> Copywriters, photographers, and freelance designers draft freely without ever having direct publishing keys.</li>
|
||||
<li><strong>Audit trail:</strong> Every sign-off logs the timestamp, approving administrator, and version hash.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="feature-visual">
|
||||
<ApprovalMockup />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Feature 2: Multi-Client Content Library -->
|
||||
<section class="block alt" id="library">
|
||||
<div class="wrap">
|
||||
<div class="feature-split reverse">
|
||||
<div class="feature-text">
|
||||
<span class="badge">Asset Management</span>
|
||||
<h2>Client-isolated content library</h2>
|
||||
<p>
|
||||
Never mix up client assets again. Each client has a dedicated content vault where editors and photographers upload high-resolution photos, Reels, TikTok videos, and graphic cards.
|
||||
</p>
|
||||
<ul class="feature-bullets">
|
||||
<li><strong>Pre-approved asset flags:</strong> Only approved media can be pulled into live campaign schedules.</li>
|
||||
<li><strong>Cross-brand protection:</strong> Content tags, asset folders, and metadata never leak across different client brands.</li>
|
||||
<li><strong>Format verification:</strong> Automatic aspect ratio check (9:16 for Reels/Shorts/TikTok, 1:1/4:5 for feeds) before submission.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="feature-visual">
|
||||
<div class="feature-card-showcase">
|
||||
<div class="lib-header">
|
||||
<span class="lib-title">Client Content Library: <strong>Peak Athletic Club</strong></span>
|
||||
<span class="badge badge-success">24 Assets Ready</span>
|
||||
</div>
|
||||
<div class="lib-grid">
|
||||
<div class="lib-item">
|
||||
<div class="lib-thumb v">Reel · 0:24</div>
|
||||
<div class="lib-meta">HIIT Morning Promo.mp4</div>
|
||||
<span class="pill">Approved Asset</span>
|
||||
</div>
|
||||
<div class="lib-item">
|
||||
<div class="lib-thumb s">Image · 1:1</div>
|
||||
<div class="lib-meta">Trainer Spotlight.jpg</div>
|
||||
<span class="pill">Approved Asset</span>
|
||||
</div>
|
||||
<div class="lib-item">
|
||||
<div class="lib-thumb v">TikTok · 0:15</div>
|
||||
<div class="lib-meta">Smoothie Bar Tour.mp4</div>
|
||||
<span class="pill">Approved Asset</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Feature 3: Client Local Time Zones -->
|
||||
<section class="block" id="timezones">
|
||||
<div class="wrap">
|
||||
<div class="feature-split">
|
||||
<div class="feature-text">
|
||||
<span class="badge">Global Agency Precision</span>
|
||||
<h2>Publish in the client's local time zone</h2>
|
||||
<p>
|
||||
Your agency may be headquartered in Waterloo, but your clients operate in Vancouver, Miami, London, or Sydney. Quorla converts all schedule calendars to each client's physical location.
|
||||
</p>
|
||||
<ul class="feature-bullets">
|
||||
<li><strong>Zero timezone math:</strong> Schedule a post for "Thursday 11:30 AM" and Quorla ensures it publishes at exactly 11:30 AM in that client's municipal market.</li>
|
||||
<li><strong>Daylight saving awareness:</strong> Automated offsets adapt to regional daylight saving changes without manual updates.</li>
|
||||
<li><strong>Peak window scheduling:</strong> Set default publishing slots per client based on their local audience engagement patterns.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="feature-visual">
|
||||
<div class="tz-card-showcase">
|
||||
<div class="tz-row">
|
||||
<div class="tz-loc">
|
||||
<span class="tz-flag">☕</span>
|
||||
<div>
|
||||
<strong>Green Corner Café</strong>
|
||||
<div class="tz-sub">Eastern Time (Toronto / NYC)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tz-time">11:30 AM EST <span class="badge badge-success">Scheduled</span></div>
|
||||
</div>
|
||||
<div class="tz-row">
|
||||
<div class="tz-loc">
|
||||
<span class="tz-flag">🏄♂️</span>
|
||||
<div>
|
||||
<strong>Pacific Surf School</strong>
|
||||
<div class="tz-sub">Pacific Time (Los Angeles / Vancouver)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tz-time">08:00 AM PST <span class="badge badge-success">Scheduled</span></div>
|
||||
</div>
|
||||
<div class="tz-row">
|
||||
<div class="tz-loc">
|
||||
<span class="tz-flag">🏛️</span>
|
||||
<div>
|
||||
<strong>Mayfair Architectural Studio</strong>
|
||||
<div class="tz-sub">Greenwich Mean Time (London)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tz-time">05:30 PM GMT <span class="badge badge-success">Scheduled</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Feature 4: Social Inbox & AI Draft Replies -->
|
||||
<section class="block alt" id="inbox">
|
||||
<div class="wrap">
|
||||
<div class="feature-split reverse">
|
||||
<div class="feature-text">
|
||||
<span class="badge">Community Management</span>
|
||||
<h2>Unified social inbox with AI reply drafts</h2>
|
||||
<p>
|
||||
Monitor Instagram and Facebook comments and direct messages per client. Quorla prepares context-aware reply suggestions, but strictly requires a human team member to review and approve before sending.
|
||||
</p>
|
||||
<ul class="feature-bullets">
|
||||
<li><strong>Client separation:</strong> Inboxes are cleanly partitioned so community managers never reply from the wrong account.</li>
|
||||
<li><strong>AI assistance (Anthropic):</strong> Intelligent draft generation analyzes the user question and suggests polite, accurate responses.</li>
|
||||
<li><strong>No robotic auto-responders:</strong> No unmonitored bots hallucinating on your client's public reputation.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="feature-visual">
|
||||
<InboxMockup />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Feature 5: White-Label PDF Reports -->
|
||||
<section class="block" id="reports">
|
||||
<div class="wrap">
|
||||
<div class="feature-split">
|
||||
<div class="feature-text">
|
||||
<span class="badge">Client Deliverables</span>
|
||||
<h2>Reports clients can actually understand</h2>
|
||||
<p>
|
||||
Ditch confusing, messy dashboards that clients ignore. Quorla generates monthly audits, weekly performance summaries, and upcoming content calendars into clean, beautifully formatted PDFs.
|
||||
</p>
|
||||
<ul class="feature-bullets">
|
||||
<li><strong>100% White-label:</strong> Exports prominently feature your marketing agency's logo, colors, and header. Zero Quorla branding.</li>
|
||||
<li><strong>Plain-English narrative:</strong> Replaces arcane algorithmic charts with actionable summaries: what worked, what drove comments, and what to test next.</li>
|
||||
<li><strong>One-click export:</strong> Ready for client board meetings, email attachments, and monthly retainer check-ins.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="feature-visual">
|
||||
<ReportMockup />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Feature 6: Team Roles & API Safeguards -->
|
||||
<section class="block alt" id="roles-quotas">
|
||||
<div class="wrap">
|
||||
<div class="head head-center">
|
||||
<span class="eyebrow">Enterprise Control</span>
|
||||
<h2>Team roles & platform rate limit protection</h2>
|
||||
<p>
|
||||
Scale your agency from 3 team members to 50 without risking credentials or tripping platform bans.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid3">
|
||||
<div class="card">
|
||||
<div class="card-icon" aria-hidden="true">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M23 21v-2a4 4 0 0 0-3-3.87"></path><path d="M16 3.13a4 4 0 0 1 0 7.75"></path></svg>
|
||||
</div>
|
||||
<h3>Role-Based Access Control (RBAC)</h3>
|
||||
<p>Assign Admin, Manager, Designer, or Editor roles. Admins manage connections and approve posts; creative staff draft without dangerous access.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-icon" aria-hidden="true">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 14 14"></polyline></svg>
|
||||
</div>
|
||||
<h3>Smart Quota & Rate Limit Protection</h3>
|
||||
<p>Social APIs strictly enforce hourly and daily publishing limits. Quorla queues and paces requests automatically instead of failing.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-icon" aria-hidden="true">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>
|
||||
</div>
|
||||
<h3>Secure OAuth 2.0 PKCE Tokens</h3>
|
||||
<p>Admins connect accounts with official platform logins. Your team never handles, sees, or stores client passwords.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA Band -->
|
||||
<CtaBand
|
||||
title="Equip your agency team with a safer social media workflow."
|
||||
lead="Request an agency invitation today. We will set up your workspace and show you how approval-gated publishing works."
|
||||
/>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
.feature-split {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 60px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.feature-split.reverse {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
.feature-split.reverse > * {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.feature-text {
|
||||
max-width: 520px;
|
||||
}
|
||||
|
||||
.feature-text h2 {
|
||||
font-size: clamp(26px, 3.2vw, 36px);
|
||||
line-height: 1.18;
|
||||
margin: 14px 0 16px;
|
||||
color: var(--navy);
|
||||
}
|
||||
|
||||
.feature-text p {
|
||||
font-size: 16px;
|
||||
line-height: 1.65;
|
||||
color: var(--muted);
|
||||
margin: 0 0 22px;
|
||||
}
|
||||
|
||||
.feature-bullets {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.feature-bullets li {
|
||||
font-size: 14.5px;
|
||||
line-height: 1.55;
|
||||
color: #353740;
|
||||
position: relative;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.feature-bullets li::before {
|
||||
content: "✓";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: var(--coral-deep);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.feature-bullets strong {
|
||||
color: var(--navy);
|
||||
}
|
||||
|
||||
.feature-visual {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Content Library Showcase */
|
||||
.feature-card-showcase {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 16px;
|
||||
padding: 24px;
|
||||
box-shadow: var(--shadow-md);
|
||||
width: 100%;
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
.lib-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid var(--line);
|
||||
padding-bottom: 12px;
|
||||
margin-bottom: 16px;
|
||||
font-size: 13.5px;
|
||||
}
|
||||
|
||||
.lib-title {
|
||||
color: var(--navy);
|
||||
}
|
||||
|
||||
.lib-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.lib-item {
|
||||
background: #faf9fd;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.lib-thumb {
|
||||
background: linear-gradient(135deg, var(--navy-2), var(--navy));
|
||||
color: #ffffff;
|
||||
border-radius: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.lib-thumb.v {
|
||||
height: 90px;
|
||||
}
|
||||
|
||||
.lib-thumb.s {
|
||||
height: 90px;
|
||||
}
|
||||
|
||||
.lib-meta {
|
||||
font-size: 11px;
|
||||
color: var(--navy);
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
/* Timezone Showcase */
|
||||
.tz-card-showcase {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 16px;
|
||||
padding: 24px;
|
||||
box-shadow: var(--shadow-md);
|
||||
width: 100%;
|
||||
max-width: 480px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.tz-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: #faf9fd;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 10px;
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.tz-loc {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.tz-flag {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.tz-sub {
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.tz-time {
|
||||
font-family: "Plus Jakarta Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 13.5px;
|
||||
color: var(--navy);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.feature-split,
|
||||
.feature-split.reverse {
|
||||
grid-template-columns: 1fr;
|
||||
direction: ltr;
|
||||
gap: 36px;
|
||||
}
|
||||
|
||||
.feature-text {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,85 +1,436 @@
|
||||
---
|
||||
import Base from "../layouts/Base.astro";
|
||||
import ApprovalMockup from "../components/ApprovalMockup.astro";
|
||||
import CtaBand from "../components/CtaBand.astro";
|
||||
|
||||
const APP = "https://app.quorlasocial.com";
|
||||
---
|
||||
<Base title="Quorla · Social media management for agencies">
|
||||
<section class="hero">
|
||||
<div class="wrap">
|
||||
<div>
|
||||
<p class="eyebrow">Social media management for agencies</p>
|
||||
<h1>Every client's social, planned, approved and posted from one place.</h1>
|
||||
<p class="lead">Quorla helps marketing agencies plan content, get each post approved, and publish it to the right client account on the right platform at the client's local time. Then it shows the client what worked.</p>
|
||||
<div class="ctas">
|
||||
<a class="btn btn-coral" href="mailto:support@quorlasocial.com?subject=Quorla%20access">Request access</a>
|
||||
<a class="btn btn-ghost" href="https://app.quorlasocial.com">Sign in</a>
|
||||
|
||||
<Base
|
||||
title="Quorla · Social Media Management for Marketing Agencies"
|
||||
description="Every client's social planned, approved, and posted from one place. Built for agencies running multiple client accounts with strict admin approvals."
|
||||
>
|
||||
<!-- Hero Section -->
|
||||
<section class="hero-home">
|
||||
<div class="wrap hero-wrap">
|
||||
<div class="hero-copy">
|
||||
<span class="eyebrow">Social Media Management for Agencies</span>
|
||||
<h1 class="hero-title">
|
||||
Every client's social, planned, approved, and posted from one place.
|
||||
</h1>
|
||||
<p class="hero-lead">
|
||||
Quorla helps marketing agencies plan content, get each post approved, and publish it to the right client account on the right platform at the client's local time. Then it shows the client what worked.
|
||||
</p>
|
||||
<div class="hero-ctas">
|
||||
<a class="btn btn-coral btn-lg" href="/contact">Request access</a>
|
||||
<a class="btn btn-ghost-light btn-lg" href={APP} target="_blank" rel="noopener noreferrer">Sign in</a>
|
||||
</div>
|
||||
<div class="hero-trust">
|
||||
<span>✓ Strict Admin Approvals</span>
|
||||
<span>✓ Client Time Zones</span>
|
||||
<span>✓ Encrypted Tokens</span>
|
||||
<span>✓ Hosted or Self-Hosted</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mock" aria-label="Example: a post waiting for approval">
|
||||
<div class="row">
|
||||
<div class="avatar" aria-hidden="true">GC</div>
|
||||
<div><div class="who">Green Corner Café</div><div class="sub">Thu 11:30 a.m. · client's local time</div></div>
|
||||
</div>
|
||||
<div class="media" aria-hidden="true">VERTICAL VIDEO · 0:18</div>
|
||||
<div class="cap">Fresh focaccia every morning at 8. First 20 people get a free cortado this Saturday.</div>
|
||||
<div class="chips"><span class="chip">Instagram Reel</span><span class="chip">TikTok</span><span class="chip">Google Business Profile</span></div>
|
||||
<div class="bar"><span class="pill">Waiting for approval</span><span class="btn btn-primary approve">Approve</span></div>
|
||||
|
||||
<div class="hero-mockup-wrap">
|
||||
<ApprovalMockup interactive={true} />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Problem / Solution Agency Value Pillars -->
|
||||
<section class="block alt" id="agency-pillars">
|
||||
<div class="wrap">
|
||||
<div class="head head-center">
|
||||
<span class="eyebrow">Built for Agency Realities</span>
|
||||
<h2>Why tools built for solo creators fail agencies</h2>
|
||||
<p>
|
||||
Managing 10, 25, or 50 client social accounts requires complete workspace separation, strict sign-offs, and time-zone precision.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid4">
|
||||
<div class="card">
|
||||
<div class="card-icon" aria-hidden="true">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path></svg>
|
||||
</div>
|
||||
<h3>Zero accidental posts</h3>
|
||||
<p>Designers and copywriters draft freely, but nothing goes live without an agency admin's explicit sign-off.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-icon" aria-hidden="true">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg>
|
||||
</div>
|
||||
<h3>Client local time zones</h3>
|
||||
<p>Posts publish at the client's local business hour (e.g. 11:30 AM EST or 8:00 AM PST), wherever your team is based.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-icon" aria-hidden="true">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><rect x="3" y="3" width="7" height="7"></rect><rect x="14" y="3" width="7" height="7"></rect><rect x="14" y="14" width="7" height="7"></rect><rect x="3" y="14" width="7" height="7"></rect></svg>
|
||||
</div>
|
||||
<h3>Client workspace isolation</h3>
|
||||
<p>Each client has their own content library, credentials, and schedule. No accidental cross-posting between accounts.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-icon" aria-hidden="true">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line></svg>
|
||||
</div>
|
||||
<h3>White-label client reports</h3>
|
||||
<p>Monthly audits and weekly reviews export into crisp PDFs with your agency branding, written in plain English.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- How It Works Section -->
|
||||
<section class="block" id="how">
|
||||
<div class="wrap">
|
||||
<div class="head">
|
||||
<span class="eyebrow">The Agency Workflow</span>
|
||||
<h2>How it works</h2>
|
||||
<p>One workflow for every client, with a person signing off before anything goes live.</p>
|
||||
<p>One calm, predictable workflow for every client account, with a person signing off before anything goes live.</p>
|
||||
</div>
|
||||
|
||||
<div class="steps">
|
||||
<div class="step"><h3>Connect</h3><p>An admin connects each client's accounts once, with the platform's own sign-in. Quorla never asks for their passwords.</p></div>
|
||||
<div class="step"><h3>Plan</h3><p>The team uploads finished work to each client's library and builds the week's posts from it, with captions written for each platform.</p></div>
|
||||
<div class="step"><h3>Approve</h3><p>An admin reviews the exact caption, media and settings. Nothing is posted without that approval.</p></div>
|
||||
<div class="step"><h3>Publish and report</h3><p>Quorla posts at the scheduled time, keeps within each platform's limits, and turns the results into a report the client can read.</p></div>
|
||||
<div class="step">
|
||||
<h3>Connect</h3>
|
||||
<p>An admin connects each client's accounts once, via official OAuth platform sign-in. Quorla never asks for or stores passwords.</p>
|
||||
</div>
|
||||
<div class="step">
|
||||
<h3>Plan</h3>
|
||||
<p>Designers and editors upload finished creative to the client's library and prepare draft posts with platform-specific formatting.</p>
|
||||
</div>
|
||||
<div class="step">
|
||||
<h3>Approve</h3>
|
||||
<p>An agency admin reviews the exact caption, media, tags, and scheduled time. Nothing posts without this verified approval.</p>
|
||||
</div>
|
||||
<div class="step">
|
||||
<h3>Publish & report</h3>
|
||||
<p>Quorla publishes on schedule, handles platform API rate limits gracefully, and turns raw performance data into clear reports.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Core Features Showcase -->
|
||||
<section class="block alt" id="features">
|
||||
<div class="wrap">
|
||||
<div class="head">
|
||||
<span class="eyebrow">Comprehensive Toolset</span>
|
||||
<h2>Built for teams running many client accounts</h2>
|
||||
<p>Each client keeps their own voice, accounts and data. Your team sees what it needs to.</p>
|
||||
<p>Each client keeps their own voice, accounts, and data. Your team sees exactly what they need to see.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid3">
|
||||
<div class="card"><h3>Content library</h3><p>Designers and editors upload finished posts per client. Only approved items can be scheduled.</p></div>
|
||||
<div class="card"><h3>Approval before publishing</h3><p>Drafts wait for an admin. Approval covers the exact caption and media, not just the idea.</p></div>
|
||||
<div class="card"><h3>Client time zones</h3><p>Posts go out at the client's local hour, wherever your team is working from.</p></div>
|
||||
<div class="card"><h3>Comments and messages</h3><p>See comments and DMs per client and draft replies. A person approves every reply.</p></div>
|
||||
<div class="card"><h3>Reports clients can read</h3><p>Monthly audits and weekly reports in plain language, exported as PDFs with your agency's branding.</p></div>
|
||||
<div class="card"><h3>Team roles</h3><p>Admins connect accounts and approve. Designers, editors and managers get the views they need.</p></div>
|
||||
<div class="card">
|
||||
<h3>Content library per client</h3>
|
||||
<p>Designers and video editors upload finished assets. Only approved creative items can be scheduled for upcoming campaigns.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>Approval before publishing</h3>
|
||||
<p>Drafts wait for an agency administrator. Approval covers the exact caption, cropped media, and settings—not just vague outlines.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>Client time zones</h3>
|
||||
<p>Posts go out at the client's local hour, whether your agency team is working from Toronto, London, or remotely across zones.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>Unified comments & DMs inbox</h3>
|
||||
<p>Triage comments and direct messages across Instagram and Facebook. Draft replies with AI assistance, signed off by a human.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>Reports clients can actually read</h3>
|
||||
<p>Monthly audits and weekly summaries in plain language, exported as clean PDFs branded with your agency's logo and colours.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>Granular agency team roles</h3>
|
||||
<p>Admins connect accounts and approve. Designers, editors, and account managers get the focused workspaces they need.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="feature-link-row">
|
||||
<a href="/features" class="inline-link">
|
||||
Explore all features and agency workflows →
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Platforms Grid -->
|
||||
<section class="block" id="platforms">
|
||||
<div class="wrap">
|
||||
<div class="head">
|
||||
<h2>Platforms</h2>
|
||||
<p>Connect the accounts each client actually uses. Every platform has its own post settings, and Quorla respects its rules and rate limits.</p>
|
||||
<span class="eyebrow">Direct Platform Integrations</span>
|
||||
<h2>Supported platforms</h2>
|
||||
<p>Connect the accounts each client actually uses. Quorla respects each platform's API rules, content guidelines, and rate limits.</p>
|
||||
</div>
|
||||
<div class="platforms">
|
||||
<span>Instagram</span><span>Facebook</span><span>TikTok</span><span>YouTube</span><span>Google Business Profile</span><span>LinkedIn</span><span>Pinterest</span><span>Threads</span><span>Reddit</span>
|
||||
|
||||
<div class="platform-cards-grid">
|
||||
<div class="p-card">
|
||||
<div class="p-card-top">
|
||||
<span class="p-name">Instagram</span>
|
||||
<span class="badge badge-success">Connected</span>
|
||||
</div>
|
||||
<p class="p-desc">Reels, Carousels, Single Images, Stories, and Comment/DM Inbox triage.</p>
|
||||
</div>
|
||||
|
||||
<div class="p-card">
|
||||
<div class="p-card-top">
|
||||
<span class="p-name">Facebook</span>
|
||||
<span class="badge badge-success">Connected</span>
|
||||
</div>
|
||||
<p class="p-desc">Page posts, video reels, photo albums, and unified conversation inbox.</p>
|
||||
</div>
|
||||
|
||||
<div class="p-card">
|
||||
<div class="p-card-top">
|
||||
<span class="p-name">TikTok</span>
|
||||
<span class="badge badge-success">Connected</span>
|
||||
</div>
|
||||
<p class="p-desc">Direct Video & Photo publishing with privacy, comment, Duet, and Stitch controls.</p>
|
||||
</div>
|
||||
|
||||
<div class="p-card">
|
||||
<div class="p-card-top">
|
||||
<span class="p-name">YouTube</span>
|
||||
<span class="badge badge-success">Connected</span>
|
||||
</div>
|
||||
<p class="p-desc">YouTube Shorts and long-form video scheduling with title and tag management.</p>
|
||||
</div>
|
||||
|
||||
<div class="p-card">
|
||||
<div class="p-card-top">
|
||||
<span class="p-name">Google Business Profile</span>
|
||||
<span class="badge badge-success">Connected</span>
|
||||
</div>
|
||||
<p class="p-desc">Local business updates, promotional offers, and Google Search/Maps visibility.</p>
|
||||
</div>
|
||||
|
||||
<div class="p-card p-coming-soon">
|
||||
<div class="p-card-top">
|
||||
<span class="p-name">LinkedIn, Pinterest, Threads, Reddit</span>
|
||||
<span class="badge">Coming Soon</span>
|
||||
</div>
|
||||
<p class="p-desc">Built in Quorla engine; awaiting platform partner approvals before public roll-out.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tiktok-callout">
|
||||
<div class="callout-icon">ℹ️</div>
|
||||
<div>
|
||||
<strong>TikTok Content Direct Posting Notice:</strong>
|
||||
Creators and agency admins select post privacy (Public, Friends, or Self-Only), configure comment, Duet, and Stitch permissions, and review TikTok's commercial music and branded-content policies directly inside Quorla before publication.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="feature-link-row">
|
||||
<a href="/platforms" class="inline-link">
|
||||
View full platform capability matrix →
|
||||
</a>
|
||||
</div>
|
||||
<p class="note">On TikTok, creators choose who can see each post and whether comments, Duet and Stitch are on, and Quorla shows TikTok's music and branded-content terms before posting.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="block" style="padding-top:0">
|
||||
<div class="wrap">
|
||||
<div class="cta">
|
||||
<div>
|
||||
<h2>Run your clients' social in one place</h2>
|
||||
<p>Quorla is available to agencies by invitation. Tell us about your team.</p>
|
||||
</div>
|
||||
<a class="btn btn-coral" href="mailto:support@quorlasocial.com?subject=Quorla%20access">Request access</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- CTA Band -->
|
||||
<CtaBand />
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
/* Hero Styles */
|
||||
.hero-home {
|
||||
background: var(--navy);
|
||||
color: #ffffff;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
padding: 80px 0 96px;
|
||||
}
|
||||
|
||||
.hero-home::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: -160px;
|
||||
top: -160px;
|
||||
width: 600px;
|
||||
height: 600px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, rgba(252, 109, 69, 0.3), transparent 65%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.hero-wrap {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: grid;
|
||||
grid-template-columns: 1.15fr 0.85fr;
|
||||
gap: 48px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.hero-copy {
|
||||
max-width: 580px;
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-size: clamp(36px, 4.8vw, 54px);
|
||||
line-height: 1.08;
|
||||
font-weight: 800;
|
||||
color: #ffffff;
|
||||
margin: 0 0 20px;
|
||||
}
|
||||
|
||||
.hero-lead {
|
||||
color: #cfcde3;
|
||||
font-size: 18px;
|
||||
line-height: 1.6;
|
||||
margin: 0 0 32px;
|
||||
}
|
||||
|
||||
.hero-ctas {
|
||||
display: flex;
|
||||
gap: 14px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
.btn-ghost-light {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 50px;
|
||||
padding: 0 28px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
border-radius: 9px;
|
||||
color: #ffffff;
|
||||
background: transparent;
|
||||
transition: background 0.15s ease, border-color 0.15s ease;
|
||||
}
|
||||
|
||||
.btn-ghost-light:hover {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.hero-trust {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
flex-wrap: wrap;
|
||||
font-size: 13px;
|
||||
color: #cfcde3;
|
||||
}
|
||||
|
||||
.hero-mockup-wrap {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Platforms Grid */
|
||||
.platform-cards-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 20px;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
.p-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 12px;
|
||||
padding: 22px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.p-card-top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.p-name {
|
||||
font-family: "Plus Jakarta Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
color: var(--navy);
|
||||
}
|
||||
|
||||
.p-desc {
|
||||
font-size: 13.5px;
|
||||
color: var(--muted);
|
||||
margin: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.p-coming-soon {
|
||||
background: #fbfbfd;
|
||||
border-style: dashed;
|
||||
}
|
||||
|
||||
.tiktok-callout {
|
||||
background: #f6f5fb;
|
||||
border: 1px solid #dfdcee;
|
||||
border-left: 4px solid var(--navy);
|
||||
border-radius: 8px;
|
||||
padding: 16px 20px;
|
||||
display: flex;
|
||||
gap: 14px;
|
||||
align-items: flex-start;
|
||||
font-size: 13.5px;
|
||||
line-height: 1.55;
|
||||
color: #353740;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.callout-icon {
|
||||
font-size: 18px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.feature-link-row {
|
||||
margin-top: 36px;
|
||||
}
|
||||
|
||||
.inline-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
font-weight: 700;
|
||||
font-size: 15px;
|
||||
color: var(--navy);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 4px;
|
||||
}
|
||||
|
||||
.inline-link:hover {
|
||||
color: var(--coral-deep);
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
.hero-wrap {
|
||||
grid-template-columns: 1fr;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.hero-mockup-wrap {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.platform-cards-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.platform-cards-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.hero-home {
|
||||
padding: 56px 0 64px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
241
src/pages/platforms.astro
Normal file
241
src/pages/platforms.astro
Normal file
@ -0,0 +1,241 @@
|
||||
---
|
||||
import Base from "../layouts/Base.astro";
|
||||
import CtaBand from "../components/CtaBand.astro";
|
||||
|
||||
const activePlatforms = [
|
||||
{
|
||||
name: "Instagram",
|
||||
status: "Active",
|
||||
postTypes: "Reels, Carousels, Single Photos, Stories",
|
||||
features: "Direct publishing, client tagging, custom caption per network, comment and DM triage inbox.",
|
||||
notes: "Requires an Instagram Business or Creator account connected through a Meta Page.",
|
||||
},
|
||||
{
|
||||
name: "Facebook",
|
||||
status: "Active",
|
||||
postTypes: "Page posts, Video Reels, Photo albums, Links",
|
||||
features: "Scheduled Page updates, targeted audience filtering, inbox message responses with human approval.",
|
||||
notes: "Direct connection via Meta Graph API. Admin permission on the client's Facebook Page is required.",
|
||||
},
|
||||
{
|
||||
name: "TikTok",
|
||||
status: "Active",
|
||||
postTypes: "Vertical Video (Direct Post), Photo Carousel posts",
|
||||
features: "Direct posting via TikTok Content Posting API, privacy levels (Public, Friends, Self-only), Duet, Stitch, and comment toggles.",
|
||||
notes: "Quorla displays TikTok's commercial music usage confirmations and branded content disclosure toggles prior to approval.",
|
||||
},
|
||||
{
|
||||
name: "YouTube",
|
||||
status: "Active",
|
||||
postTypes: "YouTube Shorts, Standard Videos",
|
||||
features: "Title formatting, detailed description, tag keywords, privacy status (Public, Unlisted, Private).",
|
||||
notes: "Connected via Google OAuth 2.0. Complies fully with Google API Services User Data Policy.",
|
||||
},
|
||||
{
|
||||
name: "Google Business Profile",
|
||||
status: "Active",
|
||||
postTypes: "Business updates, Offer posts, Event announcements",
|
||||
features: "Local store visibility, Call-to-action buttons (Call Now, Learn More, Order Online), photo uploads.",
|
||||
notes: "Connects to verified local Google Business locations to boost local SEO and client search prominence.",
|
||||
},
|
||||
];
|
||||
|
||||
const upcomingPlatforms = [
|
||||
{
|
||||
name: "LinkedIn",
|
||||
stage: "Awaiting Platform Approval",
|
||||
types: "Company Page posts, Personal Profile articles, PDF carousels",
|
||||
status: "Built in Quorla engine. Currently in official platform partner verification.",
|
||||
},
|
||||
{
|
||||
name: "Pinterest",
|
||||
stage: "Awaiting Platform Approval",
|
||||
types: "Standard Pins, Video Pins, Board destination routing",
|
||||
status: "Built in Quorla engine. Undergoing partner developer review.",
|
||||
},
|
||||
{
|
||||
name: "Threads",
|
||||
stage: "Awaiting Platform Approval",
|
||||
types: "Text threads, Single image, Video, Link sharing",
|
||||
status: "Integrated with Meta Threads API; scheduled for rollout upon final app approval.",
|
||||
},
|
||||
{
|
||||
name: "Reddit",
|
||||
stage: "Awaiting Platform Approval",
|
||||
types: "Subreddit community posts, Link shares, Image submissions",
|
||||
status: "Built in Quorla engine with subreddit flair management; awaiting public API rollout.",
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
<Base
|
||||
title="Supported Platforms · Quorla Social Media Management"
|
||||
description="See what platforms Quorla supports: Instagram, Facebook, TikTok, YouTube, Google Business Profile, and upcoming networks with complete capability breakdown."
|
||||
>
|
||||
<section class="page-hero">
|
||||
<div class="wrap">
|
||||
<div class="page-hero-inner">
|
||||
<span class="eyebrow">Direct Network Integrations</span>
|
||||
<h1>Connect the platforms your clients actually rely on</h1>
|
||||
<p class="lead">
|
||||
Every social network operates under its own guidelines, media aspect ratios, and rate limits. Quorla manages platform peculiarities so your agency posts safely without API warnings or policy strikes.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Connected Platforms Table -->
|
||||
<section class="block">
|
||||
<div class="wrap">
|
||||
<div class="head">
|
||||
<span class="eyebrow">Available Today</span>
|
||||
<h2>Connected platforms & capabilities</h2>
|
||||
<p>Every account is connected once via official OAuth authentication. Your team never manages or handles client passwords.</p>
|
||||
</div>
|
||||
|
||||
<div class="table-wrap">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 22%">Platform</th>
|
||||
<th style="width: 28%">Supported Post Formats</th>
|
||||
<th style="width: 28%">Agency Features</th>
|
||||
<th style="width: 22%">Technical & Policy Notes</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{activePlatforms.map((p) => (
|
||||
<tr>
|
||||
<td>
|
||||
<strong>{p.name}</strong>
|
||||
<div style="margin-top: 4px;">
|
||||
<span class="badge badge-success">{p.status}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>{p.postTypes}</td>
|
||||
<td>{p.features}</td>
|
||||
<td><small style="color: var(--muted); line-height: 1.4; display: block;">{p.notes}</small></td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Deep Dive: TikTok Compliance and Direct Post -->
|
||||
<section class="block alt" id="tiktok-compliance">
|
||||
<div class="wrap">
|
||||
<div class="tiktok-compliance-card">
|
||||
<div class="compliance-badge">Specialized Integration</div>
|
||||
<h2>TikTok Content Posting & Creator Privacy Controls</h2>
|
||||
<p class="lead-note">
|
||||
Quorla integrates with the official TikTok Content Posting API. We give marketing agencies granular control while maintaining strict adherence to TikTok's community guidelines and developer terms.
|
||||
</p>
|
||||
|
||||
<div class="grid3" style="margin-top: 24px;">
|
||||
<div class="card">
|
||||
<h3>Audience & Privacy Settings</h3>
|
||||
<p>Select who can view the video: Public, Friends-only, or Self-only (private draft verification). No surprise public releases.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>Interactivity Flags</h3>
|
||||
<p>Explicitly enable or disable Comments, Duets, and Stitches on a per-video basis during the pre-approval review.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>Music & Branded Content Terms</h3>
|
||||
<p>Mandatory confirmation of TikTok's Commercial Music Usage Confirmation and Branded Content declaration prior to queuing.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="notice-bar">
|
||||
<strong>Direct Post Guarantee:</strong> Quorla never adds promotional watermarks, vendor overlays, or unauthorized metadata to client videos. Content appears exactly as created by your team.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Platforms Coming Soon -->
|
||||
<section class="block" id="coming-soon">
|
||||
<div class="wrap">
|
||||
<div class="head">
|
||||
<span class="eyebrow">In Verification Pipeline</span>
|
||||
<h2>Coming soon: New platform expansions</h2>
|
||||
<p>
|
||||
These networks are fully built within the Quorla publishing engine and are undergoing platform approval with developer review teams before general release.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid2">
|
||||
{upcomingPlatforms.map((up) => (
|
||||
<div class="card">
|
||||
<div class="up-header">
|
||||
<h3 style="margin: 0;">{up.name}</h3>
|
||||
<span class="badge badge-coral">{up.stage}</span>
|
||||
</div>
|
||||
<p style="margin: 12px 0 6px;"><strong>Target formats:</strong> {up.types}</p>
|
||||
<p style="color: var(--muted); font-size: 14px;">{up.status}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<CtaBand
|
||||
title="Need a custom platform setup for your agency accounts?"
|
||||
lead="Talk with our technical team about supported client account limits, self-hosted deployment, or specific network requirements."
|
||||
/>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
.tiktok-compliance-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 18px;
|
||||
padding: 36px 40px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.compliance-badge {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--coral-deep);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.tiktok-compliance-card h2 {
|
||||
font-size: clamp(24px, 3vw, 32px);
|
||||
color: var(--navy);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.lead-note {
|
||||
font-size: 16px;
|
||||
color: var(--muted);
|
||||
line-height: 1.6;
|
||||
max-width: 780px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.notice-bar {
|
||||
margin-top: 28px;
|
||||
background: var(--soft);
|
||||
border: 1px solid var(--line);
|
||||
border-left: 4px solid var(--navy);
|
||||
padding: 14px 18px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.up-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid var(--line);
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
</style>
|
||||
171
src/pages/pricing.astro
Normal file
171
src/pages/pricing.astro
Normal file
@ -0,0 +1,171 @@
|
||||
---
|
||||
import Base from "../layouts/Base.astro";
|
||||
import PlanCard from "../components/PlanCard.astro";
|
||||
import CtaBand from "../components/CtaBand.astro";
|
||||
|
||||
const hostedFeatures = [
|
||||
"Managed Canadian cloud hosting (zero DevOps needed)",
|
||||
"Automated daily backups and software updates",
|
||||
"Unlimited client workspaces & isolated content libraries",
|
||||
"Direct publishing: Instagram, Facebook, TikTok, YouTube, GBP",
|
||||
"Strict Admin Approval engine (Human-in-the-loop)",
|
||||
"Client local time zone scheduling (IANA sync)",
|
||||
"Multi-client Social Inbox with AI-assisted draft replies",
|
||||
"White-label client PDF performance reports",
|
||||
"Role-based access (Admin, Manager, Designer, Editor)",
|
||||
"Direct email support with product engineering team",
|
||||
];
|
||||
|
||||
const selfHostedFeatures = [
|
||||
"Deploy directly on your agency's server or private VPC",
|
||||
"Complete data custody (tokens & client assets never leave your infra)",
|
||||
"Direct PostgreSQL database access & custom SQL reporting",
|
||||
"White-label custom domain (e.g. social.youragency.com)",
|
||||
"All connected platforms: Instagram, FB, TikTok, YouTube, GBP",
|
||||
"Full Admin Approval gate & multi-role permissions",
|
||||
"Docker containerized deployment with one-command updates",
|
||||
"Offline / private client asset storage support",
|
||||
"Custom platform rate-limit queue configurations",
|
||||
"Dedicated deployment architecture review & setup guidance",
|
||||
];
|
||||
|
||||
const faqs = [
|
||||
{
|
||||
q: "Why are prices not listed on the website?",
|
||||
a: "Quorla is currently rolling out by invitation to marketing agencies. We work closely with our initial agency cohorts to ensure optimal onboarding, quota sizing, and workflow integration before establishing public tiered pricing.",
|
||||
},
|
||||
{
|
||||
q: "What is the difference between Hosted and Self-Hosted?",
|
||||
a: "With Hosted Cloud, Metatroncube runs and monitors the infrastructure in Canada. You log in and manage your clients immediately. With Self-Hosted, your agency deploys Quorla on your own Linux server or cloud instance (via Docker), giving you total custody of all tokens, database records, and media files.",
|
||||
},
|
||||
{
|
||||
q: "Who owns our clients' data and media?",
|
||||
a: "Your agency and your clients retain 100% ownership of all uploaded content, captions, and analytics data. We never sell platform data, never run third-party advertising, and never train AI models on your private client assets.",
|
||||
},
|
||||
{
|
||||
q: "How does the access invitation process work?",
|
||||
a: "Submit a request through our contact page or email support@quorlasocial.com. Tell us how many clients your agency manages and your preferred deployment model. Our team will review your application and send you an onboarding invitation.",
|
||||
},
|
||||
{
|
||||
q: "Which platforms are available right out of the box?",
|
||||
a: "Instagram, Facebook, TikTok, YouTube, and Google Business Profile are actively connected. LinkedIn, Pinterest, Threads, and Reddit publishing are built in the engine and waiting for final platform partner approval.",
|
||||
},
|
||||
{
|
||||
q: "Can our freelance contractors draft posts without seeing other clients?",
|
||||
a: "Yes. With Quorla's role-based access control, you assign team members only to specific client workspaces. Designers and copywriters can draft content, but they can never publish directly or see client workspaces to which they haven't been assigned.",
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
<Base
|
||||
title="Pricing & Deployment Models · Quorla Social Media Management"
|
||||
description="Hosted Cloud and Self-Hosted deployment options for marketing agencies. Transparent data custody, invite-only access, and comprehensive FAQ."
|
||||
>
|
||||
<section class="page-hero">
|
||||
<div class="wrap">
|
||||
<div class="page-hero-inner">
|
||||
<span class="eyebrow">Deployment & Plans</span>
|
||||
<h1>Hosted or self-hosted: Choose the right model for your agency</h1>
|
||||
<p class="lead">
|
||||
Whether you want a fully managed cloud solution or need to keep client tokens and media within your agency's private servers, Quorla gives you complete architectural choice.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Plans Comparison Section -->
|
||||
<section class="block">
|
||||
<div class="wrap">
|
||||
<div class="head head-center">
|
||||
<span class="eyebrow">Two Deployment Modes</span>
|
||||
<h2>Built around agency data ownership</h2>
|
||||
<p>Currently available by invitation. Onboarding slots are opened regularly for qualified marketing agencies.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid2" style="max-width: 960px; margin: 0 auto;">
|
||||
<PlanCard
|
||||
name="Hosted Cloud"
|
||||
tagline="We manage the servers, backups, and security updates so your team can focus strictly on client delivery."
|
||||
badge="Most Convenient"
|
||||
isPopular={true}
|
||||
features={hostedFeatures}
|
||||
ctaText="Request Hosted Invitation"
|
||||
ctaHref="/contact?plan=hosted"
|
||||
/>
|
||||
|
||||
<PlanCard
|
||||
name="Self-Hosted Dedicated"
|
||||
tagline="Deploy Quorla directly in your agency's private cloud or bare-metal server for total data custody."
|
||||
badge="Total Custody"
|
||||
isPopular={false}
|
||||
features={selfHostedFeatures}
|
||||
ctaText="Request Self-Hosted Info"
|
||||
ctaHref="/contact?plan=self-hosted"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- FAQ Section -->
|
||||
<section class="block alt" id="faq">
|
||||
<div class="wrap">
|
||||
<div class="head head-center">
|
||||
<span class="eyebrow">Frequently Asked Questions</span>
|
||||
<h2>Everything you need to know about Quorla plans</h2>
|
||||
<p>Clear, direct answers for agency founders, operations leads, and technical evaluators.</p>
|
||||
</div>
|
||||
|
||||
<div class="faq-grid">
|
||||
{faqs.map((faq) => (
|
||||
<div class="faq-card">
|
||||
<h3 class="faq-q">{faq.q}</h3>
|
||||
<p class="faq-a">{faq.a}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<CtaBand
|
||||
title="Ready to explore which Quorla deployment fits your agency?"
|
||||
lead="Send us an email or submit an access request. We will answer your technical questions and walk you through a private preview."
|
||||
/>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
.faq-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 24px;
|
||||
max-width: 980px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.faq-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 14px;
|
||||
padding: 26px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.faq-q {
|
||||
font-size: 17px;
|
||||
color: var(--navy);
|
||||
margin-bottom: 10px;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.faq-a {
|
||||
font-size: 14.5px;
|
||||
line-height: 1.6;
|
||||
color: var(--muted);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
.faq-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
177
src/pages/security.astro
Normal file
177
src/pages/security.astro
Normal file
@ -0,0 +1,177 @@
|
||||
---
|
||||
import Base from "../layouts/Base.astro";
|
||||
import CtaBand from "../components/CtaBand.astro";
|
||||
---
|
||||
|
||||
<Base
|
||||
title="Security, Privacy & Data Custody · Quorla Social Media Management"
|
||||
description="How Quorla safeguards marketing agency credentials: AES-256 token encryption at rest, strict human-in-the-loop approvals, instant token purge, and self-hosted options."
|
||||
>
|
||||
<section class="page-hero">
|
||||
<div class="wrap">
|
||||
<div class="page-hero-inner">
|
||||
<span class="eyebrow">Trust & Security Standards</span>
|
||||
<h1>Engineered for absolute client data custody</h1>
|
||||
<p class="lead">
|
||||
Agency clients trust you with their public reputation and valuable social accounts. Quorla is built around strict data isolation, token encryption, and human-in-the-loop sign-offs.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Security Pillars Grid -->
|
||||
<section class="block">
|
||||
<div class="wrap">
|
||||
<div class="head">
|
||||
<span class="eyebrow">Security Architecture</span>
|
||||
<h2>Core security guarantees</h2>
|
||||
<p>Built by Metatroncube Software Solutions in Waterloo, Ontario, Canada, with strict adherence to Canadian and international data protection standards.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid3">
|
||||
<div class="card" id="data-protection">
|
||||
<div class="card-icon" aria-hidden="true">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>
|
||||
</div>
|
||||
<h3>Encrypted Tokens at Rest</h3>
|
||||
<p>All social platform OAuth tokens and application secret keys are encrypted at rest using industry-standard AES-256 encryption. Stored tokens are accessible strictly by authorized background dispatch workers.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-icon" aria-hidden="true">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path></svg>
|
||||
</div>
|
||||
<h3>Zero Stored Passwords</h3>
|
||||
<p>Admins connect client social accounts via official OAuth 2.0 PKCE authentication flows. Quorla never sees, prompts for, handles, or stores client passwords or credentials.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-icon" aria-hidden="true">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>
|
||||
</div>
|
||||
<h3>Instant Token Deletion</h3>
|
||||
<p>When an agency or client disconnects an account in Quorla, stored access tokens are purged from the database immediately. Permissions can also be revoked from the platform's native settings at any time.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-icon" aria-hidden="true">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 14 14"></polyline></svg>
|
||||
</div>
|
||||
<h3>Mandatory Human Approval</h3>
|
||||
<p>No automated background bot can schedule or push live content. Every single post, Reel, or photo carousel must receive manual approval by an agency user with Admin privileges.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-icon" aria-hidden="true">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><rect x="2" y="2" width="20" height="8" rx="2" ry="2"></rect><rect x="2" y="14" width="20" height="8" rx="2" ry="2"></rect><line x1="6" y1="6" x2="6.01" y2="6"></line><line x1="6" y1="18" x2="6.01" y2="18"></line></svg>
|
||||
</div>
|
||||
<h3>Self-Hosted Custody Option</h3>
|
||||
<p>For agencies working with financial, medical, or government clients with strict data residency rules, Quorla can be deployed entirely inside your own private virtual private cloud (VPC).</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-icon" aria-hidden="true">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line></svg>
|
||||
</div>
|
||||
<h3>Zero AI Training on Client Data</h3>
|
||||
<p>We process AI-assisted drafts via Anthropic under commercial terms that strictly prohibit using your clients' private captions, assets, or performance data to train foundation models.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Platform Compliance Section -->
|
||||
<section class="block alt" id="compliance">
|
||||
<div class="wrap">
|
||||
<div class="compliance-box">
|
||||
<span class="eyebrow">Platform API Compliance</span>
|
||||
<h2>Strict adherence to developer terms & user data policies</h2>
|
||||
<p>
|
||||
Quorla operates strictly within the official developer guidelines and security agreements of each connected network:
|
||||
</p>
|
||||
|
||||
<div class="compliance-list">
|
||||
<div class="comp-item">
|
||||
<h4>Google API Services Compliance</h4>
|
||||
<p>
|
||||
Quorla's use and transfer of information received from Google APIs (YouTube, Google Business Profile) adheres to the <a href="https://developers.google.com/terms/api-services-user-data-policy" target="_blank" rel="noopener noreferrer">Google API Services User Data Policy</a>, including the Limited Use requirements.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="comp-item">
|
||||
<h4>TikTok Developer & Content Posting Terms</h4>
|
||||
<p>
|
||||
Integrates with TikTok Login Kit and Content Posting API. Adheres to TikTok's Music Usage Confirmation, Branded Content Policies, and Developer Terms. We never watermark uploaded videos or add unauthorized promotions.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="comp-item">
|
||||
<h4>Meta Platform Policies</h4>
|
||||
<p>
|
||||
Direct Graph API integration for Instagram and Facebook. We respect user privacy, never scrape public profiles, and enforce user access revocation immediately.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<CtaBand
|
||||
title="Have security questionnaire or enterprise compliance questions?"
|
||||
lead="Our technical engineering team is happy to review your agency's security requirements, data custody, or self-hosted deployment architecture."
|
||||
/>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
.compliance-box {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 18px;
|
||||
padding: 40px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.compliance-box h2 {
|
||||
font-size: clamp(24px, 3vw, 32px);
|
||||
margin: 10px 0 16px;
|
||||
color: var(--navy);
|
||||
}
|
||||
|
||||
.compliance-box > p {
|
||||
font-size: 16px;
|
||||
color: var(--muted);
|
||||
line-height: 1.6;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
.compliance-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.comp-item {
|
||||
background: var(--soft);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 10px;
|
||||
padding: 20px 24px;
|
||||
}
|
||||
|
||||
.comp-item h4 {
|
||||
font-size: 16.5px;
|
||||
color: var(--navy);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.comp-item p {
|
||||
font-size: 14.5px;
|
||||
color: #353740;
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.comp-item a {
|
||||
color: var(--navy-2);
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
@ -1,106 +1,609 @@
|
||||
/* Quorla site styles. Brand: navy #242142, coral #FC6D45. */
|
||||
:root {
|
||||
--navy: #242142; --navy-2: #3b3778; --coral: #fc6d45; --coral-deep: #c2461a;
|
||||
--ink: #1f2024; --muted: #5d6070; --line: #e6e5ef; --soft: #f6f5fb; --bg: #ffffff;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
html { -webkit-font-smoothing: antialiased; }
|
||||
body { margin: 0; background: var(--bg); color: var(--ink); font: 16px/1.6 Inter, "Segoe UI", system-ui, sans-serif; }
|
||||
h1, h2, h3 { font-family: "Plus Jakarta Sans", "Segoe UI", system-ui, sans-serif; letter-spacing: -0.015em; margin: 0; }
|
||||
a { color: inherit; }
|
||||
.wrap { max-width: 1120px; margin: 0 auto; padding: 0 24px; }
|
||||
:focus-visible { outline: 2px solid var(--coral); outline-offset: 3px; border-radius: 4px; }
|
||||
--navy: #242142;
|
||||
--navy-2: #3b3778;
|
||||
--navy-light: #524d9c;
|
||||
--coral: #fc6d45;
|
||||
--coral-deep: #c2461a;
|
||||
--coral-light: #fff0ea;
|
||||
--ink: #1f2024;
|
||||
--muted: #5d6070;
|
||||
--line: #e6e5ef;
|
||||
--soft: #f6f5fb;
|
||||
--bg: #ffffff;
|
||||
|
||||
/* header */
|
||||
header.top { position: sticky; top: 0; z-index: 5; background: rgba(255,255,255,.92); backdrop-filter: blur(8px); border-bottom: 1px solid var(--line); }
|
||||
header.top .wrap { display: flex; align-items: center; justify-content: space-between; height: 64px; gap: 16px; }
|
||||
header.top img { height: 30px; width: auto; display: block; }
|
||||
nav.links { display: flex; align-items: center; gap: 24px; font-size: 14.5px; font-weight: 500; }
|
||||
nav.links a { text-decoration: none; color: var(--muted); }
|
||||
nav.links a:hover { color: var(--ink); }
|
||||
.btn { display: inline-flex; align-items: center; justify-content: center; height: 42px; padding: 0 18px; border-radius: 8px; font-weight: 600; font-size: 15px; text-decoration: none; border: 1px solid transparent; white-space: nowrap; }
|
||||
.btn-primary { background: var(--navy); color: #fff; }
|
||||
.btn-primary:hover { background: var(--navy-2); }
|
||||
.btn-ghost { border-color: #d6d4e4; color: var(--navy); background: #fff; }
|
||||
.btn-ghost:hover { background: var(--soft); }
|
||||
.btn-coral { background: var(--coral); color: var(--navy); }
|
||||
.btn-coral:hover { background: #ff8460; }
|
||||
nav.links .btn { height: 36px; font-size: 14px; color: #fff; }
|
||||
|
||||
/* hero */
|
||||
.hero { background: var(--navy); color: #fff; position: relative; overflow: hidden; }
|
||||
.hero::after { content: ""; position: absolute; right: -180px; top: -180px; width: 560px; height: 560px; border-radius: 50%; background: radial-gradient(circle, rgba(252,109,69,.32), transparent 65%); pointer-events: none; }
|
||||
.hero .wrap { position: relative; z-index: 1; padding-top: 88px; padding-bottom: 96px; display: grid; grid-template-columns: 1.1fr .9fr; gap: 56px; align-items: center; }
|
||||
.eyebrow { font-size: 12.5px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--coral); margin: 0 0 16px; }
|
||||
.hero h1 { font-size: clamp(36px, 5vw, 56px); line-height: 1.06; font-weight: 800; }
|
||||
.hero p.lead { color: #cfcde3; font-size: 18px; max-width: 540px; margin: 20px 0 32px; }
|
||||
.hero .ctas { display: flex; gap: 12px; flex-wrap: wrap; }
|
||||
.hero .btn-ghost { background: transparent; color: #fff; border-color: rgba(255,255,255,.28); }
|
||||
.hero .btn-ghost:hover { background: rgba(255,255,255,.08); }
|
||||
|
||||
/* approval mock */
|
||||
.mock { background: #fff; color: var(--ink); border-radius: 14px; padding: 18px; box-shadow: 0 30px 60px -20px rgba(0,0,0,.45); font-size: 14px; }
|
||||
.mock .row { display: flex; align-items: center; gap: 10px; }
|
||||
.mock .who { font-weight: 600; }
|
||||
.mock .sub { color: var(--muted); font-size: 12.5px; }
|
||||
.mock .media { margin: 14px 0; height: 150px; border-radius: 10px; background: linear-gradient(135deg, #3b3778, #242142 55%, #fc6d45); display: grid; place-items: center; color: #fff; font-weight: 700; font-size: 13px; letter-spacing: .04em; }
|
||||
.mock .cap { color: #3a3c46; }
|
||||
.chips { display: flex; gap: 6px; flex-wrap: wrap; margin: 12px 0 14px; }
|
||||
.chip { font-size: 12px; font-weight: 600; padding: 3px 9px; border-radius: 999px; background: var(--soft); color: var(--navy); border: 1px solid var(--line); }
|
||||
.mock .bar { display: flex; justify-content: space-between; align-items: center; border-top: 1px solid var(--line); padding-top: 12px; }
|
||||
.pill { font-size: 12px; font-weight: 600; padding: 4px 10px; border-radius: 999px; background: #fff0ea; color: var(--coral-deep); }
|
||||
.mock .approve { height: 34px; font-size: 13.5px; padding: 0 14px; }
|
||||
.avatar { width: 34px; height: 34px; border-radius: 50%; background: var(--soft); border: 1px solid var(--line); display: grid; place-items: center; font-weight: 700; color: var(--navy); font-size: 13px; flex-shrink: 0; }
|
||||
|
||||
/* sections */
|
||||
section.block { padding: 88px 0; }
|
||||
section.alt { background: var(--soft); }
|
||||
.head { max-width: 640px; margin-bottom: 44px; }
|
||||
.head h2 { font-size: clamp(28px, 3.4vw, 38px); line-height: 1.15; font-weight: 800; color: var(--navy); }
|
||||
.head p { color: var(--muted); font-size: 17px; margin: 12px 0 0; }
|
||||
.steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; counter-reset: step; }
|
||||
.step { border-top: 2px solid var(--navy); padding-top: 18px; }
|
||||
.step::before { counter-increment: step; content: "0" counter(step); font: 700 13px "Plus Jakarta Sans", sans-serif; color: var(--coral-deep); }
|
||||
.step h3 { font-size: 18px; margin: 8px 0 6px; color: var(--navy); }
|
||||
.step p { margin: 0; color: var(--muted); font-size: 15px; }
|
||||
.grid3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
|
||||
.card { background: #fff; border: 1px solid var(--line); border-radius: 12px; padding: 22px; }
|
||||
.card h3 { font-size: 17px; color: var(--navy); margin-bottom: 6px; }
|
||||
.card p { margin: 0; color: var(--muted); font-size: 15px; }
|
||||
.platforms { display: flex; flex-wrap: wrap; gap: 10px; }
|
||||
.platforms span { padding: 10px 16px; border-radius: 10px; background: #fff; border: 1px solid var(--line); font-weight: 600; color: var(--navy); font-size: 15px; }
|
||||
.note { color: var(--muted); font-size: 14px; margin-top: 18px; }
|
||||
|
||||
.cta { background: var(--navy); color: #fff; border-radius: 18px; padding: 48px; display: flex; justify-content: space-between; align-items: center; gap: 24px; flex-wrap: wrap; }
|
||||
.cta h2 { font-size: clamp(26px, 3vw, 34px); }
|
||||
.cta p { color: #cfcde3; margin: 8px 0 0; }
|
||||
|
||||
footer { border-top: 1px solid var(--line); padding: 36px 0 48px; font-size: 14px; color: var(--muted); }
|
||||
footer .wrap { display: flex; justify-content: space-between; gap: 24px; flex-wrap: wrap; align-items: center; }
|
||||
footer nav { display: flex; gap: 20px; flex-wrap: wrap; }
|
||||
footer a { text-decoration: none; }
|
||||
footer a:hover { color: var(--ink); text-decoration: underline; }
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.hero .wrap { grid-template-columns: 1fr; padding-top: 56px; padding-bottom: 64px; }
|
||||
.steps { grid-template-columns: 1fr 1fr; }
|
||||
.grid3 { grid-template-columns: 1fr; }
|
||||
nav.links a:not(.btn) { display: none; }
|
||||
}
|
||||
@media (max-width: 560px) {
|
||||
.wrap { padding: 0 16px; }
|
||||
.steps { grid-template-columns: 1fr; }
|
||||
section.block { padding: 64px 0; }
|
||||
.cta { padding: 32px 22px; }
|
||||
--shadow-sm: 0 1px 3px rgba(36, 33, 66, 0.06), 0 1px 2px rgba(36, 33, 66, 0.04);
|
||||
--shadow-md: 0 4px 14px -2px rgba(36, 33, 66, 0.08), 0 2px 6px -1px rgba(36, 33, 66, 0.04);
|
||||
--shadow-lg: 0 14px 28px -5px rgba(36, 33, 66, 0.12), 0 8px 12px -3px rgba(36, 33, 66, 0.06);
|
||||
--shadow-xl: 0 24px 48px -12px rgba(36, 33, 66, 0.22);
|
||||
}
|
||||
|
||||
/* Legal and long-form pages */
|
||||
.prose { max-width: 760px; margin: 0 auto; padding: 56px 24px 88px; }
|
||||
.prose h1 { font-size: clamp(30px, 4vw, 40px); line-height: 1.15; color: var(--navy); margin-bottom: 6px; }
|
||||
.prose .meta { color: var(--muted); font-size: 14px; margin: 0 0 28px; }
|
||||
.prose h2 { font-size: 20px; color: var(--navy); margin: 34px 0 8px; padding-top: 20px; border-top: 1px solid var(--line); }
|
||||
.prose p, .prose li { color: #3a3c46; }
|
||||
.prose ul { padding-left: 1.2em; }
|
||||
.prose li { margin: 6px 0; }
|
||||
.prose a { color: var(--navy-2); }
|
||||
@media (max-width: 560px) { .prose { padding: 40px 16px 64px; } }
|
||||
*, *::before, *::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background: var(--bg);
|
||||
color: var(--ink);
|
||||
font: 16px/1.6 Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5 {
|
||||
font-family: "Plus Jakarta Sans", "Segoe UI", system-ui, sans-serif;
|
||||
letter-spacing: -0.02em;
|
||||
color: var(--navy);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
transition: color 0.15s ease;
|
||||
}
|
||||
|
||||
img, svg {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.wrap {
|
||||
max-width: 1140px;
|
||||
margin: 0 auto;
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
:focus-visible {
|
||||
outline: 2px solid var(--coral);
|
||||
outline-offset: 3px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Buttons
|
||||
========================================================================== */
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 44px;
|
||||
padding: 0 22px;
|
||||
border-radius: 9px;
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
text-decoration: none;
|
||||
border: 1px solid transparent;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
transition: all 0.18s ease;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.btn:active {
|
||||
transform: translateY(1px);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: var(--navy);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background: var(--navy-2);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.btn-coral {
|
||||
background: var(--coral);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.btn-coral:hover {
|
||||
background: #f7582b;
|
||||
color: #ffffff;
|
||||
box-shadow: 0 4px 12px rgba(252, 109, 69, 0.35);
|
||||
}
|
||||
|
||||
.btn-ghost {
|
||||
border-color: var(--line);
|
||||
color: var(--navy);
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.btn-ghost:hover {
|
||||
background: var(--soft);
|
||||
border-color: #d2cfdf;
|
||||
}
|
||||
|
||||
.btn-sm {
|
||||
min-height: 36px;
|
||||
padding: 0 14px;
|
||||
font-size: 13.5px;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.btn-lg {
|
||||
min-height: 50px;
|
||||
padding: 0 28px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Badges, Pills, Chips
|
||||
========================================================================== */
|
||||
.eyebrow {
|
||||
display: inline-block;
|
||||
font-size: 12.5px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
color: var(--coral);
|
||||
margin: 0 0 14px;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
padding: 4px 10px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid var(--line);
|
||||
background: var(--soft);
|
||||
color: var(--navy);
|
||||
}
|
||||
|
||||
.badge-coral {
|
||||
background: var(--coral-light);
|
||||
border-color: #ffd8cc;
|
||||
color: var(--coral-deep);
|
||||
}
|
||||
|
||||
.badge-success {
|
||||
background: #eefaf3;
|
||||
border-color: #c7eed6;
|
||||
color: #1a7f45;
|
||||
}
|
||||
|
||||
.pill {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
padding: 4px 10px;
|
||||
border-radius: 999px;
|
||||
background: var(--coral-light);
|
||||
color: var(--coral-deep);
|
||||
}
|
||||
|
||||
.chips {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.chip {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
padding: 4px 10px;
|
||||
border-radius: 999px;
|
||||
background: var(--soft);
|
||||
color: var(--navy);
|
||||
border: 1px solid var(--line);
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Page Headers (Hero for Inner Pages)
|
||||
========================================================================== */
|
||||
.page-hero {
|
||||
background: var(--navy);
|
||||
color: #ffffff;
|
||||
padding: 72px 0 64px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.page-hero::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: -120px;
|
||||
top: -120px;
|
||||
width: 420px;
|
||||
height: 420px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, rgba(252, 109, 69, 0.22), transparent 70%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.page-hero-inner {
|
||||
max-width: 760px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.page-hero-inner h1 {
|
||||
font-size: clamp(32px, 4.4vw, 48px);
|
||||
line-height: 1.12;
|
||||
font-weight: 800;
|
||||
color: #ffffff;
|
||||
margin: 0 0 16px;
|
||||
}
|
||||
|
||||
.page-hero-inner p.lead {
|
||||
font-size: 18px;
|
||||
line-height: 1.6;
|
||||
color: #cfcde3;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Sections
|
||||
========================================================================== */
|
||||
section.block {
|
||||
padding: 88px 0;
|
||||
}
|
||||
|
||||
section.alt {
|
||||
background: var(--soft);
|
||||
}
|
||||
|
||||
.head {
|
||||
max-width: 680px;
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.head-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.head h2 {
|
||||
font-size: clamp(28px, 3.4vw, 38px);
|
||||
line-height: 1.18;
|
||||
font-weight: 800;
|
||||
color: var(--navy);
|
||||
}
|
||||
|
||||
.head p {
|
||||
color: var(--muted);
|
||||
font-size: 17px;
|
||||
line-height: 1.6;
|
||||
margin: 14px 0 0;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Grids and Cards
|
||||
========================================================================== */
|
||||
.grid2 {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 28px;
|
||||
}
|
||||
|
||||
.grid3 {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.grid4 {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 14px;
|
||||
padding: 28px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-md);
|
||||
border-color: #d5d3e6;
|
||||
}
|
||||
|
||||
.card-icon {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 10px;
|
||||
background: var(--soft);
|
||||
color: var(--coral-deep);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 18px;
|
||||
border: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.card h3 {
|
||||
font-size: 19px;
|
||||
color: var(--navy);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.card p {
|
||||
margin: 0;
|
||||
color: var(--muted);
|
||||
font-size: 15px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Steps */
|
||||
.steps {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 24px;
|
||||
counter-reset: step;
|
||||
}
|
||||
|
||||
.step {
|
||||
border-top: 3px solid var(--navy);
|
||||
padding-top: 22px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.step::before {
|
||||
counter-increment: step;
|
||||
content: "0" counter(step);
|
||||
font: 800 14px "Plus Jakarta Sans", sans-serif;
|
||||
color: var(--coral-deep);
|
||||
letter-spacing: 0.05em;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.step h3 {
|
||||
font-size: 20px;
|
||||
margin: 6px 0 10px;
|
||||
color: var(--navy);
|
||||
}
|
||||
|
||||
.step p {
|
||||
margin: 0;
|
||||
color: var(--muted);
|
||||
font-size: 15px;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Tables
|
||||
========================================================================== */
|
||||
.table-wrap {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 12px;
|
||||
background: #ffffff;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.data-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
text-align: left;
|
||||
font-size: 14.5px;
|
||||
}
|
||||
|
||||
.data-table th,
|
||||
.data-table td {
|
||||
padding: 16px 20px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.data-table th {
|
||||
background: var(--soft);
|
||||
font-family: "Plus Jakarta Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
color: var(--navy);
|
||||
font-size: 13.5px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.data-table tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.data-table tr:hover td {
|
||||
background: #faf9fd;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Form Controls
|
||||
========================================================================== */
|
||||
.form-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 16px;
|
||||
padding: 36px;
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 22px;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: block;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
color: var(--navy);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.form-label .req {
|
||||
color: var(--coral-deep);
|
||||
}
|
||||
|
||||
.form-input,
|
||||
.form-select,
|
||||
.form-textarea {
|
||||
width: 100%;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
padding: 12px 14px;
|
||||
font-family: inherit;
|
||||
font-size: 15px;
|
||||
color: var(--ink);
|
||||
background: #ffffff;
|
||||
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
||||
}
|
||||
|
||||
.form-input:focus,
|
||||
.form-select:focus,
|
||||
.form-textarea:focus {
|
||||
outline: none;
|
||||
border-color: var(--coral);
|
||||
box-shadow: 0 0 0 3px rgba(252, 109, 69, 0.15);
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
resize: vertical;
|
||||
min-height: 120px;
|
||||
}
|
||||
|
||||
.form-help {
|
||||
font-size: 12.5px;
|
||||
color: var(--muted);
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.honeypot {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 0;
|
||||
width: 0;
|
||||
z-index: -1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Prose (Legal & Articles)
|
||||
========================================================================== */
|
||||
.prose {
|
||||
max-width: 760px;
|
||||
margin: 0 auto;
|
||||
padding: 56px 24px 88px;
|
||||
}
|
||||
|
||||
.prose h1 {
|
||||
font-size: clamp(32px, 4vw, 42px);
|
||||
line-height: 1.15;
|
||||
color: var(--navy);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.prose .meta {
|
||||
color: var(--muted);
|
||||
font-size: 14px;
|
||||
margin: 0 0 32px;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.prose h2 {
|
||||
font-size: 22px;
|
||||
color: var(--navy);
|
||||
margin: 40px 0 12px;
|
||||
padding-top: 24px;
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.prose h3 {
|
||||
font-size: 18px;
|
||||
color: var(--navy);
|
||||
margin: 24px 0 8px;
|
||||
}
|
||||
|
||||
.prose p,
|
||||
.prose li {
|
||||
color: #353740;
|
||||
font-size: 16px;
|
||||
line-height: 1.68;
|
||||
}
|
||||
|
||||
.prose ul,
|
||||
.prose ol {
|
||||
padding-left: 1.3em;
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
.prose li {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.prose a {
|
||||
color: var(--navy-2);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 3px;
|
||||
}
|
||||
|
||||
.prose a:hover {
|
||||
color: var(--coral-deep);
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Responsive Breakpoints
|
||||
========================================================================== */
|
||||
@media (max-width: 990px) {
|
||||
.grid4 {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
.steps {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
.grid3 {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.grid2 {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.wrap {
|
||||
padding: 0 18px;
|
||||
}
|
||||
section.block {
|
||||
padding: 60px 0;
|
||||
}
|
||||
.page-hero {
|
||||
padding: 52px 0 44px;
|
||||
}
|
||||
.steps {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.grid4 {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.form-card {
|
||||
padding: 24px 18px;
|
||||
}
|
||||
.prose {
|
||||
padding: 40px 18px 64px;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user