diff --git a/site/content/_index.md b/site/content/_index.md
@@ -1,103 +1,95 @@
+++
title = "ommp — Oh My Music Player"
-description = "A terminal music player written in Rust. No MPD, no daemon — point it at ~/Music and press play."
+description = "A terminal music player written in Rust. It plays the files already on your disk, in the terminal you already have open."
template = "landing.html"
[extra]
kicker = "Terminal music player"
-headline = "Point it at ~/Music."
-headline2 = "Press play."
-lede = "No MPD. No daemon. No config file. One binary that reads your tags, draws your album art in the terminal, and keeps your playlists and layout between sessions."
+headline = "Play your own music"
+headline2 = "without leaving the terminal."
+lede = "ommp plays the files already on your disk: the CDs you ripped, the albums you went looking for, the folder you have been adding to for years. One command, and it plays."
-install_primary_label = "Arch Linux"
-install_primary = "yay -S ommp"
+install_primary_label = "Arch Linux"
+install_primary = "yay -S ommp"
install_secondary_label = "Anywhere else"
install_secondary = "cargo install ommp"
-# Each feature is keyed to the accent colour its tab actually uses in
+# ── 1. The artwork ───────────────────────────────────────────────────────
+art_title = "That is your album art, in a terminal."
+art_lede = "The cover comes out of the file itself: the same image your tags have been carrying since you ripped the disc or paid for the download."
+art_body_1 = "In Ghostty, Kitty, WezTerm, Konsole, foot, xterm and Contour, ommp hands the artwork to the terminal's own graphics protocol and it arrives as a real image, grain and gradient intact, sitting in a shell next to your prompt. Terminals without one draw the same sleeve in block characters, coarser, and still recognisably the record you know."
+art_body_2 = "Beside it, thirteen lines saying exactly what is playing, including the ones you went to some trouble over: <b>48.0 kHz</b>, <b>24-bit</b>, <b>Stereo</b>. Nothing there was fetched or guessed. All of it came off your disk, where it has been the whole time."
+
+# ── 2. Nothing to start ──────────────────────────────────────────────────
+start_title = "Nothing to start first."
+start_lede = "No daemon in the background, no service to enable, no file to write before the first note. You type <code>ommp</code>, it reads <code>~/Music</code>, and it plays."
+start_body = "Quit it and nothing of it keeps running. Everything it plays is already on your disk, so there is nothing to sign into, nothing to subscribe to, and nothing that stops working when a company changes its mind."
+skipped = [
+ "Create an account",
+ "Import your library",
+ "systemctl --user enable mpd",
+ "~/.config/mpd/mpd.conf",
+]
+
+# ── 3. Browse ────────────────────────────────────────────────────────────
+browse_title = "Ask it seven ways, or just type."
+browse_lede = "Press <kbd>1</kbd> to <kbd>7</kbd> to move along the tab strip: the queue everything lands in, the directory tree you built yourself, then artists, albums, genre, format and playlists. The same library, seven questions."
+browse_body_1 = "Directories keeps the folders you organised, in the order you organised them. Genre is whatever you wrote in it. Format counts what you have of each: FLAC, MP3, M4A, OGG, WAV, Opus, AAC, WMA."
+browse_body_2 = "When you already know the name, <kbd>Ctrl</kbd>+<kbd>S</kbd> and start typing. The list narrows on every keystroke. Put <code>artist:</code>, <code>album:</code> or <code>genre:</code> in front to say which you meant, or type <code>*.flac</code> for when you own something twice and want the good copy."
+
+# ── 4. Nothing lost ──────────────────────────────────────────────────────
+lost_title = "Nothing quietly disappears."
+lost_lede = "The small decisions are the ones you notice on the second day."
+lost_close = "Volume, shuffle, repeat, your playlists and the pane widths you dragged all come back the way you left them. The track does not. You choose that again."
+
+# ── 5. Keys ──────────────────────────────────────────────────────────────
+keys_title = "h j k l, Space, n."
+keys_lede = "The keys already under your hands in every other window you have open."
+keys_body_1 = "<kbd>j</kbd> and <kbd>k</kbd> move the list, <kbd>g</kbd> and <kbd>G</kbd> jump to the ends, <kbd>h</kbd> and <kbd>l</kbd> move between panes and <kbd>Tab</kbd> does the same. <kbd>Space</kbd> plays and pauses, <kbd>n</kbd> and <kbd>N</kbd> step through the queue, <kbd>+</kbd> and <kbd>-</kbd> take the volume, the arrows seek, <kbd>s</kbd> shuffles, <kbd>r</kbd> repeats, and <kbd>b</kbd> drops the playing track into a playlist. <kbd>Ctrl</kbd>+<kbd>H</kbd> lists every key there is."
+keys_body_2 = "The mouse works too, when your hand is already there: click a tab, double-click a track, <kbd>Ctrl</kbd>-drag a border to resize a pane."
+
+# ── 6. Install ───────────────────────────────────────────────────────────
+install_title = "Install it."
+install_lede = "About 7 MB installed, linked against alsa-lib, glibc and gcc-libs and nothing else, and a 5,000-track library opens in about 18 ms once its tags are cached."
+install_note_1 = "Two things to set while you are here. ommp draws its interface with <a href=\"https://www.nerdfonts.com/\">Nerd Font</a> glyphs, so point your terminal at a Nerd Font or the icons arrive as empty boxes. And album art comes through as a real image in terminals that speak Kitty graphics, Sixel or the iTerm2 protocol; ommp works out which at startup and there is nothing for you to configure. Everywhere else the cover is drawn in blocks."
+install_note_2 = "Linux only, said plainly: it is untested anywhere else and does not compile on Windows. It plays what is on your disk, so there is no streaming, no catalogue and no account, and it does not resume the track you were playing last time."
+install_close = "Then put some music in <code>~/Music</code> and run <code>ommp</code>."
+splash_note = "The notes behind the top of this page are the ones ommp scatters across its splash screen, generated from the same hash the program uses."
+
+# The seven tabs, each in the accent colour it actually uses in
# src/ui/widgets/tab_bar.rs, so the page and the app agree.
-[[extra.features]]
-name = "Queue"
+[[extra.tabs]]
+name = "Queue"
color = "#64DCFF"
-body = "Everything queues by default. Add an album without losing what is playing, drop a track with <code>d</code>, clear it with <code>c</code>."
-
-[[extra.features]]
-name = "Directories"
+[[extra.tabs]]
+name = "Directories"
color = "#78FFB4"
-body = "Browse the folders you actually organised, not a database's idea of them."
-
-[[extra.features]]
-name = "Artists"
+[[extra.tabs]]
+name = "Artists"
color = "#FFB464"
-body = "Grouped by the track artist, exactly as the file is tagged. Untagged files land under one heading instead of vanishing."
-
-[[extra.features]]
-name = "Albums"
+[[extra.tabs]]
+name = "Albums"
color = "#C882FF"
-body = "Paired with the album artist where it is tagged, the track artist where it is not — so two records called <em>Greatest Hits</em> stay two records."
-
-[[extra.features]]
-name = "Genre"
+[[extra.tabs]]
+name = "Genre"
color = "#FF7896"
-body = "Whatever your tags say. ommp reads them, it does not invent them."
-
-[[extra.features]]
-name = "Format"
+[[extra.tabs]]
+name = "Format"
color = "#78C8FF"
-body = "FLAC, MP3, M4A, OGG, WAV, Opus, AAC, WMA — with a count beside each."
-
-[[extra.features]]
-name = "Playlists"
+[[extra.tabs]]
+name = "Playlists"
color = "#FFDC64"
-body = "Create, rename, star a track with <code>b</code>. Saved between sessions, and entries survive a drive that was not mounted."
-
-[[extra.numbers]]
-value = "18 ms"
-label = "to open a 5,000-track library"
-note = "Tags are cached and re-read only when a file's timestamp or size changes. The first scan runs across every core."
-
-[[extra.numbers]]
-value = "0.3 ms"
-label = "per frame at 50,000 tracks"
-note = "Flat, not linear — the browse views are built once when the library loads, not on every redraw."
-
-[[extra.numbers]]
-value = "7 MB"
-label = "one binary, three libraries"
-note = "Links against alsa-lib, glibc and gcc-libs. Nothing to configure, nothing running in the background."
-[[extra.keys]]
-key = "Space"
-desc = "Play / pause"
-[[extra.keys]]
-key = "n / N"
-desc = "Next / previous"
-[[extra.keys]]
-key = "+ / -"
-desc = "Volume"
-[[extra.keys]]
-key = "s / r"
-desc = "Shuffle / repeat"
-[[extra.keys]]
-key = "1–7"
-desc = "Switch tab"
-[[extra.keys]]
-key = "Tab"
-desc = "Cycle pane focus"
-[[extra.keys]]
-key = "Ctrl+S"
-desc = "Search"
-[[extra.keys]]
-key = "Ctrl+H"
-desc = "Every other key"
-
-[[extra.protocols]]
-name = "Kitty graphics"
-terms = "Ghostty, Kitty, WezTerm, Konsole"
-[[extra.protocols]]
-name = "Sixel"
-terms = "foot, WezTerm, xterm, Contour"
-[[extra.protocols]]
-name = "iTerm2"
-terms = "WezTerm, Konsole"
+[[extra.details]]
+color = "#FFB464"
+body = "A file with no tags at all lands under <b>Unknown Artist</b>, where you can still find it."
+[[extra.details]]
+color = "#C882FF"
+body = "An album is paired with its album artist where one is tagged and the track artist where one is not, so two records called <i>Greatest Hits</i> stay two records."
+[[extra.details]]
+color = "#FFDC64"
+body = "A playlist entry pointing at a drive that was not mounted when you started is left alone rather than pruned, and it works again when the drive comes back."
+[[extra.details]]
+color = "#78FFB4"
+body = "Add files to the folder while ommp is running and they turn up. Take some away and they go."
+++
diff --git a/site/static/css/main.css b/site/static/css/main.css
@@ -72,8 +72,8 @@ body {
/* The terminal face is reserved for things that are literally the app:
commands you type, keys you press, tab names, the status bar. */
-code, kbd, .cmd, .kicker, .install-label, .feature-name,
-.number-label, .protocols th, .sb-row { font-family: var(--mono); }
+code, kbd, .cmd, .kicker, .install-label, .tabstrip, .setup,
+.sec-title-mono, .sb-row { font-family: var(--mono); }
a { color: var(--sky); text-underline-offset: .2em; text-decoration-thickness: 1px; }
a:hover { color: var(--cyan); }
@@ -103,8 +103,7 @@ a:hover { color: var(--cyan); }
/* The splash screen, as the page opens on. ommp scatters music notes across a
dark field while it loads (about_modal.rs, render_splash_screen); the tile is
- that same scatter, generated from the same hash by tools/note-field.py. It
- fades out before the screenshot so the two are never competing. */
+ that same scatter, generated from the same hash by tools/note-field.py. */
.hero::before {
content: "";
position: absolute; inset: 0; z-index: 0;
@@ -114,10 +113,10 @@ a:hover { color: var(--cyan); }
radial-gradient(52rem 30rem at 88% 4%, #143C5066, transparent 70%),
url("../img/note-field.png") repeat;
background-size: auto, auto, 370px 740px;
- -webkit-mask-image: linear-gradient(#000 48%, #0000 88%);
- mask-image: linear-gradient(#000 48%, #0000 88%);
+ -webkit-mask-image: linear-gradient(#000 60%, #0000 100%);
+ mask-image: linear-gradient(#000 60%, #0000 100%);
}
-.hero-in, .shot-hero { position: relative; z-index: 1; }
+.hero-in { position: relative; z-index: 1; }
.hero-in { text-align: center; }
@@ -182,11 +181,13 @@ a:hover { color: var(--cyan); }
border: 1px solid var(--line); border-radius: 6px;
}
.shot-hero {
- /* The one element allowed past the wide measure: it is the product. */
- width: min(100% - 2.5rem, 84rem);
- margin: clamp(3rem, 7vw, 5rem) auto 0;
+ /* The one element allowed past the wide measure: it is the product, and it is
+ the first thing you scroll into. */
+ width: min(100% - 2.5rem, 92%, 84rem);
+ margin: clamp(2.5rem, 5vw, 3.5rem) auto clamp(2.5rem, 5vw, 3.5rem);
}
.shot-hero img { box-shadow: 0 2rem 5rem -1.5rem #00000099; }
+.shot-wide { margin-top: clamp(2.5rem, 5vw, 3.5rem); }
/* ── Bands ────────────────────────────────────────────────────────── */
@@ -200,46 +201,24 @@ a:hover { color: var(--cyan); }
line-height: 1.1; letter-spacing: -.02em; margin: 0 0 1rem;
}
.sec-lede { max-width: 44rem; color: var(--ink-2); margin: 0 0 2.5rem; }
+.sec-body { max-width: 44rem; color: var(--ink-2); margin: 0 0 1.1rem; font-size: .9375rem; }
+.sec-body:last-child { margin-bottom: 0; }
-/* ── Features ─────────────────────────────────────────────────────── */
+/* The section that opens the page carries the weight the hero used to. */
+.band-art { padding-top: clamp(2.5rem, 6vw, 4.5rem); }
+.sec-title-lg { font-size: clamp(2rem, 1.3rem + 2.6vw, 3.2rem); }
+.sec-lede-lg { font-size: 1.0625rem; margin-bottom: 0; }
+/* A mono heading, because the heading is keys. */
+.sec-title-mono { font-size: clamp(1.5rem, 1.1rem + 1.5vw, 2.2rem); letter-spacing: 0; }
-.features {
- list-style: none; margin: 0; padding: 0;
- display: grid; gap: 1rem;
- grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
+/* Two columns of prose under a full-width image, so a long explanation does not
+ become one very long line. */
+.two-up {
+ display: grid; gap: clamp(1.5rem, 4vw, 3rem);
+ color: var(--ink-2); font-size: .9375rem;
}
-.feature {
- background: var(--panel);
- border: 1px solid var(--line); border-left: 2px solid var(--accent);
- border-radius: 5px;
- padding: 1.4rem 1.4rem 1.6rem;
-}
-.feature-name {
- display: inline-block; margin-bottom: .6rem;
- color: var(--accent); font-weight: 700; font-size: .9375rem;
- letter-spacing: .04em;
-}
-.feature-body { margin: 0; color: var(--ink-2); font-size: .9375rem; }
-.feature-body code {
- color: var(--sky); background: #1B1140;
- padding: .05em .3em; border-radius: 3px; font-size: .875em;
-}
-.feature-body em { font-style: italic; color: var(--ink); }
-
-/* ── Numbers ──────────────────────────────────────────────────────── */
-
-.numbers {
- margin: 0; display: grid; gap: 2.5rem;
- grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
-}
-.number { border-top: 2px solid var(--violet); padding-top: 1.25rem; }
-.number-value {
- font-family: var(--disp); font-weight: 700;
- font-size: clamp(2.2rem, 1.6rem + 2.4vw, 3.2rem);
- line-height: 1; letter-spacing: -.03em; margin: 0 0 .5rem;
-}
-.number-label { margin: 0 0 .75rem; color: var(--ink); font-size: .9375rem; }
-.number-note { margin: 0; color: var(--ink-2); font-size: .875rem; }
+.two-up p { margin: 0; }
+@media (min-width: 52rem) { .two-up { grid-template-columns: 1fr 1fr; } }
/* ── Split sections ───────────────────────────────────────────────── */
@@ -257,15 +236,54 @@ a:hover { color: var(--cyan); }
.split-reverse .split-text { order: 2; }
}
-.filters { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; }
-.filters code {
- display: inline-block; background: var(--panel); border: 1px solid var(--line);
- padding: .35rem .7rem; border-radius: 4px; font-size: .875rem; color: var(--sky);
+/* ── The setup you skip ───────────────────────────────────────────── */
+
+/* Four things you do not do, struck out, and the one line you do type. The
+ argument is made by the ratio, so nothing here is decorated further. */
+.setup { font-size: .9375rem; }
+.setup-skipped { list-style: none; margin: 0 0 1.5rem; padding: 0; display: grid; gap: .7rem; }
+.setup-skipped li {
+ color: var(--dim);
+ text-decoration: line-through;
+ text-decoration-color: #FF329699;
+ text-decoration-thickness: 1px;
+}
+.setup-real {
+ margin: 0; font-weight: 700; font-size: 1.5rem;
+ background: linear-gradient(100deg, var(--pink), var(--cyan));
+ -webkit-background-clip: text; background-clip: text; color: transparent;
+}
+.setup-real::before { content: "$ "; -webkit-text-fill-color: var(--dim); }
+
+/* ── The tab strip, set as type ────────────────────────────────────── */
+
+/* ommp's own tab bar. Same names, same order, same seven accents it draws them
+ in — the separators included, because that is how the app renders them. */
+.tabstrip {
+ list-style: none; margin: 0 0 2.5rem; padding: 0;
+ display: flex; flex-wrap: wrap; align-items: baseline;
+ font-size: clamp(.875rem, .75rem + .4vw, 1.0625rem); font-weight: 700;
+}
+.tabstrip li { color: var(--accent); }
+.tabstrip li + li::before {
+ content: "│"; color: var(--line); font-weight: 400;
+ margin-inline: .75em; -webkit-text-fill-color: var(--line);
}
-.keys { list-style: none; margin: 0; padding: 0; display: grid; gap: .55rem; }
-.keys li { display: grid; grid-template-columns: 6.5rem 1fr; align-items: baseline; gap: .75rem; }
-.keys span { color: var(--ink-2); font-size: .9375rem; }
+/* ── The small decisions ──────────────────────────────────────────── */
+
+.details {
+ list-style: none; margin: 0 0 2.5rem; padding: 0;
+ display: grid; gap: 1.75rem;
+}
+@media (min-width: 46rem) { .details { grid-template-columns: 1fr 1fr; gap: 2rem 3rem; } }
+.details li {
+ border-top: 2px solid var(--accent); padding-top: 1rem;
+ color: var(--ink-2); font-size: .9375rem;
+}
+.details li b { color: var(--ink); font-weight: 700; }
+.details li i { font-style: italic; color: var(--ink); }
+.details-close { max-width: 44rem; margin: 0; color: var(--ink-2); font-size: .9375rem; }
kbd {
font-family: var(--mono); font-size: .8125rem; font-weight: 700;
@@ -274,19 +292,6 @@ kbd {
display: inline-block; text-align: center;
}
-/* ── Requirements ─────────────────────────────────────────────────── */
-
-.reqs { display: grid; gap: 2.5rem; grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr)); }
-.req h3 { font-family: var(--disp); font-size: 1.25rem; font-weight: 600; margin: 0 0 .75rem; }
-.req p { margin: 0 0 1rem; color: var(--ink-2); font-size: .9375rem; }
-.req code { background: var(--panel); padding: .05em .35em; border-radius: 3px; color: var(--ink); }
-.req-note { font-size: .8125rem; }
-
-.protocols { border-collapse: collapse; width: 100%; margin-bottom: 1rem; font-size: .875rem; }
-.protocols th, .protocols td { text-align: left; padding: .5rem 0; border-bottom: 1px solid var(--line); vertical-align: top; }
-.protocols th { font-weight: 700; color: var(--sky); white-space: nowrap; padding-right: 1.25rem; }
-.protocols td { color: var(--ink-2); }
-
/* ── Install grid ─────────────────────────────────────────────────── */
.install-grid {
@@ -301,6 +306,12 @@ kbd {
.install-card { display: grid; grid-template-rows: auto 1fr; }
.install-card .cmd { white-space: normal; overflow-wrap: anywhere; height: 100%; }
+.install-close { margin: 0 0 2.5rem; font-size: 1.0625rem; }
+/* Everything a person about to type the command needs to know, at the size that
+ says it is not the reason they came. */
+.fine { max-width: 46rem; margin: 0 0 1rem; color: var(--ink-2); font-size: .875rem; }
+.fine:last-child { margin-bottom: 0; }
+
/* ── Footer ───────────────────────────────────────────────────────── */
.foot { border-top: 1px solid var(--line); padding-block: 2.5rem; }
diff --git a/site/templates/landing.html b/site/templates/landing.html
@@ -26,7 +26,7 @@
</head>
<body>
-<a class="skip" href="#what">Skip to content</a>
+<a class="skip" href="#art">Skip to content</a>
<!-- ── Hero ──────────────────────────────────────────────────────────── -->
<header class="hero">
@@ -57,132 +57,126 @@
<a href="https://aur.archlinux.org/packages/ommp">AUR</a>
</p>
</div>
+</header>
+
+<!-- ── 1. The artwork: the first thing you scroll into ────────────────── -->
+<section id="art" class="band band-art" data-section="Album art">
+ <div class="wrap">
+ <h2 class="sec-title sec-title-lg">{{ x.art_title }}</h2>
+ <p class="sec-lede sec-lede-lg">{{ x.art_lede }}</p>
+ </div>
<figure class="shot shot-hero">
- <img src="{{ asset('img/01-main.avif') }}" alt="ommp playing a track: library on the left, queue in the middle, album art and track details on the right"
+ <img src="{{ asset('img/01-main.avif') }}" alt="ommp playing a track: the library on the left, the queue in the middle, and on the right the album cover drawn as a real image above thirteen lines of track detail"
width="3840" height="2160" fetchpriority="high">
</figure>
-</header>
-<!-- ── Features, keyed to the tabs ───────────────────────────────────── -->
-<section id="what" class="band" data-section="Seven ways in">
- <div class="wrap-wide">
- <h2 class="sec-title">Seven ways into the same library</h2>
- <p class="sec-lede">The tab strip across the top is the whole navigation model. Each one is a different question about the same files.</p>
-
- <ul class="features">
- {%- for f in x.features %}
- <li class="feature" style="--accent: {{ f.color }}">
- <span class="feature-name">{{ f.name }}</span>
- <p class="feature-body">{{ f.body | safe }}</p>
- </li>
- {%- endfor %}
- </ul>
- </div>
-</section>
-
-<!-- ── Speed ─────────────────────────────────────────────────────────── -->
-<section class="band band-alt" data-section="Speed">
- <div class="wrap">
- <h2 class="sec-title">Fast enough to forget about</h2>
- <p class="sec-lede">Measured on this machine, not estimated. A library that takes a moment to open is a library you stop opening.</p>
-
- <dl class="numbers">
- {%- for n in x.numbers %}
- <div class="number">
- <dt class="number-value">{{ n.value }}</dt>
- <dd class="number-label">{{ n.label }}</dd>
- <dd class="number-note">{{ n.note }}</dd>
- </div>
- {%- endfor %}
- </dl>
+ <div class="wrap two-up">
+ <p>{{ x.art_body_1 | safe }}</p>
+ <p>{{ x.art_body_2 | safe }}</p>
</div>
</section>
-<!-- ── Search ────────────────────────────────────────────────────────── -->
-<section class="band" data-section="Search">
+<!-- ── 2. Nothing to start ────────────────────────────────────────────── -->
+<section class="band band-alt" data-section="Nothing to start">
<div class="wrap-wide split">
<div class="split-text">
- <h2 class="sec-title">Find it while you type</h2>
- <p class="sec-lede">Results narrow on every keystroke. Narrow further with a field, or by format.</p>
- <ul class="filters">
- <li><code>artist:yorushika</code></li>
- <li><code>album:elma</code></li>
- <li><code>genre:rock</code></li>
- <li><code>*.flac</code></li>
+ <h2 class="sec-title">{{ x.start_title }}</h2>
+ <p class="sec-lede">{{ x.start_lede | safe }}</p>
+ <p class="sec-body">{{ x.start_body }}</p>
+ </div>
+
+ {#- The setup you do not do, struck through, and under it the one line you
+ actually type. Presentational, so it is hidden from assistive tech —
+ the paragraph beside it already says this in words. -#}
+ <div class="setup" aria-hidden="true">
+ <ul class="setup-skipped">
+ {%- for step in x.skipped %}
+ <li>{{ step }}</li>
+ {%- endfor %}
</ul>
+ <p class="setup-real">ommp</p>
</div>
- <figure class="shot">
- <img src="{{ asset('img/03-search.avif') }}" alt="The search overlay filtering a library down to fifty of fifty-two tracks"
- width="3840" height="2160" loading="lazy">
- </figure>
</div>
</section>
-<!-- ── Keys ──────────────────────────────────────────────────────────── -->
-<section class="band band-alt" data-section="Keys">
- <div class="wrap-wide split split-reverse">
- <div class="split-text">
- <h2 class="sec-title">Keys where you expect them</h2>
- <p class="sec-lede">Vim motions for the lists, media keys for the music. The mouse works too — click a tab, double-click a track, <kbd>Ctrl</kbd>-drag a border to resize.</p>
- <ul class="keys">
- {%- for k in x.keys %}
- <li><kbd>{{ k.key }}</kbd><span>{{ k.desc }}</span></li>
- {%- endfor %}
- </ul>
+<!-- ── 3. Browse ──────────────────────────────────────────────────────── -->
+<section class="band" data-section="Browse">
+ <div class="wrap-wide">
+ <h2 class="sec-title">{{ x.browse_title }}</h2>
+ <p class="sec-lede">{{ x.browse_lede | safe }}</p>
+
+ {#- The app's own tab bar, set as type in the app's own tab colours. -#}
+ <ol class="tabstrip">
+ {%- for t in x.tabs %}
+ <li style="--accent: {{ t.color }}">{{ t.name }}</li>
+ {%- endfor %}
+ </ol>
+
+ <div class="two-up">
+ <p>{{ x.browse_body_1 }}</p>
+ <p>{{ x.browse_body_2 | safe }}</p>
</div>
- <figure class="shot">
- <img src="{{ asset('img/02-help.avif') }}" alt="The keybinding overlay, two columns covering playback and navigation"
+
+ <figure class="shot shot-wide">
+ <img src="{{ asset('img/03-search.avif') }}" alt="The search overlay narrowing a library to fifty of its fifty-two tracks as the word yorushika is typed"
width="3840" height="2160" loading="lazy">
</figure>
</div>
</section>
-<!-- ── Requirements ──────────────────────────────────────────────────── -->
-<section class="band" data-section="Before you start">
+<!-- ── 4. Nothing lost ────────────────────────────────────────────────── -->
+<section class="band band-alt" data-section="Nothing lost">
<div class="wrap">
- <h2 class="sec-title">Two things to check first</h2>
+ <h2 class="sec-title">{{ x.lost_title }}</h2>
+ <p class="sec-lede">{{ x.lost_lede }}</p>
- <div class="reqs">
- <div class="req">
- <h3>A Nerd Font</h3>
- <p>The interface is built from <a href="https://www.nerdfonts.com/">Nerd Font</a> icons. Without one they render as empty boxes. Install <code>JetBrainsMono Nerd Font</code> or similar and set it as your terminal font.</p>
- </div>
- <div class="req">
- <h3>A graphics protocol, for album art</h3>
- <p>Cover art is read out of the audio file itself and drawn as a real image where the terminal supports it. ommp detects which protocol is available at startup — there is nothing to configure.</p>
- <table class="protocols">
- <tbody>
- {%- for p in x.protocols %}
- <tr><th scope="row">{{ p.name }}</th><td>{{ p.terms }}</td></tr>
- {%- endfor %}
- </tbody>
- </table>
- <p class="req-note">Anything else falls back to block characters, which still shows the artwork — just coarser. GPU acceleration is unrelated: Alacritty is accelerated and supports none of these; xterm is not and supports Sixel.</p>
- </div>
+ <ul class="details">
+ {%- for d in x.details %}
+ <li style="--accent: {{ d.color }}">{{ d.body | safe }}</li>
+ {%- endfor %}
+ </ul>
+
+ <p class="details-close">{{ x.lost_close }}</p>
+ </div>
+</section>
+
+<!-- ── 5. Keys ────────────────────────────────────────────────────────── -->
+<section class="band" data-section="Keys">
+ <div class="wrap-wide split split-reverse">
+ <div class="split-text">
+ <h2 class="sec-title sec-title-mono">{{ x.keys_title }}</h2>
+ <p class="sec-lede">{{ x.keys_lede }}</p>
+ <p class="sec-body">{{ x.keys_body_1 | safe }}</p>
+ <p class="sec-body">{{ x.keys_body_2 | safe }}</p>
</div>
+ <figure class="shot">
+ <img src="{{ asset('img/02-help.avif') }}" alt="The keybinding overlay open over the player, two columns covering playback and navigation"
+ width="3840" height="2160" loading="lazy">
+ </figure>
</div>
</section>
-<!-- ── Install ───────────────────────────────────────────────────────── -->
+<!-- ── 6. Install ─────────────────────────────────────────────────────── -->
<section class="band band-close" data-section="Install">
<div class="wrap">
- <h2 class="sec-title">Install</h2>
+ <h2 class="sec-title">{{ x.install_title }}</h2>
+
<div class="install-grid">
<div class="install-card">
- <span class="install-label">Arch Linux</span>
- <code class="cmd" data-copy>yay -S ommp</code>
- </div>
- <div class="install-card">
- <span class="install-label">With Rust installed</span>
- <code class="cmd" data-copy>cargo install ommp</code>
+ <span class="install-label">{{ x.install_primary_label }}</span>
+ <code class="cmd" data-copy>{{ x.install_primary }}</code>
</div>
<div class="install-card">
- <span class="install-label">From source</span>
- <code class="cmd" data-copy>git clone https://github.com/sqzer-x/ommp</code>
+ <span class="install-label">{{ x.install_secondary_label }}</span>
+ <code class="cmd" data-copy>{{ x.install_secondary }}</code>
</div>
</div>
- <p class="sec-lede">Then put some music in <code>~/Music</code> and run <code>ommp</code>.</p>
+
+ <p class="install-close">{{ x.install_close | safe }}</p>
+ <p class="fine">{{ x.install_lede }}</p>
+ <p class="fine">{{ x.install_note_1 | safe }}</p>
+ <p class="fine">{{ x.install_note_2 }}</p>
</div>
</section>
@@ -195,6 +189,7 @@
<a href="https://aur.archlinux.org/packages/ommp">AUR</a>
<a href="https://github.com/sqzer-x/ommp/blob/main/LICENSE">Apache 2.0</a>
</nav>
+ <p class="foot-fine">{{ x.splash_note }}</p>
<p class="foot-fine">Built with <a href="https://github.com/sqzer-x/sqzass">sqzass</a>. Copyright 2026 sqzer (hyukjin an).</p>
</div>
</footer>
|