Files
AvianVisitors/avian/frontend/index.html
T
2026-05-28 15:23:26 -07:00

216 lines
9.7 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<title>your birds</title>
<meta name="description" content="A live bird collage from your window.">
<link rel="icon" type="image/png" href="./favicon.png">
<link rel="apple-touch-icon" href="./favicon.png">
<link rel="stylesheet" href="./styles.css">
</head>
<body class="av-local">
<!-- Pill in the top-left slot, only visible on admin overlays
(body.admin-on); CSS in styles.css hides it everywhere else.
href="/" returns to the collage view via a full reload, which is
fine for an off-hot-path control. -->
<a class="return-to-atlas" id="returnToAtlas" href="/" aria-label="back to collage">
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">
<path d="M10 3 L4 8 L10 13"/>
</svg>
collage
</a>
<header class="top">
<div class="window-pick" id="winPick" role="tablist">
<i class="seg-pill" aria-hidden="true"></i>
<button data-h="1" type="button">1H</button>
<button data-h="12" type="button">12H</button>
<button data-h="24" type="button" aria-current="true">24H</button>
<button data-h="168" type="button">7D</button>
<button data-h="1000000" type="button">ALL</button>
</div>
<button class="menu-btn" id="menuBtn">menu</button>
</header>
<aside id="menu-dd" aria-hidden="true">
<div id="dd-locked">
<form class="lock-row" id="unlockForm">
<input id="lockPass" type="password" placeholder="password" autocomplete="current-password">
<button type="submit" aria-label="unlock"></button>
</form>
<p class="lock-hint" id="lockHint">enter password to unlock tools.</p>
</div>
<nav class="menu-items" id="dd-items"></nav>
<p class="built-by">built by <a href="https://theodore.net" target="_blank" rel="noopener">teddy</a> · <a href="https://github.com/Twarner491/AvianVisitors" target="_blank" rel="noopener">github</a></p>
</aside>
<main class="stage">
<header class="static-head">
<button type="button" class="pre" id="aboutLink">your birds</button>
<h1 id="staticTitle">Heard Recently</h1>
</header>
<div class="views" id="views">
<!-- ========== View 1 - Collage ========== -->
<section class="view" id="v0" aria-label="Bird collage">
<div class="gcollage" id="collage"></div>
</section>
<!-- ========== View 2 - Stats ========== -->
<section class="view" id="v1" aria-label="Stats">
<div class="stats-grid">
<div class="stats-timeline" id="statsTimeline">
<!-- Editorial detection timeline. Each column = one species
from the current time window. The black square's vertical
position encodes detection count; the species name + sci
name sit rotated below. Vertical hairlines separate
columns. Hard-rendered by renderStatsTimeline(). -->
</div>
<aside class="stats-side">
<div class="grp">
<h3>By Period</h3>
<small>detections, grouped by recency</small>
<ol id="statsByPeriod"></ol>
</div>
<div class="grp">
<h3>Top Species</h3>
<small id="statsTopSpecCap">most-heard, current window</small>
<ol id="statsTopSpec"></ol>
</div>
<div class="grp">
<h3>First Detections</h3>
<small>newest additions to the life list</small>
<ol id="statsFirstSeen"></ol>
</div>
</aside>
</div>
</section>
<!-- ========== View 3 - Atlas ========== -->
<section class="view" id="v2" aria-label="Atlas">
<div class="atlas-controls">
<div class="atlas-sort" id="atlasSort" role="tablist" aria-label="sort atlas">
<i class="seg-pill" aria-hidden="true"></i>
<button data-sort="count" type="button" aria-current="true" aria-label="most heard">
<svg viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round">
<path d="M2 12 V8"/><path d="M6 12 V5"/><path d="M10 12 V3"/>
</svg>
<span class="tip">most heard</span>
</button>
<button data-sort="recent" type="button" aria-label="most recent">
<svg viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">
<circle cx="7" cy="7" r="5.2"/><path d="M7 4 V7 L9.2 8.3"/>
</svg>
<span class="tip">most recent</span>
</button>
<button data-sort="alpha" type="button" aria-label="alphabetical">
<svg viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round">
<path d="M2.4 11.5 L4 4.5 L5.6 11.5"/><path d="M2.9 9.2 H5.1"/>
<path d="M8.2 11.5 V4.5 H10.4 a1.3 1.3 0 0 1 0 2.6 H8.2"/><path d="M8.2 7.1 H10.6 a1.5 1.5 0 0 1 0 3 H8.2"/>
</svg>
<span class="tip">a → z</span>
</button>
</div>
</div>
<div class="atlas-grid" id="atlasGrid"></div>
</section>
</div>
</main>
<div id="detail-modal" aria-hidden="true" role="dialog" aria-labelledby="modalCommon">
<div class="modal-backdrop" data-close="1"></div>
<article class="modal-card">
<button class="modal-close" type="button" aria-label="Close" data-close="1">×</button>
<div class="modal-grid">
<div class="modal-img">
<img id="modalImg" src="" alt="" loading="eager">
<div class="pose-toggle" id="modalPoseToggle" role="tablist" aria-label="Pose">
<i class="seg-pill" aria-hidden="true"></i>
<button type="button" data-pose="1" aria-label="perched">
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">
<path d="M3.5 6.5 C 4 4, 6 3, 8 4 C 10 3.6, 11.6 4.6, 12 6.5 L 11.5 8 C 11 9.6, 9.4 10.4, 8 10.4 C 6.4 10.4, 4.8 9.6, 4.2 8 Z"/>
<circle cx="10.6" cy="5.7" r=".4" fill="currentColor"/>
<path d="M12 6.2 L 13.6 5.8"/>
<path d="M7.5 10.4 L 7.2 12.2"/>
<path d="M8.6 10.4 L 8.9 12.2"/>
<path d="M2 12.6 H 13"/>
</svg>
<span class="tip">perched</span>
</button>
<button type="button" data-pose="2" aria-label="in flight">
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">
<path d="M1.5 8 Q 4.5 4, 7.5 7.5 Q 11 4, 14.5 8"/>
<path d="M7.5 7.5 L 8 9.5"/>
<circle cx="8.5" cy="7.2" r=".4" fill="currentColor"/>
<path d="M8.6 7 L 10 6.6"/>
</svg>
<span class="tip">in flight</span>
</button>
</div>
</div>
<div class="modal-info">
<h2 id="modalCommon">-</h2>
<p class="sci" id="modalSci"></p>
<div class="modal-stats">
<div><span class="n" id="modalAllTime">-</span><span class="lbl">all time</span></div>
<div id="modalWindowStat"><span class="n" id="modalWindow">-</span><span class="lbl" id="modalWindowLbl">window</span></div>
<div><span class="n" id="modalFirstSeen">-</span><span class="lbl">first heard</span></div>
</div>
<p class="desc placeholder" id="modalDesc">Loading description...</p>
<div class="modal-meta">
<span class="meta-item"><span class="k">genus</span><span class="v" id="modalGenus">-</span></span>
<span class="meta-item"><span class="k">rarity</span><span class="v" id="modalRarity">-</span></span>
</div>
</div>
</div>
<div class="modal-recordings">
<div class="rec-head">
<h3>Recordings</h3>
<span class="rec-count" id="modalRecCount"></span>
</div>
<ol id="modalRecordings">
<li class="rec-empty">Loading recordings...</li>
</ol>
</div>
<div class="modal-actions">
<a id="modalWiki" class="chip ext" target="_blank" rel="noopener">wiki</a>
<a id="modalEbird" class="chip ext" target="_blank" rel="noopener">ebird</a>
</div>
</article>
</div>
<div id="about-modal" aria-hidden="true" role="dialog" aria-labelledby="aboutTitle">
<div class="modal-backdrop" data-close="1"></div>
<div class="about-card" role="document">
<button type="button" class="modal-close" data-close="1" aria-label="close">×</button>
<p class="about-eyebrow">your birds</p>
<h2 id="aboutTitle">The birds outside your window</h2>
<p class="about-body">A tiny microphone identifies every passing bird with Cornell's <a href="https://birdnet.cornell.edu/" target="_blank" rel="noopener">BirdNET</a>. Each species shows up as an illustration in the collage, sized by how often it's been heard.</p>
<button type="button" class="about-explore" data-close="1">explore the birds →</button>
</div>
</div>
<nav class="slider" id="slider" aria-label="View">
<i class="seg-pill" aria-hidden="true"></i>
<button type="button" data-i="0" aria-current="true">collage</button>
<button type="button" data-i="1">stats</button>
<button type="button" data-i="2">atlas</button>
</nav>
<!-- AvianVisitors: empty admin-screen stub. The live JS expects this
element to exist (openAdmin/closeAdmin call setAttribute on it).
Menu items navigate to BirdNET-Pi's stock pages instead of opening
in-app admin views, so this stays empty. -->
<section class="admin-screen" id="adminScreen" aria-hidden="true">
<div class="admin-frame">
<header class="admin-title"><h1 id="adminTitle"></h1></header>
<div class="admin-body" id="adminBody"></div>
</div>
</section>
<script src="./apt.js"></script>
</body>
</html>