Snapshot: full project state

This commit is contained in:
2026-10-06 23:43:23 -07:00
commit ed212cdbd9
21 changed files with 2090 additions and 0 deletions

57
templates/services.html Normal file
View File

@@ -0,0 +1,57 @@
{% extends "base.html" %}
{% block title %}Services — Supernova{% endblock %}
{% block content %}
<div class="hero" style="padding:48px 0 24px">
<h1 style="font-size:2.4rem">Services</h1>
<p class="sub">Search the catalog. Every boost is fulfilled automatically.</p>
<div class="field" style="max-width:520px;margin:0 auto">
<input id="search" type="text" placeholder="Search — e.g. Instagram likes, TikTok views…" autocomplete="off">
</div>
</div>
<div id="catalog">
{% for cat, items in cats.items() %}
<section class="cat-block" data-cat="{{ cat|lower }}">
<h2 class="section-title">{{ cat }} <span class="muted" style="font-size:0.9rem">({{ items|length }})</span></h2>
<div class="platform-grid">
{% for s in items %}
<div class="card" data-name="{{ s.name|lower }}">
<h3>{{ s.name }}</h3>
<div class="meta">min {{ s.min }} · max {{ "{:,}".format(s.max) }}</div>
<div class="price">${{ "%.2f"|format(s.rate|float) }} <span class="muted" style="font-size:0.8rem">/ 1k</span></div>
<div class="row">
<span class="meta">{% if s.refill %}♻️ refill{% endif %}{% if s.dripfeed %} 💧 dripfeed{% endif %}{% if not s.refill and not s.dripfeed %}·{% endif %}</span>
<a class="btn sm" href="{{ url_for('order', service_id=s.service) }}">Boost →</a>
</div>
</div>
{% endfor %}
</div>
</section>
{% endfor %}
</div>
<div id="no-results" class="center muted" style="display:none;padding:40px 0">No services match your search.</div>
<script>
(function () {
const search = document.getElementById('search');
const cards = document.querySelectorAll('.card[data-name]');
const blocks = document.querySelectorAll('.cat-block');
const noRes = document.getElementById('no-results');
search.addEventListener('input', () => {
const q = search.value.trim().toLowerCase();
let any = false;
cards.forEach(c => {
const hit = !q || c.dataset.name.includes(q);
c.style.display = hit ? '' : 'none';
if (hit) any = true;
});
blocks.forEach(b => {
const has = Array.from(b.querySelectorAll('.card[data-name]')).some(c => c.style.display !== 'none');
b.style.display = has ? '' : 'none';
});
noRes.style.display = any ? 'none' : '';
});
})();
</script>
{% endblock %}