The Amazon Robotics FC Album (Peak Season Deluxe Edition · Remastered at Rate · Now With 40% More Andons): heading, edition line, page title and the hero button; the tracklist shows four songs before it fades; less empty space under the album; on phones the jump button is full width with the song count under the name, so it never runs off the screen
Changes
@@@ -16,7 +16,7 @@ const countWord = WORDS[count] ?? String(count);try {if (/(?:^|[?&])pae2(?:[=&]|$)/.test(location.search)) {document.documentElement.classList.add("pae2");-- document.title = "FC Menu: the album · Alex Frison";++ document.title = "The Amazon Robotics FC Album · Alex Frison";}} catch (e) {}})();@@@ -26,7 +26,8 @@ const countWord = WORDS[count] ?? String(count);<div class="container"><div class="album__head"><div class="eyebrow"><i class="fa-solid fa-hat-cowboy" aria-hidden="true"></i> You found the hat link</div>-- <h2 class="sec-title album__title" id="album-title">{album.title.split(":")[0]}: <em>the album</em></h2>++ <h2 class="sec-title album__title" id="album-title">{album.title.replace(/FC Album$/, "")}<em>FC Album</em></h2>++ <p class="album__edition">({album.edition})</p><p class="sec-lead album__lead">{countWord} parody music videos about life on the floor: rates, andons, scanners, AR and everything in between. Turn it up, then keep scrolling for the grown-up part of the site.</p></div>@@@ -80,14 +81,14 @@ const countWord = WORDS[count] ?? String(count);var list = root.querySelector("[data-album-scroll]");var all = [player.getAttribute("data-first")].concat((player.getAttribute("data-rest") || "").split(",").filter(Boolean));-- // The list shows three tracks and a sliver of the fourth, fading out; the fade leaves the edge++ // The list shows four tracks and a sliver of the fifth, fading out; the fade leaves the edge// that has nothing more to scroll to.function cap() {var rows = list.querySelectorAll("li");-- if (rows.length <= 3) { list.style.removeProperty("--album-cap"); return; }++ if (rows.length <= 4) { list.style.removeProperty("--album-cap"); return; }var top = list.getBoundingClientRect().top - list.scrollTop;-- var third = rows[2].getBoundingClientRect(), fourth = rows[3].getBoundingClientRect();-- var px = Math.round(third.bottom - top + fourth.height * 0.45);++ var last = rows[3].getBoundingClientRect(), peek = rows[4].getBoundingClientRect();++ var px = Math.round(last.bottom - top + peek.height * 0.45);if (px > 0) list.style.setProperty("--album-cap", px + "px");fades();}@@@ -110,7 +111,7 @@ const countWord = WORDS[count] ?? String(count);var src = "https://www.youtube-nocookie.com/embed/" + encodeURIComponent(id) + "?autoplay=1&rel=0&playsinline=1" + (queue ? "&playlist=" + queue.map(encodeURIComponent).join(",") : "");var f = document.createElement("iframe");f.src = src;-- f.title = "FC Menu album player";++ f.title = "The Amazon Robotics FC Album player";f.allow = "autoplay; encrypted-media; picture-in-picture; fullscreen";f.allowFullscreen = true;f.referrerPolicy = "strict-origin-when-cross-origin";@@@ -137,10 +138,13 @@ const countWord = WORDS[count] ?? String(count);<style>.album { display: none; }-- :global(html.pae2) .album { display: block; }++ /* Tight below: the metrics strip that follows has its own top padding. */++ :global(html.pae2) .album { display: block; padding-bottom: clamp(4px, 1vw, 16px); }.album__head { max-width: 760px; margin-bottom: 1.75rem; }.album__head .eyebrow i { margin-right: .35rem; }.album__title em { font-style: normal; background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent; }++ .album__edition { margin-top: .45rem; font: 600 clamp(.95rem, 2vw, 1.25rem)/1.35 var(--font-display); font-style: italic; letter-spacing: -.005em;++ background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent; }.album__lead { margin-top: .75rem; }.album__grid { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: 1.25rem; align-items: start; }.album__stage { padding: 0; overflow: hidden; }@@@ -161,7 +165,7 @@ const countWord = WORDS[count] ?? String(count);.album__list-head { display: flex; align-items: baseline; justify-content: space-between; gap: .75rem; padding: 0 .6rem .5rem; }.album__count { color: var(--dim); font-size: .8rem; }.album__tracks { list-style: none; margin: 0; padding: 0; display: grid; gap: .25rem;-- max-height: var(--album-cap, 15.5rem); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin;++ max-height: var(--album-cap, 20rem); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin;-webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 3.5rem), transparent);mask-image: linear-gradient(to bottom, #000 calc(100% - 3.5rem), transparent); }.album__tracks.is-top { -webkit-mask-image: linear-gradient(to bottom, transparent, #000 2rem, #000 calc(100% - 3.5rem), transparent);@@@ -43,10 +43,12 @@ import fcAlbum from "../data/fc-album.json";<a href={profile.resumePdf} class="btn" data-magnetic data-resume-link><i class="fa-solid fa-file-pdf"></i> Resume PDF</a><a href="#contact" class="btn btn--ghost" data-magnetic><i class="fa-solid fa-paper-plane"></i> Get in touch</a><!-- Only on the FC album visit (?pae2, from the hat): jump straight to the music. -->-- <a href="#album" class="btn hero__album" data-magnetic aria-label={`Jump to the FC album, ${fcAlbum.tracks.length} songs`}>++ <a href="#album" class="btn hero__album" data-magnetic aria-label={`Jump to ${fcAlbum.title}, ${fcAlbum.tracks.length} songs`}><span class="hero__eq" aria-hidden="true"><i></i><i></i><i></i><i></i></span>-- <span>The FC album</span>-- <span class="hero__album-badge" aria-hidden="true">{fcAlbum.tracks.length} songs</span>++ <span class="hero__album-label">++ <span class="hero__album-name">{fcAlbum.title}</span>++ <span class="hero__album-badge" aria-hidden="true">{fcAlbum.tracks.length} songs</span>++ </span><span class="btn__arrow hero__album-arrow" aria-hidden="true">↓</span></a></div>@@@ -200,6 +202,7 @@ import fcAlbum from "../data/fc-album.json";.hero__eq i:nth-child(3) { animation-duration: .8s; animation-delay: -.6s; }.hero__eq i:nth-child(4) { animation-duration: 1.2s; animation-delay: -.15s; }@keyframes eqBar { 0%, 100% { height: 25%; } 50% { height: 100%; } }++ .hero__album-label { display: inline-flex; align-items: center; gap: 10px; }.hero__album-badge {padding: 3px 8px; border-radius: 999px; font: 600 .66rem/1 var(--font-mono); letter-spacing: .08em; text-transform: uppercase;background: rgba(var(--accent-rgb), .16); color: var(--accent); border: 1px solid rgba(var(--accent-rgb), .3);@@@ -207,6 +210,13 @@ import fcAlbum from "../data/fc-album.json";.hero__album .hero__album-arrow { animation: albumNudge 1.5s ease-in-out infinite; }.hero__album:hover .hero__album-arrow { transform: none; }@keyframes albumNudge { 0%, 100% { transform: translateY(-1px); } 50% { transform: translateY(3px); } }++ /* Phones: a full-width button, the song count under the name, and the name free to wrap rather++ than run off the screen. */++ @media (max-width: 520px) {++ :global(html.pae2) .hero__album { width: 100%; padding: 12px 18px; gap: 12px; white-space: normal; line-height: 1.2; text-align: left; }++ .hero__album-label { flex: 1 1 auto; min-width: 0; flex-direction: column; align-items: flex-start; gap: 5px; }++ .hero__eq, .hero__album-arrow { flex: none; }++ }@media (prefers-reduced-motion: reduce) {:global(html.pae2) .hero__album, .hero__eq i, .hero__album .hero__album-arrow { animation: none; }.hero__eq i { height: 70%; }@@@ -1,5 +1,6 @@{-- "title": "FC Menu: the album",++ "title": "The Amazon Robotics FC Album",++ "edition": "Peak Season Deluxe Edition · Remastered at Rate · Now With 40% More Andons","channel": "https://www.youtube.com/@FCMenus","note": "Parody music videos about life on the FC floor: every public video on YouTube channel FCMenu, in upload order (checked 2026-09-24; unlisted ones are left out).","tracks": [
@@ -16,7 +16,7 @@ const countWord = WORDS[count] ?? String(count);
@@ -16,7 +16,7 @@ const countWord = WORDS[count] ?? String(count);
try {
try {
if (/(?:^|[?&])pae2(?:[=&]|$)/.test(location.search)) {
if (/(?:^|[?&])pae2(?:[=&]|$)/.test(location.search)) {
document.documentElement.classList.add("pae2");
document.documentElement.classList.add("pae2");
- document.title = "FC Menu: the album · Alex Frison";
+ document.title = "The Amazon Robotics FC Album · Alex Frison";
}
}
} catch (e) {}
} catch (e) {}
})();
})();
@@ -26,7 +26,8 @@ const countWord = WORDS[count] ?? String(count);
@@ -26,7 +26,8 @@ const countWord = WORDS[count] ?? String(count);
<div class="container">
<div class="container">
<div class="album__head">
<div class="album__head">
<div class="eyebrow"><i class="fa-solid fa-hat-cowboy" aria-hidden="true"></i> You found the hat link</div>
<div class="eyebrow"><i class="fa-solid fa-hat-cowboy" aria-hidden="true"></i> You found the hat link</div>
- <h2 class="sec-title album__title" id="album-title">{album.title.split(":")[0]}: <em>the album</em></h2>
+ <h2 class="sec-title album__title" id="album-title">{album.title.replace(/FC Album$/, "")}<em>FC Album</em></h2>
+ <p class="album__edition">({album.edition})</p>
<p class="sec-lead album__lead">{countWord} parody music videos about life on the floor: rates, andons, scanners, AR and everything in between. Turn it up, then keep scrolling for the grown-up part of the site.</p>
<p class="sec-lead album__lead">{countWord} parody music videos about life on the floor: rates, andons, scanners, AR and everything in between. Turn it up, then keep scrolling for the grown-up part of the site.</p>
</div>
</div>
@@ -80,14 +81,14 @@ const countWord = WORDS[count] ?? String(count);
@@ -80,14 +81,14 @@ const countWord = WORDS[count] ?? String(count);
var list = root.querySelector("[data-album-scroll]");
var list = root.querySelector("[data-album-scroll]");
var all = [player.getAttribute("data-first")].concat((player.getAttribute("data-rest") || "").split(",").filter(Boolean));
var all = [player.getAttribute("data-first")].concat((player.getAttribute("data-rest") || "").split(",").filter(Boolean));
- // The list shows three tracks and a sliver of the fourth, fading out; the fade leaves the edge
+ // The list shows four tracks and a sliver of the fifth, fading out; the fade leaves the edge
// that has nothing more to scroll to.
// that has nothing more to scroll to.
function cap() {
function cap() {
var rows = list.querySelectorAll("li");
var rows = list.querySelectorAll("li");
- if (rows.length <= 3) { list.style.removeProperty("--album-cap"); return; }
+ if (rows.length <= 4) { list.style.removeProperty("--album-cap"); return; }
var top = list.getBoundingClientRect().top - list.scrollTop;
var top = list.getBoundingClientRect().top - list.scrollTop;
- var third = rows[2].getBoundingClientRect(), fourth = rows[3].getBoundingClientRect();
- var px = Math.round(third.bottom - top + fourth.height * 0.45);
+ var last = rows[3].getBoundingClientRect(), peek = rows[4].getBoundingClientRect();
+ var px = Math.round(last.bottom - top + peek.height * 0.45);
if (px > 0) list.style.setProperty("--album-cap", px + "px");
if (px > 0) list.style.setProperty("--album-cap", px + "px");
fades();
fades();
}
}
@@ -110,7 +111,7 @@ const countWord = WORDS[count] ?? String(count);
@@ -110,7 +111,7 @@ const countWord = WORDS[count] ?? String(count);
var src = "https://www.youtube-nocookie.com/embed/" + encodeURIComponent(id) + "?autoplay=1&rel=0&playsinline=1" + (queue ? "&playlist=" + queue.map(encodeURIComponent).join(",") : "");
var src = "https://www.youtube-nocookie.com/embed/" + encodeURIComponent(id) + "?autoplay=1&rel=0&playsinline=1" + (queue ? "&playlist=" + queue.map(encodeURIComponent).join(",") : "");
var f = document.createElement("iframe");
var f = document.createElement("iframe");
f.src = src;
f.src = src;
- f.title = "FC Menu album player";
+ f.title = "The Amazon Robotics FC Album player";
f.allow = "autoplay; encrypted-media; picture-in-picture; fullscreen";
f.allow = "autoplay; encrypted-media; picture-in-picture; fullscreen";
f.allowFullscreen = true;
f.allowFullscreen = true;
f.referrerPolicy = "strict-origin-when-cross-origin";
f.referrerPolicy = "strict-origin-when-cross-origin";
@@ -137,10 +138,13 @@ const countWord = WORDS[count] ?? String(count);
@@ -137,10 +138,13 @@ const countWord = WORDS[count] ?? String(count);
<style>
<style>
.album { display: none; }
.album { display: none; }
- :global(html.pae2) .album { display: block; }
+ /* Tight below: the metrics strip that follows has its own top padding. */
+ :global(html.pae2) .album { display: block; padding-bottom: clamp(4px, 1vw, 16px); }
.album__head { max-width: 760px; margin-bottom: 1.75rem; }
.album__head { max-width: 760px; margin-bottom: 1.75rem; }
.album__head .eyebrow i { margin-right: .35rem; }
.album__head .eyebrow i { margin-right: .35rem; }
.album__title em { font-style: normal; background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent; }
.album__title em { font-style: normal; background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent; }
+ .album__edition { margin-top: .45rem; font: 600 clamp(.95rem, 2vw, 1.25rem)/1.35 var(--font-display); font-style: italic; letter-spacing: -.005em;
+ background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent; }
.album__lead { margin-top: .75rem; }
.album__lead { margin-top: .75rem; }
.album__grid { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: 1.25rem; align-items: start; }
.album__grid { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: 1.25rem; align-items: start; }
.album__stage { padding: 0; overflow: hidden; }
.album__stage { padding: 0; overflow: hidden; }
@@ -161,7 +165,7 @@ const countWord = WORDS[count] ?? String(count);
@@ -161,7 +165,7 @@ const countWord = WORDS[count] ?? String(count);
.album__list-head { display: flex; align-items: baseline; justify-content: space-between; gap: .75rem; padding: 0 .6rem .5rem; }
.album__list-head { display: flex; align-items: baseline; justify-content: space-between; gap: .75rem; padding: 0 .6rem .5rem; }
.album__count { color: var(--dim); font-size: .8rem; }
.album__count { color: var(--dim); font-size: .8rem; }
.album__tracks { list-style: none; margin: 0; padding: 0; display: grid; gap: .25rem;
.album__tracks { list-style: none; margin: 0; padding: 0; display: grid; gap: .25rem;
- max-height: var(--album-cap, 15.5rem); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin;
+ max-height: var(--album-cap, 20rem); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin;
-webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 3.5rem), transparent);
-webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 3.5rem), transparent);
mask-image: linear-gradient(to bottom, #000 calc(100% - 3.5rem), transparent); }
mask-image: linear-gradient(to bottom, #000 calc(100% - 3.5rem), transparent); }
.album__tracks.is-top { -webkit-mask-image: linear-gradient(to bottom, transparent, #000 2rem, #000 calc(100% - 3.5rem), transparent);
.album__tracks.is-top { -webkit-mask-image: linear-gradient(to bottom, transparent, #000 2rem, #000 calc(100% - 3.5rem), transparent);
@@ -43,10 +43,12 @@ import fcAlbum from "../data/fc-album.json";
@@ -43,10 +43,12 @@ import fcAlbum from "../data/fc-album.json";
<a href={profile.resumePdf} class="btn" data-magnetic data-resume-link><i class="fa-solid fa-file-pdf"></i> Resume PDF</a>
<a href={profile.resumePdf} class="btn" data-magnetic data-resume-link><i class="fa-solid fa-file-pdf"></i> Resume PDF</a>
<a href="#contact" class="btn btn--ghost" data-magnetic><i class="fa-solid fa-paper-plane"></i> Get in touch</a>
<a href="#contact" class="btn btn--ghost" data-magnetic><i class="fa-solid fa-paper-plane"></i> Get in touch</a>
<!-- Only on the FC album visit (?pae2, from the hat): jump straight to the music. -->
<!-- Only on the FC album visit (?pae2, from the hat): jump straight to the music. -->
- <a href="#album" class="btn hero__album" data-magnetic aria-label={`Jump to the FC album, ${fcAlbum.tracks.length} songs`}>
+ <a href="#album" class="btn hero__album" data-magnetic aria-label={`Jump to ${fcAlbum.title}, ${fcAlbum.tracks.length} songs`}>
<span class="hero__eq" aria-hidden="true"><i></i><i></i><i></i><i></i></span>
<span class="hero__eq" aria-hidden="true"><i></i><i></i><i></i><i></i></span>
- <span>The FC album</span>
- <span class="hero__album-badge" aria-hidden="true">{fcAlbum.tracks.length} songs</span>
+ <span class="hero__album-label">
+ <span class="hero__album-name">{fcAlbum.title}</span>
+ <span class="hero__album-badge" aria-hidden="true">{fcAlbum.tracks.length} songs</span>
+ </span>
<span class="btn__arrow hero__album-arrow" aria-hidden="true">↓</span>
<span class="btn__arrow hero__album-arrow" aria-hidden="true">↓</span>
</a>
</a>
</div>
</div>
@@ -200,6 +202,7 @@ import fcAlbum from "../data/fc-album.json";
@@ -200,6 +202,7 @@ import fcAlbum from "../data/fc-album.json";
.hero__eq i:nth-child(3) { animation-duration: .8s; animation-delay: -.6s; }
.hero__eq i:nth-child(3) { animation-duration: .8s; animation-delay: -.6s; }
.hero__eq i:nth-child(4) { animation-duration: 1.2s; animation-delay: -.15s; }
.hero__eq i:nth-child(4) { animation-duration: 1.2s; animation-delay: -.15s; }
@keyframes eqBar { 0%, 100% { height: 25%; } 50% { height: 100%; } }
@keyframes eqBar { 0%, 100% { height: 25%; } 50% { height: 100%; } }
+ .hero__album-label { display: inline-flex; align-items: center; gap: 10px; }
.hero__album-badge {
.hero__album-badge {
padding: 3px 8px; border-radius: 999px; font: 600 .66rem/1 var(--font-mono); letter-spacing: .08em; text-transform: uppercase;
padding: 3px 8px; border-radius: 999px; font: 600 .66rem/1 var(--font-mono); letter-spacing: .08em; text-transform: uppercase;
background: rgba(var(--accent-rgb), .16); color: var(--accent); border: 1px solid rgba(var(--accent-rgb), .3);
background: rgba(var(--accent-rgb), .16); color: var(--accent); border: 1px solid rgba(var(--accent-rgb), .3);
@@ -207,6 +210,13 @@ import fcAlbum from "../data/fc-album.json";
@@ -207,6 +210,13 @@ import fcAlbum from "../data/fc-album.json";
.hero__album .hero__album-arrow { animation: albumNudge 1.5s ease-in-out infinite; }
.hero__album .hero__album-arrow { animation: albumNudge 1.5s ease-in-out infinite; }
.hero__album:hover .hero__album-arrow { transform: none; }
.hero__album:hover .hero__album-arrow { transform: none; }
@keyframes albumNudge { 0%, 100% { transform: translateY(-1px); } 50% { transform: translateY(3px); } }
@keyframes albumNudge { 0%, 100% { transform: translateY(-1px); } 50% { transform: translateY(3px); } }
+ /* Phones: a full-width button, the song count under the name, and the name free to wrap rather
+ than run off the screen. */
+ @media (max-width: 520px) {
+ :global(html.pae2) .hero__album { width: 100%; padding: 12px 18px; gap: 12px; white-space: normal; line-height: 1.2; text-align: left; }
+ .hero__album-label { flex: 1 1 auto; min-width: 0; flex-direction: column; align-items: flex-start; gap: 5px; }
+ .hero__eq, .hero__album-arrow { flex: none; }
+ }
@media (prefers-reduced-motion: reduce) {
@media (prefers-reduced-motion: reduce) {
:global(html.pae2) .hero__album, .hero__eq i, .hero__album .hero__album-arrow { animation: none; }
:global(html.pae2) .hero__album, .hero__eq i, .hero__album .hero__album-arrow { animation: none; }
.hero__eq i { height: 70%; }
.hero__eq i { height: 70%; }
@@ -1,5 +1,6 @@
@@ -1,5 +1,6 @@
{
{
- "title": "FC Menu: the album",
+ "title": "The Amazon Robotics FC Album",
+ "edition": "Peak Season Deluxe Edition · Remastered at Rate · Now With 40% More Andons",
"channel": "https://www.youtube.com/@FCMenus",
"channel": "https://www.youtube.com/@FCMenus",
"note": "Parody music videos about life on the FC floor: every public video on YouTube channel FCMenu, in upload order (checked 2026-09-24; unlisted ones are left out).",
"note": "Parody music videos about life on the FC floor: every public video on YouTube channel FCMenu, in upload order (checked 2026-09-24; unlisted ones are left out).",
"tracks": [
"tracks": [