Update html/apps.ejs

This commit is contained in:
ashley 2025-08-19 02:23:30 +02:00
parent a149a85207
commit fca44c3670

View File

@ -1,138 +1,344 @@
<!--
This Source Code Form is subject to the terms of the GNU General Public License:
Copyright (C) 2021-2024 PokeTube (https://codeberg.org/Ashley/poketube)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
<!--
Poke Apps — clean landing with video background
License: GNU GPLv3+ (Free Software)
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Poke Apps</title>
<meta content="▶▶ Poke - The Ultimate privacy App!" property=og:title>
<meta content="Poke is more then a youtueb front end - see all the stuff in poke!! :3" property=twitter:description>
<meta content="https://cdn.glitch.global/d68d17bb-f2c0-4bc3-993f-50902734f652/aa70111e-5bcd-4379-8b23-332a33012b78.image.png?v=1701898829884" property="og:image" />
<meta content="summary_large_image" name="twitter:card" />
<link rel="manifest" href="/manifest.json">
<link href="/css/yt-ukraine.svg?v=3" rel="icon" />
<link href="https://p.poketube.fun/https://site-assets.fontawesome.com/releases/v6.1.1/css/all.css" rel="stylesheet" />
<style>
@font-face {
font-family: "PokeTube Flex";
src: url("https://p.poketube.fun/https://cdn.glitch.global/43b6691a-c8db-41d4-921c-8cf6aa0d9108/robotoflex.ttf?v=1668343428681");
font-style: normal;
font-stretch: 1% 800%;
font-display: swap;
}
body {
font-family: "PokeTube flex", sans-serif;
margin: 0;
display: flex;
background-image: radial-gradient(
circle,
#231638,
#2b160e,
#09250e,
#0f132b
);
animation: gradient 64s ease infinite;
background-size: 400% 400%;
min-height: 100vh;
align-items: center;
justify-content: center;
}
h1 {
margin-top: 0;
font-weight: 1000;
font-stretch: ultra-expanded;
font-family: "Poketube flex";
color: #fff;
}
@keyframes gradient {
0% {
background-position: 0 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0 50%;
}
}
.poke-container {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
padding: 16px;
background: #1e1e1e;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.poke-header {
text-align: center;
padding: 16px;
background: #212121;
color: #fff;
border-radius: 8px 8px 0 0;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
grid-column: span 4;
}
.subtext {
color: #b0b0b0;
margin-top: 8px;
}
.poke-app-btn {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 20px;
background: #2c2c2c;
color: #fff;
text-decoration: none;
border-radius: 4px;
font-size: 14px;
transition: background 0.3s ease, color 0.3s ease, box-shadow 0.3s ease;
}
.poke-app-btn:hover {
background: #404040;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
}
.poke-app-btn i {
margin-bottom: 8px;
font-size: 24px;
}
</style>
</head>
<body>
<div class="poke-container">
<div class="poke-header">
<h1>Moar from Poke</h1>
<p class="subtext">Poke is not just a youtube front end - its moar!!</p>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<title>Poke — Apps</title>
<meta name="description" content="Poke is free software: a privacy-first suite with a player, translator, maps, notes, calendar, and more." />
<meta name="theme-color" content="#0d0f14" id="themeColorMeta" />
<meta property="og:type" content="website" />
<meta property="og:title" content="Poke — Apps" />
<meta property="og:description" content="Explore the Poke suite: watch, translate, map, take notes, and more — all privacy-first." />
<link rel="icon" href="/css/yt-ukraine.svg?v=3" />
<link href="https://p.poketube.fun/https://site-assets.fontawesome.com/releases/v6.1.1/css/all.css" rel="stylesheet" />
<style>
:root{
--ink:#eef2f8;
--muted:#c4cede;
--accent:#0ea5e9;
--accent-2:#7dd3fc;
--glass:rgba(13,15,20,.52);
--glass-2:rgba(13,15,20,.64);
--ring:0 0 0 3px rgba(14,165,233,.35);
--radius:16px;
--shadow:0 20px 60px rgba(0,0,0,.35);
--maxw:1120px;
}
*{box-sizing:border-box}
html,body{height:100%}
body{
margin:0;
color:var(--ink);
font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Inter, "Noto Sans", Arial, "Apple Color Emoji", "Segoe UI Emoji";
background:#0b0e14;
overflow-x:hidden;
}
/* === Background video === */
.bg{
position:fixed; inset:0; z-index:-2;
background:#0b0e14;
}
.bg video{
position:absolute; inset:0; width:100%; height:100%;
object-fit:cover; object-position:center;
filter:saturate(105%) contrast(102%) brightness(70%);
}
.bg::after{
/* soft vignette + gradient tint so text is readable */
content:""; position:absolute; inset:0; z-index:1;
background:
radial-gradient(1200px 700px at 20% 10%, rgba(14,165,233,.18), transparent 60%),
linear-gradient(180deg, rgba(7,10,16,.75) 0%, rgba(7,10,16,.35) 40%, rgba(7,10,16,.8) 100%),
radial-gradient(80% 60% at 80% 20%, rgba(124,58,237,.12), transparent 60%);
pointer-events:none;
}
/* === Layout === */
.page{
min-height:100dvh;
display:flex; flex-direction:column;
}
/* === Top nav === */
.nav{
position:sticky; top:0; z-index:10;
display:flex; align-items:center; justify-content:space-between;
padding:12px 18px;
max-width:var(--maxw); margin-inline:auto;
backdrop-filter: blur(10px);
background:linear-gradient(180deg, var(--glass-2), transparent);
border-radius:0 0 var(--radius) var(--radius);
}
.brand{
display:flex; align-items:center; gap:10px; font-weight:900; letter-spacing:.2px;
}
.brand img{ width:26px; height:26px; border-radius:6px }
.nav .right{ display:flex; align-items:center; gap:10px }
.search{
display:flex; align-items:center; gap:10px;
background:rgba(255,255,255,.06);
border:1px solid rgba(255,255,255,.13);
border-radius:999px; padding:8px 12px; min-width:260px;
transition:background .2s ease, border-color .2s ease;
}
.search:focus-within{ background:rgba(255,255,255,.10); border-color:rgba(255,255,255,.24); box-shadow:var(--ring) }
.search input{
flex:1; background:transparent; border:0; outline:0; color:var(--ink);
font-size:.95rem
}
.icon-btn{
display:grid; place-items:center; width:38px; height:38px; border-radius:10px;
background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.13);
color:var(--ink); text-decoration:none; transition:transform .15s ease, background .2s ease, border-color .2s ease;
}
.icon-btn:hover{ transform:translateY(-2px); background:rgba(255,255,255,.1); border-color:rgba(255,255,255,.22) }
/* === Hero === */
.hero{
max-width:var(--maxw);
margin: clamp(18px, 5dvh, 56px) auto 0;
padding: clamp(16px, 2.8vw, 28px);
display:grid; gap:18px;
background:linear-gradient(180deg, rgba(255,255,255,.04), rgba(255,255,255,.02));
border:1px solid rgba(255,255,255,.14);
border-radius:var(--radius);
box-shadow:var(--shadow);
backdrop-filter: blur(8px);
}
.kicker{
display:inline-flex; align-items:center; gap:8px;
font-size:12px; letter-spacing:.35px; text-transform:uppercase; color:var(--muted);
background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.18);
padding:8px 12px; border-radius:999px; width:max-content
}
h1.title{
margin:0; line-height:1.04; letter-spacing:.4px;
font-weight:1000; font-size:clamp(30px, 5.6vw, 56px);
text-wrap:balance;
}
.subtitle{
margin:0; color:var(--muted); max-width:70ch; font-size:clamp(15px, 1.7vw, 18px);
}
.cta-row{
display:flex; flex-wrap:wrap; gap:10px; margin-top:6px;
}
.cta{
display:inline-flex; align-items:center; gap:10px; text-decoration:none;
padding:12px 16px; border-radius:12px; font-weight:800; letter-spacing:.2px;
border:1px solid rgba(255,255,255,.22);
background:linear-gradient(180deg, color-mix(in oklab, var(--accent) 88%, #fff), color-mix(in oklab, var(--accent-2) 88%, #fff));
color:#0b0f14;
transition:transform .15s ease, filter .15s ease;
}
.cta:hover{ transform:translateY(-2px); filter:saturate(1.04) }
.ghost{
background:rgba(255,255,255,.06); color:var(--ink);
border:1px solid rgba(255,255,255,.18); font-weight:700;
}
/* === App grid === */
.apps{
max-width:var(--maxw);
margin: 18px auto clamp(24px, 6dvh, 64px);
padding: clamp(10px, 2.4vw, 18px);
display:grid; gap:14px;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.card{
position:relative;
display:flex; flex-direction:column; gap:8px;
text-decoration:none; color:var(--ink);
background:rgba(255,255,255,.06);
border:1px solid rgba(255,255,255,.14);
border-radius:var(--radius);
padding:16px;
transition:transform .15s ease, background .2s ease, border-color .2s ease;
outline: none;
min-height:120px;
backdrop-filter: blur(6px);
}
.card:hover{ transform:translateY(-4px); background:rgba(255,255,255,.1); border-color:rgba(255,255,255,.24) }
.card:focus-visible{ box-shadow:var(--ring) }
.row{ display:flex; align-items:center; gap:12px }
.badge{
display:grid; place-items:center; width:42px; height:42px; border-radius:12px;
background:linear-gradient(180deg, rgba(255,255,255,.22), rgba(255,255,255,.06));
border:1px solid rgba(255,255,255,.22);
color:var(--ink); font-size:20px
}
.name{ font-weight:800; letter-spacing:.2px }
.hint{ color:var(--muted); font-size:.9rem }
.ext{ position:absolute; right:12px; top:12px; color:var(--muted); font-size:.85rem }
/* === Footer === */
footer{
max-width:var(--maxw); margin: 0 auto 28px; padding:12px 18px;
color:var(--muted); text-align:center;
background:linear-gradient(180deg, rgba(255,255,255,.04), rgba(255,255,255,0));
border:1px solid rgba(255,255,255,.12);
border-radius:var(--radius);
backdrop-filter: blur(6px);
}
/* Mobile tweaks */
@media (max-width:720px){
.nav{ padding-inline:12px }
.search{ min-width:0; width:min(58vw, 300px) }
.cta-row{ gap:8px }
.hero{ padding:16px }
}
/* Respect reduced motion */
@media (prefers-reduced-motion: reduce){
*{animation:none !important; transition:none !important}
.bg video{ filter:brightness(.85) }
}
</style>
</head>
<body>
<div class="bg" aria-hidden="true">
<video id="bgvid" autoplay muted loop playsinline preload="auto" poster="/bg-poster.jpg">
<source src="/bg-480.webm" type="video/webm" />
</video>
</div>
<div class="page">
<!-- Top navigation -->
<div class="nav" role="navigation" aria-label="Top">
<div class="brand">
<img src="/css/yt-ukraine.svg?v=3" alt="" />
<span>Poke</span>
</div>
<a href="/game-hub" class="poke-app-btn"><i class="fa-light fa-gamepad"></i>Games</a>
<!-- <a href="/search" class="poke-app-btn"><i class="fa-light fa-search"></i>Search</a> -->
<a href="/translate" class="poke-app-btn"><i class="fa-light fa-language"></i>Translate</a>
<a href="/map" class="poke-app-btn"><i class="fa-light fa-map-marker-alt"></i>Maps</a>
<a href="https://social.poketube.fun" class="poke-app-btn"><i class="fa-brands fa-mastodon"></i>Fediverse</a>
<a href="/calendar" class="poke-app-btn"><i class="fa-light fa-calendar"></i>Calendar</a>
<a href="/app" class="poke-app-btn"><i class="fa-light fa-play"></i>Watch</a>
<a href="/notepad" class="poke-app-btn"><i class="fa-light fa-memo-pad"></i>Pokepad!</a>
<a href="/settings" class="poke-app-btn"><i class="fa-light fa-cogs"></i>Settings</a>
<div class="right">
<form class="search" action="/search" method="get" role="search">
<i class="fa-regular fa-magnifying-glass" aria-hidden="true"></i>
<input type="search" name="query" placeholder="Search videos..." required />
<kbd style="opacity:.7;font-size:.8rem">/</kbd>
</form>
<a class="icon-btn" href="/settings" aria-label="Settings"><i class="fa-regular fa-gear"></i></a>
<a class="icon-btn" href="/account" aria-label="Account"><i class="fa-regular fa-user"></i></a>
</div>
</div>
</body>
<!-- Hero -->
<section class="hero" aria-labelledby="title">
<span class="kicker"><i class="fa-regular fa-shield"></i> Free software · Privacy-first</span>
<h1 id="title" class="title">Poke Apps</h1>
<p class="subtitle">Youtube Front-end, translator, maps, notes, calendar, and moar! and they are cool as heck!!</p>
<div class="cta-row">
<a class="cta" href="/app"><i class="fa-regular fa-compass"></i>Discover!</a>
<a class="cta ghost" href="#apps"><i class="fa-regular fa-grid-2"></i> Browse Apps</a>
</div>
</section>
<!-- Apps grid -->
<nav id="apps" class="apps" aria-label="Apps">
<a class="card" href="/game-hub" aria-label="Games">
<div class="row"><span class="badge"><i class="fa-light fa-gamepad"></i></span><span class="name">Games</span></div>
<span class="hint">Amazing games :3</span>
</a>
<a class="card" href="/translate" aria-label="Translate">
<div class="row"><span class="badge"><i class="fa-light fa-language"></i></span><span class="name">Translate</span></div>
<span class="hint">fast & accurate and free software translation!!</span>
</a>
<a class="card" href="/map" aria-label="Maps">
<div class="row"><span class="badge"><i class="fa-light fa-map-location-dot"></i></span><span class="name">Maps</span></div>
<span class="hint">A good map-view for web!</span>
</a>
<a class="card" href="https://social.poketube.fun" target="_blank" rel="noopener" aria-label="Fediverse (opens in new tab)">
<span class="ext"><i class="fa-regular fa-arrow-up-right-from-square"></i></span>
<div class="row"><span class="badge"><i class="fa-brands fa-mastodon"></i></span><span class="name">Fediverse</span></div>
<span class="hint">Poke Social community</span>
</a>
<a class="card" href="/calendar" aria-label="Calendar">
<div class="row"><span class="badge"><i class="fa-light fa-calendar"></i></span><span class="name">Calendar</span></div>
<span class="hint">NO javascript!!! calender</span>
</a>
<a class="card" href="/notepad" aria-label="Pokepad">
<div class="row"><span class="badge"><i class="fa-light fa-memo-pad"></i></span><span class="name">Pokepad!</span></div>
<span class="hint">End to End encrypted notepad!</span>
</a>
<a class="card" href="/app" aria-label="Watch">
<div class="row"><span class="badge"><i class="fa-light fa-play"></i></span><span class="name">Watch</span></div>
<span class="hint">the biggest part of poke!</span>
</a>
<a class="card" href="/settings" aria-label="Settings">
<div class="row"><span class="badge"><i class="fa-light fa-gear"></i></span><span class="name">Settings</span></div>
<span class="hint">Tune everything</span>
</a>
</nav>
</div>
<script>
// Respect reduced motion silent autoplay on mobile
(function(){
const meta = document.getElementById('themeColorMeta');
const mql = window.matchMedia('(prefers-color-scheme: dark)');
const setBar = () => meta && (meta.content = mql.matches ? '#0b0e14' : '#0b0e14');
setBar(); mql.addEventListener?.('change', setBar);
})();
(function(){
const v = document.getElementById('bgvid');
if(!v) return;
const reduce = matchMedia('(prefers-reduced-motion: reduce)').matches;
if(reduce){ v.pause(); v.removeAttribute('autoplay'); v.currentTime = 0; }
v.muted = true; v.playsInline = true; v.setAttribute('playsinline','');
const tryPlay = () => v.play().catch(()=>{/* ignore */});
document.addEventListener('visibilitychange', ()=>{ if(!document.hidden) tryPlay(); });
window.addEventListener('pointerdown', tryPlay, {once:true, passive:true});
tryPlay();
})();
// Keyboard focus order for cards
(function(){
const cards = Array.from(document.querySelectorAll('.card'));
cards.forEach(c => c.tabIndex = 0);
const gridCols = () => getComputedStyle(document.querySelector('.apps')).gridTemplateColumns.split(' ').length;
cards.forEach((el, idx) => {
el.addEventListener('keydown', e=>{
const cols = gridCols();
let t=null;
if(e.key==='ArrowRight') t=(idx+1)%cards.length;
else if(e.key==='ArrowLeft') t=(idx-1+cards.length)%cards.length;
else if(e.key==='ArrowDown') t=Math.min(cards.length-1, idx+cols);
else if(e.key==='ArrowUp') t=Math.max(0, idx-cols);
else if(e.key==='Home') t=0;
else if(e.key==='End') t=cards.length-1;
else if(e.key==='Enter'||e.key===' '){ e.preventDefault(); el.click(); return; }
if(t!=null){ e.preventDefault(); cards[t].focus(); }
}, {passive:false});
});
})();
// Quick "/" to focus search
(function(){
const input = document.querySelector('.search input');
if(!input) return;
window.addEventListener('keydown', e=>{
if (e.key === '/' && document.activeElement !== input){
e.preventDefault(); input.focus();
}
});
})();
</script>
</body>
</html>