Feat: Fixed hero, retract ground, sections below

This commit is contained in:
2025-11-09 06:46:44 -08:00
parent b81be7a41c
commit 03a0db0a5c

View File

@@ -14,14 +14,15 @@
} }
body{overflow-x:hidden} body{overflow-x:hidden}
.scene-wrap{ .scene-wrap{
position:relative; position:fixed;
width:100vw; inset:0;
height:100vh;
display:flex; display:flex;
align-items:flex-end; align-items:flex-end;
justify-content:center; justify-content:center;
background:linear-gradient(to bottom,#bfe7ff 0%,#d8f1ff 35%,#f5fbff 100%); background:linear-gradient(to bottom,#bfe7ff 0%,#d8f1ff 35%,#f5fbff 100%);
overflow:hidden overflow:hidden;
z-index:0;
pointer-events:none
} }
.scene-sky{ .scene-sky{
position:absolute; position:absolute;
@@ -58,14 +59,14 @@
opacity:.82; opacity:.82;
letter-spacing:.06em letter-spacing:.06em
} }
.content{
main{
position:relative; position:relative;
z-index:10; z-index:10;
max-width:960px; max-width:960px;
margin:0 auto; margin:0 auto;
padding:4rem 6vw 5rem; padding:100vh 6vw 5rem;
color:#102331; color:#102331
background:transparent
} }
.section{ .section{
margin-bottom:2.6rem; margin-bottom:2.6rem;
@@ -100,7 +101,7 @@
opacity:.76 opacity:.76
} }
@media(max-width:640px){ @media(max-width:640px){
.content{padding:3rem 5vw 3.6rem} main{padding:100vh 5vw 3.6rem}
.section{margin-bottom:2.1rem;padding:1.1rem 1rem .9rem} .section{margin-bottom:2.1rem;padding:1.1rem 1rem .9rem}
.section h2{font-size:1.0rem} .section h2{font-size:1.0rem}
.section p{font-size:.9rem} .section p{font-size:.9rem}
@@ -159,6 +160,7 @@
<ellipse cx="1105" cy="168" rx="46" ry="24" /> <ellipse cx="1105" cy="168" rx="46" ry="24" />
</g> </g>
<g id="ground-group">
<path <path
id="hill" id="hill"
d="M0,530 d="M0,530
@@ -168,7 +170,6 @@
fill="url(#hillGradient)" fill="url(#hillGradient)"
opacity="0.96" opacity="0.96"
/> />
<path <path
id="land" id="land"
d="M0,560 d="M0,560
@@ -177,7 +178,6 @@
L1440,760 L0,760 Z" L1440,760 L0,760 Z"
fill="url(#landGradient)" fill="url(#landGradient)"
/> />
<path <path
id="dirt" id="dirt"
d="M0,720 d="M0,720
@@ -265,155 +265,126 @@
y="880" y="880"
class="ground-label" class="ground-label"
>FOUNDATION: TRANSPARENT, VERIFIABLE PRIVACY SCORES</text> >FOUNDATION: TRANSPARENT, VERIFIABLE PRIVACY SCORES</text>
</g>
</svg> </svg>
</div> </div>
<main class="content"> <main>
<section class="section"> <section class="section">
<h2>VPN</h2> <h2>VPN</h2>
<p> <p>
<span class="highlight">Mullvad</span> and <span class="highlight">Mullvad</span> and
<span class="highlight">Proton VPN</span> are preferred: strong privacy <span class="highlight">Proton VPN</span>.
posture, public audits, and resistance to invasive data collection.
</p> </p>
</section> </section>
<section class="section"> <section class="section">
<h2>Browser</h2> <h2>Browser</h2>
<p> <p>
<span class="highlight">Firefox</span> (hardened) for daily use. <span class="highlight">Firefox</span> (hardened) and
<span class="highlight">Tor Browser</span> for anonymity-critical <span class="highlight">Tor Browser</span>.
activity.
</p> </p>
</section> </section>
<section class="section"> <section class="section">
<h2>Operating Systems</h2> <h2>Operating Systems</h2>
<p> <p>
<span class="highlight">Qubes OS</span> for strict compartmentalization. <span class="highlight">Qubes OS</span>,
<span class="highlight">Tails</span> for amnesic, Tor-routed sessions. <span class="highlight">Tails</span>,
<span class="highlight">Fedora</span> as a strong general-purpose choice. <span class="highlight">Fedora</span>.
</p> </p>
</section> </section>
<section class="section"> <section class="section">
<h2>Password Management + Auth</h2> <h2>Password Management + Auth</h2>
<p> <p>
<span class="highlight">KeePassXC</span> on desktop (especially Windows), <span class="highlight">KeePassXC</span> (Windows desktop),
<span class="highlight">KeePassDX</span> on mobile, plus <span class="highlight">KeePassDX</span> (mobile),
<span class="highlight">Firefox Password Manager</span> for integrated, <span class="highlight">Firefox Password Manager</span>,
syncable credentials, and <span class="highlight">Proton Pass</span>,
<span class="highlight">Proton Pass</span> + <span class="highlight">Proton Auth</span>.
<span class="highlight">Proton Auth</span> for encrypted, ecosystem-based
secrets and 2FA.
</p> </p>
</section> </section>
<section class="section"> <section class="section">
<h2>Email</h2> <h2>Email</h2>
<p> <p>
<span class="highlight">Proton Mail</span> for end-to-end encrypted, <span class="highlight">Proton Mail</span>.
jurisdiction-conscious mail.
</p> </p>
</section> </section>
<section class="section"> <section class="section">
<h2>File Storage</h2> <h2>File Storage</h2>
<p> <p>
<span class="highlight">Proton Drive</span> for encrypted cloud storage <span class="highlight">Proton Drive</span>.
tied to a privacy-respecting provider.
</p> </p>
</section> </section>
<section class="section"> <section class="section">
<h2>Cryptocurrency</h2> <h2>Cryptocurrency</h2>
<p> <p>
<span class="highlight">Monero</span> first-choice for privacy-focused <span class="highlight">Monero</span> first,
transactions. <span class="highlight">Bitcoin</span> second, <span class="highlight">Bitcoin</span> second.
with strict self-custody and privacy hygiene.
</p> </p>
<p class="warn"> <p class="warn">
Avoid Zcash: Avoid Zcash:
influential figures, including Edward Snowden, have publicly promoted lots of influential people, including Edward Snowden,
it in ways that undermine trust; its model and ecosystem do not align sold out to advertise Zcash; trust and incentives are misaligned.
with this index&apos;s bar for credible privacy.
</p> </p>
</section> </section>
<section class="section"> <section class="section">
<h2>Instant Messaging</h2> <h2>Instant Messaging</h2>
<p> <p>
<span class="highlight">Signal</span> for default end-to-end encrypted <span class="highlight">Signal</span>.
messaging with a strong track record.
</p> </p>
</section> </section>
<section class="section"> <section class="section">
<h2>Web Search</h2> <h2>Web Search</h2>
<p class="muted"> <p class="muted">
No engine currently meets a high enough standard to be recommended Nothing currently good enough to recommend without major caveats.
without significant caveats.
</p> </p>
</section> </section>
<section class="section"> <section class="section">
<h2>Calendar</h2> <h2>Calendar</h2>
<p> <p>
<span class="highlight">Proton Calendar</span> alongside Proton&apos;s <span class="highlight">Proton Calendar</span>.
encrypted ecosystem.
</p> </p>
</section> </section>
<section class="section"> <section class="section">
<h2>Hosting</h2> <h2>Hosting</h2>
<p> <p>
<span class="highlight">ovobox.org</span> as a focused, privacy-forward <span class="highlight">ovobox.org</span>.
hosting option.
</p> </p>
</section> </section>
</main> </main>
<script> <script>
;(()=>{ ;(()=>{
const svg=document.querySelector('.scene-svg') const g=document.getElementById('ground-group')
if(!svg)return if(!g)return
const hill=svg.querySelector('#hill') const max=1
const land=svg.querySelector('#land') const minY=-380
const dirt=svg.querySelector('#dirt') const base=g.transform.baseVal.consolidate()
const label=svg.querySelector('.ground-label') const baseY=base?base.matrix.f:0
const trees=[...svg.querySelectorAll('.tree')] const ensure=()=>{
const base={ if(!g.transform.baseVal.numberOfItems){
hill:hill.getAttribute('d'), const t=g.ownerSVGElement.createSVGTransform()
land:land.getAttribute('d'), t.setTranslate(0,0)
dirt:dirt.getAttribute('d') g.transform.baseVal.appendItem(t)
} }
const baseLabelY=parseFloat(label.getAttribute('y'))
const maxShift=520
const lerp=(a,b,t)=>a+(b-a)*t
const shiftPath=(d,dy)=>{
return d.replace(/(-?\d+(\.\d+)?)/g,(m)=>{
let n=parseFloat(m)
if(isNaN(n))return m
return String(n)
}).replace(/(,)(\d+(\.\d+)?)/g,(m,sep,num)=>{
const y=parseFloat(num)+dy
return sep+String(y)
})
} }
ensure()
const onScroll=()=>{ const onScroll=()=>{
const maxScroll=window.innerHeight*1.4 const h=window.innerHeight||1
const s=Math.min(window.scrollY/maxScroll,1) const p=Math.min(window.scrollY/h,max)
const easing=s*s const eased=p*p
const shift=-maxShift*easing const y=baseY+minY*eased
hill.setAttribute('d',shiftPath(base.hill,shift)) const t=g.transform.baseVal.getItem(0)
land.setAttribute('d',shiftPath(base.land,shift)) t.setTranslate(0,y)
dirt.setAttribute('d',shiftPath(base.dirt,shift))
label.setAttribute('y',baseLabelY+shift)
trees.forEach(t=>{
const ty=t.__baseY||(t.__baseY=parseFloat((t.getAttribute('transform').match(/,([\d.]+)/)||[0,520])[1]))
const nx=ty+shift
t.setAttribute('transform',t.getAttribute('transform').replace(/,([\d.]+)\)/,','+nx+')'))
})
} }
window.addEventListener('scroll',onScroll,{passive:true}) window.addEventListener('scroll',onScroll,{passive:true})
onScroll() onScroll()