iuna

iuna

iuna - experimental mainnet-candidate protocol
git clone https://getiuna.org/git/iuna.git
Log | Files | Refs | README | LICENSE

commit 16d58b672e15189b02e849f78cb7058b062601f1
parent a247d44d7734229de02addbf9923c38e1f50d00a
Author: Joris Hartog <jorishartog@hotmail.com>
Date:   Thu,  3 Sep 2026 09:46:20 +0200

Modernize website section navigation

Diffstat:
Mwww/assets/static-listing.css | 14++++++++++++++
Mwww/downloads.html | 4++++
Mwww/index.html | 379+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
3 files changed, 333 insertions(+), 64 deletions(-)

diff --git a/www/assets/static-listing.css b/www/assets/static-listing.css @@ -11,6 +11,7 @@ --text: #edf2f5; --green: #d5f55f; --cyan: #8de9cd; + --amber: #ffd070; } * { box-sizing: border-box; } @@ -398,6 +399,19 @@ body > h3 { font-size: 13px; } +.safety-note { + border: 1px solid rgba(255, 208, 112, .24); + border-left: 3px solid var(--amber); + border-radius: 0 10px 10px 0; + padding: 14px 16px; + background: rgba(255, 208, 112, .055); + color: #ddd5c5; + font-size: 15px; + line-height: 1.55; +} + +.safety-note code { color: #ffe2a3; } + .source-build { margin-top: 28px; } diff --git a/www/downloads.html b/www/downloads.html @@ -44,6 +44,10 @@ <p class="checksum-link"><a href="/downloads/SHA256SUMS">SHA256 checksums</a></p> + <aside class="safety-note"> + <strong>Public peer safety:</strong> expose only the P2P listener on TCP port <code>9444</code>; keep the management UI local or behind strict access control. + </aside> + <section class="source-build"> <h2>Build from source</h2> <p class="muted">Clone the repository and run a local release build.</p> diff --git a/www/index.html b/www/index.html @@ -27,7 +27,7 @@ --panel: #15191b; --panel-2: #101315; --line: #273036; - --muted: #98a6ad; + --muted: #a8b5bb; --text: #edf2f5; --green: #d5f55f; --cyan: #8de9cd; @@ -40,18 +40,22 @@ * { box-sizing: border-box; } html { max-width: 100%; - overflow-x: hidden; + overflow-x: clip; + scroll-behavior: smooth; + scroll-padding-top: 64px; } body { margin: 0; max-width: 100%; - overflow-x: hidden; + overflow-x: clip; background: - radial-gradient(circle at 12% 0%, rgba(141, 233, 205, .045), transparent 34rem), + radial-gradient(circle at 12% 0%, rgba(141, 233, 205, .065), transparent 38rem), + radial-gradient(circle at 88% 42%, rgba(139, 220, 255, .035), transparent 32rem), var(--bg); color: var(--text); } a { color: var(--green); text-decoration-thickness: 1px; text-underline-offset: 3px; } + a:focus-visible { outline: 2px solid var(--green); outline-offset: 4px; border-radius: 4px; } code { color: #c7f5ea; overflow-wrap: anywhere; @@ -67,11 +71,11 @@ background: #0b0d0e; box-shadow: inset 0 1px 0 rgba(255, 255, 255, .03); } - .wrap { width: min(1120px, calc(100% - 48px)); margin: 0 auto; } + .wrap { width: min(1240px, calc(100% - 64px)); margin: 0 auto; } .topbar { position: sticky; top: 0; - z-index: 2; + z-index: 100; border-bottom: 1px solid rgba(39, 48, 54, .9); background: rgba(13, 15, 16, .82); backdrop-filter: blur(12px); @@ -84,6 +88,33 @@ align-items: center; min-height: 64px; } + .scroll-progress { + position: fixed; + z-index: 110; + right: 0; + bottom: 0; + left: 0; + height: 3px; + overflow: hidden; + pointer-events: none; + } + .scroll-progress::after { + content: ""; + display: block; + width: 100%; + height: 100%; + background: linear-gradient(90deg, var(--green), var(--cyan)); + box-shadow: 0 0 14px rgba(213, 245, 95, .45); + transform: scaleX(0); + transform-origin: left center; + } + @keyframes reading-progress { from { transform: scaleX(0); } to { transform: scaleX(1); } } + @supports (animation-timeline: scroll()) { + .scroll-progress::after { + animation: reading-progress linear both; + animation-timeline: scroll(root block); + } + } .brand { display: flex; gap: 10px; align-items: center; font-weight: 900; } .mark { position: relative; @@ -117,19 +148,36 @@ .hero { position: relative; isolation: isolate; - padding: 112px 0 80px; + min-height: calc(100svh - 64px); + display: grid; + align-items: center; + padding: clamp(84px, 12vh, 140px) 0; overflow: hidden; } + .hero::before { + content: ""; + position: absolute; + z-index: -1; + inset: 0; + opacity: .16; + background-image: + linear-gradient(rgba(141, 233, 205, .13) 1px, transparent 1px), + linear-gradient(90deg, rgba(141, 233, 205, .13) 1px, transparent 1px); + background-size: 72px 72px; + -webkit-mask-image: linear-gradient(to bottom, transparent, #000 20%, #000 68%, transparent 95%); + mask-image: linear-gradient(to bottom, transparent, #000 20%, #000 68%, transparent 95%); + pointer-events: none; + } .hero::after { content: ""; position: absolute; z-index: -1; - top: 5%; - right: -8%; - width: min(540px, 48vw); + top: -2%; + right: -10%; + width: min(700px, 62vw); aspect-ratio: 1; border-radius: 50%; - background: radial-gradient(circle, rgba(213, 245, 95, .09), rgba(141, 233, 205, .025) 44%, transparent 70%); + background: radial-gradient(circle, rgba(213, 245, 95, .18), rgba(141, 233, 205, .075) 42%, rgba(139, 220, 255, .025) 58%, transparent 72%); pointer-events: none; } .hero-grid { @@ -138,6 +186,34 @@ gap: clamp(36px, 5vw, 72px); align-items: center; } + .scroll-cue { + position: absolute; + bottom: clamp(48px, 7vh, 76px); + left: 50%; + display: inline-flex; + gap: 10px; + align-items: center; + border: 1px solid rgba(213, 245, 95, .2); + border-radius: 999px; + padding: 9px 13px; + background: rgba(13, 15, 16, .62); + color: var(--muted); + font-size: 11px; + font-weight: 850; + letter-spacing: .08em; + text-decoration: none; + text-transform: uppercase; + transform: translateX(-50%); + backdrop-filter: blur(10px); + transition: border-color .18s ease, color .18s ease, background-color .18s ease; + } + .scroll-cue:hover { border-color: rgba(213, 245, 95, .55); background: rgba(21, 25, 27, .9); color: var(--text); } + .scroll-cue span:last-child { + color: var(--green); + font-size: 16px; + animation: scroll-nudge 1.8s ease-in-out infinite; + } + @keyframes scroll-nudge { 0%, 100% { transform: translateY(-2px); } 50% { transform: translateY(4px); } } .hero-grid > * { min-width: 0; } .eyebrow { display: inline-flex; @@ -186,12 +262,13 @@ .candidate-callout::before { content: ""; position: absolute; - top: -1px; - left: 26px; - width: 56px; + top: 0; + left: 50%; + width: 72px; height: 3px; - border-radius: 999px; - background: var(--green); + border-radius: 0 0 999px 999px; + background: linear-gradient(90deg, var(--green), var(--cyan)); + transform: translateX(-50%); pointer-events: none; } .callout-kicker { @@ -259,22 +336,48 @@ text-decoration: none; } .repo-link:hover { color: var(--green); } - section { padding: var(--section-space) 0; border-top: 1px solid rgba(39, 48, 54, .82); } - main section { position: relative; } + section { + min-height: calc(100svh - 64px); + display: grid; + align-items: center; + border-top: 1px solid rgba(39, 48, 54, .82); + padding: clamp(92px, 12vh, 148px) 0; + } + main section { position: relative; isolation: isolate; overflow: hidden; } main section:nth-child(even) { background: linear-gradient(180deg, rgba(21, 25, 27, .36), rgba(16, 19, 21, .16)); } .section-head { + position: relative; display: grid; grid-template-columns: minmax(150px, .42fr) minmax(0, 1.58fr); column-gap: clamp(28px, 5vw, 72px); row-gap: 10px; align-items: start; - margin-bottom: clamp(32px, 4vw, 48px); + margin-bottom: clamp(44px, 6vw, 72px); } - .section-head .section-kicker { grid-column: 1; grid-row: 1 / span 2; padding-top: 8px; } + .section-head .section-meta { grid-column: 1; grid-row: 1 / span 2; } .section-head h2, .section-head p { grid-column: 2; } .section-head p { margin: 0; max-width: 680px; font-size: 15px; } + .section-meta { display: grid; gap: 18px; justify-items: start; } + .section-icon { + width: clamp(96px, 10vw, 136px); + height: clamp(96px, 10vw, 136px); + display: none; + place-items: center; + color: var(--cyan); + opacity: .085; + pointer-events: none; + } + .section-icon svg { + width: 100%; + height: 100%; + fill: none; + stroke: currentColor; + stroke-width: 1.8; + stroke-linecap: round; + stroke-linejoin: round; + } .grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; } .card { min-width: 0; @@ -314,7 +417,7 @@ gap: 22px; align-items: baseline; border-bottom: 1px solid var(--line); - padding: 18px 0; + padding: clamp(22px, 3vw, 34px) 0; } .principle-row .tag { width: fit-content; margin: 0; } .principle-row h3 { margin: 0; font-size: 18px; } @@ -327,7 +430,8 @@ align-items: start; border: 1px solid var(--line); border-radius: var(--radius); - padding: 22px; + min-height: 230px; + padding: clamp(22px, 3vw, 30px); background: linear-gradient(145deg, rgba(24, 29, 31, .96), rgba(17, 21, 23, .9)); box-shadow: 0 14px 34px rgba(0, 0, 0, .12); transition: border-color .18s ease, transform .18s ease, box-shadow .18s ease; @@ -409,18 +513,50 @@ .trust-link span:last-child { color: var(--green); } .trust-link:hover { color: var(--green); } .community-panel { - display: flex; - justify-content: space-between; - gap: 24px; + position: relative; + width: min(880px, 100%); + display: grid; + grid-template-columns: minmax(0, 700px); + justify-content: center; + justify-items: center; + gap: 0; align-items: center; - border: 1px solid rgba(213, 245, 95, .4); + overflow: hidden; + margin: 0 auto; + border: 1px solid rgba(141, 233, 205, .2); border-radius: var(--radius-large); - padding: clamp(26px, 4vw, 38px); - background: linear-gradient(110deg, rgba(213, 245, 95, .11), rgba(21, 25, 27, .9) 60%); + padding: clamp(38px, 5vw, 60px); + padding-top: clamp(48px, 6vw, 72px); + padding-bottom: clamp(30px, 3.5vw, 40px); + background: linear-gradient(135deg, rgba(141, 233, 205, .055), rgba(21, 25, 27, .9) 62%); + text-align: center; + } + .community-panel::before { + content: ""; + position: absolute; + top: 0; + left: 50%; + width: 72px; + height: 3px; + border-radius: 0 0 999px 999px; + background: linear-gradient(90deg, var(--green), var(--cyan)); + transform: translateX(-50%); + } + .community-panel .section-kicker { display: inline-block; margin-bottom: 14px; } + .community-panel .section-icon { + top: 24px; + right: 28px; + width: 104px; + height: 104px; + } + .community-panel h2 { margin-bottom: 17px; font-size: clamp(34px, 4vw, 44px); } + .community-panel p { margin: 0 auto; font-size: 15px; } + .community-panel .actions { justify-content: center; margin-top: 30px; } + .community-panel .button.discord { + min-height: 40px; + padding: 0 13px; + box-shadow: 0 8px 22px rgba(88, 101, 242, .12), inset 0 1px 0 rgba(255, 255, 255, .07); } - .community-panel h2 { font-size: 31px; } - .community-panel p { margin: 0; font-size: 15px; } - .community-panel .actions { flex: 0 0 auto; margin-top: 0; } .split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(260px, .54fr); @@ -491,40 +627,92 @@ background: #101315; } .note { - border-left: 3px solid var(--green); - padding-left: 14px; - color: #cbd3d7; + position: relative; + width: fit-content; + max-width: 100%; + overflow: hidden; + margin: 24px auto 0; + border: 1px solid rgba(255, 208, 112, .24); + border-radius: 10px; + padding: 16px; + background: rgba(255, 208, 112, .055); + color: #ddd5c5; font-size: 15px; + white-space: nowrap; + } + .note::before { + content: ""; + position: absolute; + top: 0; + left: 50%; + width: 56px; + height: 3px; + border-radius: 0 0 999px 999px; + background: linear-gradient(90deg, var(--amber), #ffe2a3); + transform: translateX(-50%); + } + .note code { color: #ffe2a3; } + #community { padding: 0; } + .community-content { + width: 100%; + min-height: calc(100svh - 64px); + display: grid; + grid-template-rows: 1fr auto; + align-items: center; } - .footer { padding: 30px 0 54px; color: #87949b; font-size: 14px; } - .footer .wrap { + .footer { + border-top: 1px solid var(--line); + padding: 26px 0; + background: rgba(9, 11, 12, .48); + color: #98a5ab; + font-size: 14px; + } + .footer-inner { display: flex; justify-content: space-between; gap: 14px; flex-wrap: wrap; } @media (max-width: 820px) { - .hero { padding: 64px 0 56px; } + .hero { min-height: auto; padding: 76px 0 84px; } + .scroll-cue { display: none; } + section { min-height: auto; padding: 80px 0; } + #community { padding-top: 80px; } + .community-content { min-height: 0; display: block; } + .footer { margin-top: 48px; } + .note { white-space: normal; } + .note::before { left: 16px; transform: none; } .hero-grid, .split, .grid, .join-panel, .participation-grid, .status-panel, .trust-band { grid-template-columns: 1fr; } .section-head { grid-template-columns: 1fr; row-gap: 8px; } - .section-head .section-kicker, .section-head h2, .section-head p { grid-column: 1; grid-row: auto; } - .section-head .section-kicker { padding-top: 0; } + .section-head .section-meta, .section-head h2, .section-head p { grid-column: 1; grid-row: auto; } .principle-row { grid-template-columns: 1fr; gap: 8px; align-items: start; } .mechanism-flow { grid-template-columns: 1fr; } .mechanism-step, .mechanism-step:first-child, .mechanism-step:last-child { padding: 18px 0; } .mechanism-step + .mechanism-step { border-top: 1px solid var(--line); border-left: 0; } .mechanism-number { margin-bottom: 10px; } .candidate-callout { max-width: none; justify-self: stretch; } + .candidate-callout::before { left: 28px; transform: none; } nav { display: none; } - .wrap { width: min(100% - 32px, 1120px); } + .wrap { width: min(100% - 32px, 1240px); } h1 { font-size: clamp(36px, 11.5vw, 62px); } .lead { font-size: 19px; } .button { max-width: 100%; justify-content: center; } .role-list { border-left: 0; border-top: 1px solid var(--line); padding-left: 0; padding-top: 16px; } - .community-panel { align-items: stretch; flex-direction: column; } + .community-panel { justify-items: stretch; text-align: left; } + .community-panel::before { left: 28px; transform: none; } .community-panel .actions { width: 100%; } .community-panel .button { width: 100%; } } + @media (min-width: 821px) { + html { scroll-snap-type: y mandatory; } + .hero, main > section { scroll-snap-align: start; scroll-snap-stop: always; } + .section-icon { + position: absolute; + top: -22px; + right: 0; + display: grid; + } + } @media (max-width: 520px) { .participation-card { grid-template-columns: 1fr; } .effort { width: fit-content; } @@ -533,7 +721,10 @@ .status-panel { padding: 22px; } } @media (prefers-reduced-motion: reduce) { - .button, .participation-card { transition: none; } + html { scroll-behavior: auto; scroll-snap-type: none; } + .scroll-progress { display: none; } + .scroll-cue span:last-child { animation: none; } + .button, .participation-card, .scroll-cue { transition: none; } .button:hover, .participation-card:hover { transform: none; } } </style> @@ -543,6 +734,12 @@ <symbol id="discord-icon" viewBox="0 0 24 24"> <path d="M19.54 5.34A16.9 16.9 0 0 0 15.35 4a11.7 11.7 0 0 0-.54 1.1 15.8 15.8 0 0 0-4.62 0A11.7 11.7 0 0 0 9.65 4a16.9 16.9 0 0 0-4.19 1.34C2.81 9.28 2.09 13.12 2.45 16.9A16.8 16.8 0 0 0 7.59 19.5a12.8 12.8 0 0 0 1.1-1.79 10.9 10.9 0 0 1-1.73-.83c.14-.1.28-.21.42-.32a12.1 12.1 0 0 0 9.24 0c.14.11.28.22.42.32-.55.32-1.13.6-1.74.83.32.63.69 1.23 1.1 1.79a16.8 16.8 0 0 0 5.15-2.6c.42-4.38-.72-8.18-2.01-11.56ZM9.32 14.57c-1 0-1.82-.92-1.82-2.04 0-1.13.8-2.05 1.82-2.05 1.02 0 1.84.92 1.82 2.05 0 1.12-.8 2.04-1.82 2.04Zm5.36 0c-1 0-1.82-.92-1.82-2.04 0-1.13.8-2.05 1.82-2.05 1.02 0 1.84.92 1.82 2.05 0 1.12-.8 2.04-1.82 2.04Z"></path> </symbol> + <symbol id="idea-icon" viewBox="0 0 24 24"><path d="M6 14a6 6 0 0 1 12 0M12 4v3M2 13h3M19 13h3M4.5 7.2l2.1 2.1M19.5 7.2l-2.1 2.1"></path><path d="m2 21 6.5-8 4 4.5 3-3.5 6.5 7H2Z"></path></symbol> + <symbol id="participate-icon" viewBox="0 0 24 24"><circle cx="9" cy="8" r="3"></circle><circle cx="17" cy="10" r="2.5"></circle><path d="M3.5 20v-1.5A4.5 4.5 0 0 1 8 14h2a4.5 4.5 0 0 1 4.5 4.5V20M14.5 15.2c.6-.4 1.3-.7 2.1-.7h.8a3.6 3.6 0 0 1 3.6 3.6V20"></path></symbol> + <symbol id="mechanism-icon" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"></circle><path d="M12.2 2h-.4a2 2 0 0 0-2 2v.2a2 2 0 0 1-1 1.7l-.4.3a2 2 0 0 1-2 0l-.2-.1a2 2 0 0 0-2.7.7l-.2.4A2 2 0 0 0 4 9.9l.2.1a2 2 0 0 1 1 1.7v.6a2 2 0 0 1-1 1.7l-.2.1a2 2 0 0 0-.7 2.7l.2.4a2 2 0 0 0 2.7.7l.2-.1a2 2 0 0 1 2 0l.4.3a2 2 0 0 1 1 1.7v.2a2 2 0 0 0 2 2h.4a2 2 0 0 0 2-2v-.2a2 2 0 0 1 1-1.7l.4-.3a2 2 0 0 1 2 0l.2.1a2 2 0 0 0 2.7-.7l.2-.4a2 2 0 0 0-.7-2.7l-.2-.1a2 2 0 0 1-1-1.7v-.6a2 2 0 0 1 1-1.7l.2-.1a2 2 0 0 0 .7-2.7l-.2-.4a2 2 0 0 0-2.7-.7l-.2.1a2 2 0 0 1-2 0l-.4-.3a2 2 0 0 1-1-1.7V4a2 2 0 0 0-2-2Z"></path></symbol> + <symbol id="progress-icon" viewBox="0 0 24 24"><path d="m3 5 2 2 4-4M3 12l2 2 4-4M12 6h9M12 13h9M12 20h9"></path><rect x="3" y="18" width="4" height="4" rx=".75"></rect></symbol> + <symbol id="trust-icon" viewBox="0 0 24 24"><path d="M12 2 20 5v6c0 5.2-3.4 9.1-8 11-4.6-1.9-8-5.8-8-11V5l8-3Z"></path><path d="m8.5 12 2.2 2.2 4.8-5"></path></symbol> + <symbol id="community-icon" viewBox="0 0 24 24"><circle cx="12" cy="5" r="2.5"></circle><circle cx="5" cy="18" r="2.5"></circle><circle cx="19" cy="18" r="2.5"></circle><path d="m10.8 7.2-4.6 8.6M13.2 7.2l4.6 8.6M7.5 18h9"></path></symbol> </svg> <div class="topbar"> <div class="wrap"> @@ -556,6 +753,7 @@ </nav> </div> </div> + <div class="scroll-progress" aria-hidden="true"></div> <header class="hero"> <div class="wrap hero-grid"> @@ -577,13 +775,14 @@ <a class="button primary" href="#join">Take part</a> </aside> </div> + <a class="scroll-cue" href="#why"><span>Scroll to explore</span><span aria-hidden="true">↓</span></a> </header> <main> <section id="why"> <div class="wrap"> <div class="section-head"> - <span class="section-kicker">The idea</span> + <div class="section-meta"><span class="section-icon" aria-hidden="true"><svg><use href="#idea-icon"></use></svg></span><span class="section-kicker">The idea</span></div> <h2>What are we trying to change?</h2> <p>Many networks give lasting influence to whoever already controls the most capital or mining scale. iuna tests a different balance: open coin issuance, lightweight finalization, and influence that expires.</p> </div> @@ -610,7 +809,7 @@ <section id="join"> <div class="wrap"> <div class="section-head"> - <span class="section-kicker">Take part</span> + <div class="section-meta"><span class="section-icon" aria-hidden="true"><svg><use href="#participate-icon"></use></svg></span><span class="section-kicker">Take part</span></div> <h2>Choose your level of involvement</h2> <p>Start small or go deep. Every path helps us learn how iuna behaves beyond a controlled test environment.</p> </div> @@ -652,14 +851,14 @@ <span class="effort">Go deep</span> </article> </div> - <p class="note"><strong>Experimental:</strong> only participate with time, hardware, and funds you can afford to risk.<br><strong>Public peer safety:</strong> expose only the P2P listener on TCP port <code>9444</code>; keep the management UI local or behind strict access control.</p> + <p class="note"><strong>Experimental:</strong> only participate with time, hardware, and funds you can afford to risk.</p> </div> </section> <section id="how"> <div class="wrap"> <div class="section-head"> - <span class="section-kicker">Under the hood</span> + <div class="section-meta"><span class="section-icon" aria-hidden="true"><svg><use href="#mechanism-icon"></use></svg></span><span class="section-kicker">Under the hood</span></div> <h2>Three mechanisms, three different jobs</h2> <p>iuna separates coin issuance, block selection, and timing instead of asking one scarce resource to control everything.</p> </div> @@ -689,7 +888,7 @@ <section id="progress"> <div class="wrap"> <div class="section-head"> - <span class="section-kicker">Building in public</span> + <div class="section-meta"><span class="section-icon" aria-hidden="true"><svg><use href="#progress-icon"></use></svg></span><span class="section-kicker">Building in public</span></div> <h2>Progress you can verify</h2> <p>The candidate is not presented as finished. Its rules, release gates, security work, and remaining launch blockers are documented in public.</p> </div> @@ -706,7 +905,7 @@ <div class="status-item"><span class="status-check">✓</span><span>Candidate protocol rules are frozen and documented.</span></div> <div class="status-item"><span class="status-check">✓</span><span>The mainnet-candidate network launched from a fresh genesis with public builds, checksums, and a bootstrap peer.</span></div> <div class="status-item"><span class="status-check">✓</span><span>An independent-node testnet completed its agreed stability window without an unplanned reset.</span></div> - <div class="status-item"><span class="status-check">✓</span><span>Release gates include audits, fuzzing, adversarial tests, recovery scenarios, and a six-node end-to-end network.</span></div> + <div class="status-item"><span class="status-check">✓</span><span>Release gates include audits, fuzzing, adversarial tests, recovery scenarios, and end-to-end testing across multiple independent nodes.</span></div> <div class="status-item"><span class="status-next">→</span><span>The candidate manifest, live recovery evidence, security sign-off, stability window, and promotion decision remain open.</span></div> </div> </div> @@ -716,7 +915,7 @@ <section id="trust"> <div class="wrap"> <div class="section-head"> - <span class="section-kicker">Trust through inspection</span> + <div class="section-meta"><span class="section-icon" aria-hidden="true"><svg><use href="#trust-icon"></use></svg></span><span class="section-kicker">Trust through inspection</span></div> <h2>Do not take the claims on faith</h2> <p>iuna is designed to be inspected. The code, rules, known risks, and launch criteria are available before you decide to participate.</p> </div> @@ -736,26 +935,78 @@ </section> <section id="community"> - <div class="wrap"> - <div class="community-panel"> - <div> - <span class="section-kicker">A network is its participants</span> - <h2>Bring a node, a question, or a way to break it.</h2> - <p>Meet the people testing iuna, share what you observe, and help decide which evidence the candidate still needs.</p> - </div> - <div class="actions"> - <a class="button discord" href="https://discord.gg/JcXRSSDhS" target="_blank" rel="noopener noreferrer"><svg class="button-icon" aria-hidden="true" focusable="false"><use href="#discord-icon"></use></svg><span>Join Discord</span></a> + <div class="community-content"> + <div class="wrap"> + <div class="community-panel"> + <div> + <span class="section-icon" aria-hidden="true"><svg><use href="#community-icon"></use></svg></span> + <span class="section-kicker">A network is its participants</span> + <h2>Bring a node, a question, or a way to break it.</h2> + <p>Meet the people testing iuna, share what you observe, and help decide which evidence the candidate still needs.</p> + </div> + <div class="actions"> + <a class="button discord" href="https://discord.gg/JcXRSSDhS" target="_blank" rel="noopener noreferrer"><svg class="button-icon" aria-hidden="true" focusable="false"><use href="#discord-icon"></use></svg><span>Join Discord</span></a> + </div> </div> </div> + <footer class="footer"> + <div class="wrap footer-inner"> + <span>iuna <span aria-hidden="true">·</span> an open cryptocurrency experiment</span> + <span><a href="/downloads/">Downloads</a> · <a href="/git/iuna/">Source</a> · <a href="https://discord.gg/JcXRSSDhS" target="_blank" rel="noopener noreferrer">Discord</a></span> + </div> + </footer> </div> </section> </main> + <script> + (() => { + const desktopMotion = window.matchMedia('(min-width: 821px) and (prefers-reduced-motion: no-preference)'); + const screens = [...document.querySelectorAll('.hero, main > section')]; + const headerOffset = 64; + const gestureThreshold = 32; + let accumulatedDelta = 0; + let gestureReset; + let scrollLocked = false; + let lockUntil = 0; + let unlockTimer; - <section class="footer"> - <div class="wrap"> - <span>iuna <span aria-hidden="true">·</span> an open cryptocurrency experiment</span> - <span><a href="/downloads/">Downloads</a> · <a href="/git/iuna/">Source</a> · <a href="https://discord.gg/JcXRSSDhS" target="_blank" rel="noopener noreferrer">Discord</a></span> - </div> - </section> + const scheduleUnlock = () => { + window.clearTimeout(unlockTimer); + unlockTimer = window.setTimeout(() => { scrollLocked = false; }, Math.max(0, lockUntil - performance.now())); + }; + + window.addEventListener('wheel', (event) => { + if (!desktopMotion.matches || event.ctrlKey || Math.abs(event.deltaX) > Math.abs(event.deltaY)) return; + + event.preventDefault(); + if (scrollLocked) { + lockUntil = Math.max(lockUntil, performance.now() + 180); + scheduleUnlock(); + return; + } + + window.clearTimeout(gestureReset); + accumulatedDelta += event.deltaY; + gestureReset = window.setTimeout(() => { accumulatedDelta = 0; }, 160); + + if (Math.abs(accumulatedDelta) < gestureThreshold) return; + + const direction = Math.sign(accumulatedDelta); + accumulatedDelta = 0; + const currentIndex = screens.reduce((closest, screen, index) => { + const distance = Math.abs(screen.getBoundingClientRect().top - headerOffset); + return distance < closest.distance ? { index, distance } : closest; + }, { index: 0, distance: Infinity }).index; + const nextIndex = Math.max(0, Math.min(screens.length - 1, currentIndex + direction)); + + if (nextIndex === currentIndex) return; + + scrollLocked = true; + lockUntil = performance.now() + 800; + scheduleUnlock(); + screens[nextIndex].scrollIntoView({ behavior: 'smooth', block: 'start' }); + }, { passive: false }); + })(); + </script> </body> </html>