style: fix biome check errors (import order + formatting)

npx biome check reported 14 errors on app/public/assets/css/,
app/public/assets/js/app/ and scripts/:
  - assist/source/organizeImports: scripts/css-content-sources.mjs,
    scripts/css-unused-report.mjs
  - format: 9 CSS files + 3 JS files

Fixed via biome check --write. Verified: npx biome check clean,
npm run build succeeds, PHPUnit 316 tests / 628 assertions pass.
This commit is contained in:
Pontoporeia
2026-09-18 16:26:49 +02:00
parent 554ba3ee8d
commit bfde71caaa
14 changed files with 2772 additions and 2721 deletions
File diff suppressed because it is too large Load Diff
+45 -36
View File
@@ -7,75 +7,84 @@
/* Full-height flex layout: header → main → (optional footer) */ /* Full-height flex layout: header → main → (optional footer) */
html, html,
body { body {
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
} }
/* ── Discreet scrollbars (WebKit / Blink / Firefox) ──────────────── */ /* ── Discreet scrollbars (WebKit / Blink / Firefox) ──────────────── */
/* CSS custom properties defined in colors.css: /* CSS custom properties defined in colors.css:
--scrollbar-thumb, --scrollbar-thumb-hover, --scrollbar-track, --scrollbar-corner */ --scrollbar-thumb, --scrollbar-thumb-hover, --scrollbar-track, --scrollbar-corner */
::-webkit-scrollbar { ::-webkit-scrollbar {
width: var(--scrollbar-width, 5px); width: var(--scrollbar-width, 5px);
height: var(--scrollbar-width, 5px); height: var(--scrollbar-width, 5px);
}
::-webkit-scrollbar-track {
background: var(--scrollbar-track);
}
::-webkit-scrollbar-thumb {
background: var(--scrollbar-thumb);
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--scrollbar-thumb-hover);
}
::-webkit-scrollbar-corner {
background: var(--scrollbar-corner);
} }
::-webkit-scrollbar-track { background: var(--scrollbar-track); }
::-webkit-scrollbar-thumb { background: var(--scrollbar-thumb); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-thumb-hover); }
::-webkit-scrollbar-corner { background: var(--scrollbar-corner); }
html { html {
scrollbar-width: thin; scrollbar-width: thin;
scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track); scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
scrollbar-gutter: stable; scrollbar-gutter: stable;
} }
body { body {
font-family: var(--font-body); font-family: var(--font-body);
font-weight: 300; font-weight: 300;
color: var(--text-primary); color: var(--text-primary);
background: linear-gradient( background: linear-gradient(
180deg, 180deg,
rgba(0, 0, 0, 0) 85%, rgba(0, 0, 0, 0) 85%,
rgba(149, 87, 181, 0.8) 100% rgba(149, 87, 181, 0.8) 100%
); );
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
main { main {
flex: 1; flex: 1;
min-height: 0; min-height: 0;
overflow-wrap: anywhere; overflow-wrap: anywhere;
} }
main * { main * {
overflow-wrap: anywhere; overflow-wrap: anywhere;
word-break: break-word; word-break: break-word;
} }
/* Global heading scale — used by admin + public pages */ /* Global heading scale — used by admin + public pages */
h1 { h1 {
font-size: var(--step-4); font-size: var(--step-4);
} }
h2 { h2 {
font-size: var(--step-3); font-size: var(--step-3);
} }
h3 { h3 {
font-size: var(--step-2); font-size: var(--step-2);
} }
h4 { h4 {
font-size: var(--step-1); font-size: var(--step-1);
} }
h5 { h5 {
font-size: var(--step--1); font-size: var(--step--1);
} }
h6 { h6 {
font-size: var(--step--2); font-size: var(--step--2);
} }
:where(h1, h2, h3, h4, h5, h6) { :where(h1, h2, h3, h4, h5, h6) {
font-family: var(--font-display); font-family: var(--font-display);
font-weight: 400; font-weight: 400;
margin: 0 0 var(--space-m) 0; margin: 0 0 var(--space-m) 0;
line-height: 1.15; line-height: 1.15;
} }
+1 -1
View File
@@ -205,7 +205,7 @@
/* Small arrow below the bubble pointing at the button */ /* Small arrow below the bubble pointing at the button */
.btn[data-tip]::before { .btn[data-tip]::before {
content: ''; content: "";
position: absolute; position: absolute;
left: 50%; left: 50%;
bottom: calc(100% + 4px); bottom: calc(100% + 4px);
+139 -126
View File
@@ -6,82 +6,82 @@
/* ── Header bar ─────────────────────────────────────────────────────── */ /* ── Header bar ─────────────────────────────────────────────────────── */
header { header {
vertical-align: center; vertical-align: center;
flex-shrink: 0; flex-shrink: 0;
background: linear-gradient( background: linear-gradient(
0deg, 0deg,
rgba(192, 93, 225, 1) 0%, rgba(192, 93, 225, 1) 0%,
rgba(51, 191, 135, 1) 66%, rgba(51, 191, 135, 1) 66%,
rgba(60, 133, 108, 1) 100% rgba(60, 133, 108, 1) 100%
); );
} }
/* ── Navigation ────────────────────────────────────────────────────── */ /* ── Navigation ────────────────────────────────────────────────────── */
header nav { header nav {
padding: var(--space-s) var(--space-s); padding: var(--space-s) var(--space-s);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
font-size: var(--step-0); font-size: var(--step-0);
} }
header nav ul { header nav ul {
display: flex; display: flex;
gap: var(--space-l); gap: var(--space-l);
align-items: center; align-items: center;
list-style: none; list-style: none;
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
header nav ul a { header nav ul a {
font-family: var(--font-display); font-family: var(--font-display);
font-size: var(--step--1); font-size: var(--step--1);
letter-spacing: 0.12em; letter-spacing: 0.12em;
text-transform: uppercase; text-transform: uppercase;
color: var(--accent-foreground); color: var(--accent-foreground);
text-decoration: none; text-decoration: none;
padding: var(--space-3xs) var(--space-xs); padding: var(--space-3xs) var(--space-xs);
text-shadow: text-shadow:
0 0 16px var(--header-shadow-strong), 0 0 16px var(--header-shadow-strong),
0 0 32px var(--header-shadow-soft); 0 0 32px var(--header-shadow-soft);
transition: opacity 0.15s; transition: opacity 0.15s;
} }
header nav ul a:hover { header nav ul a:hover {
color: var(--accent-primary); color: var(--accent-primary);
} }
header nav ul a[aria-current="page"] { header nav ul a[aria-current="page"] {
color: var(--accent-primary); color: var(--accent-primary);
border-radius: 0; border-radius: 0;
border-bottom: 2px solid currentColor; border-bottom: 2px solid currentColor;
padding-bottom: 1px; padding-bottom: 1px;
} }
/* ── Logo ───────────────────────────────────────────────────────────── */ /* ── Logo ───────────────────────────────────────────────────────────── */
.nav-logo { .nav-logo {
text-decoration: none; text-decoration: none;
} }
.nav-left-links, .nav-left-links,
.nav-right-links { .nav-right-links {
display: flex; display: flex;
gap: var(--space-l); gap: var(--space-l);
align-items: center; align-items: center;
list-style: none; list-style: none;
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
.nav-top-row { .nav-top-row {
display: contents; display: contents;
} }
.nav-mobile-links { .nav-mobile-links {
display: none; display: none;
} }
/* ── Hamburger menu (pure CSS, checkbox trick) ──────────────────────── */ /* ── Hamburger menu (pure CSS, checkbox trick) ──────────────────────── */
@@ -95,119 +95,132 @@ header nav ul a[aria-current="page"] {
ul.nav-mobile-links ← full dropdown (hidden by default) */ ul.nav-mobile-links ← full dropdown (hidden by default) */
.menu-btn { .menu-btn {
position: absolute; position: absolute;
top: -9999px; top: -9999px;
left: -9999px; left: -9999px;
} }
.menu-icon { .menu-icon {
display: none; display: none;
cursor: pointer; cursor: pointer;
padding: var(--space-2xs) var(--space-s); padding: var(--space-2xs) var(--space-s);
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
/* Middle bar of the burger icon */ /* Middle bar of the burger icon */
.navicon { .navicon {
background: var(--accent-foreground); background: var(--accent-foreground);
display: block; display: block;
height: 2px; height: 2px;
width: 24px; width: 24px;
position: relative; position: relative;
transition: all 0.3s ease-out; transition: all 0.3s ease-out;
} }
.navicon::before, .navicon::before,
.navicon::after { .navicon::after {
content: ""; content: "";
background: var(--accent-foreground); background: var(--accent-foreground);
display: block; display: block;
height: 2px; height: 2px;
width: 100%; width: 100%;
position: absolute; position: absolute;
transition: all 0.3s ease-out; transition: all 0.3s ease-out;
} }
.navicon::before { .navicon::before {
top: -7px; top: -7px;
} }
.navicon::after { .navicon::after {
bottom: -7px; bottom: -7px;
} }
/* ── Mobile (≤ 640px) ───────────────────────────────────────────────── */ /* ── Mobile (≤ 640px) ───────────────────────────────────────────────── */
@media screen and (max-width: 640px) { @media screen and (max-width: 640px) {
header nav[aria-label="Navigation principale"] { header nav[aria-label="Navigation principale"] {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: stretch; align-items: stretch;
padding: 0; padding: 0;
} }
header nav[aria-label="Navigation principale"] .nav-top-row { header nav[aria-label="Navigation principale"] .nav-top-row {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: var(--space-s); padding: var(--space-s);
} }
header nav[aria-label="Navigation principale"] .nav-right-links { header nav[aria-label="Navigation principale"] .nav-right-links {
display: none; display: none;
} }
header nav[aria-label="Navigation principale"] .nav-left-links { header nav[aria-label="Navigation principale"] .nav-left-links {
display: flex; display: flex;
gap: 0; gap: 0;
} }
header nav[aria-label="Navigation principale"] .nav-left-links li:not(:first-child) { header
display: none; nav[aria-label="Navigation principale"]
} .nav-left-links
li:not(:first-child) {
display: none;
}
.menu-icon { .menu-icon {
display: flex; display: flex;
} }
header nav[aria-label="Navigation principale"] .nav-mobile-links { header nav[aria-label="Navigation principale"] .nav-mobile-links {
display: block; display: block;
list-style: none; list-style: none;
margin: 0; margin: 0;
padding: 0; padding: 0;
max-height: 0; max-height: 0;
overflow: hidden; overflow: hidden;
transition: max-height 0.2s ease-out; transition: max-height 0.2s ease-out;
} }
.menu-btn:checked ~ nav[aria-label="Navigation principale"] .nav-mobile-links { .menu-btn:checked
max-height: 300px; ~ nav[aria-label="Navigation principale"]
} .nav-mobile-links {
max-height: 300px;
}
header nav[aria-label="Navigation principale"] .nav-mobile-links li { header nav[aria-label="Navigation principale"] .nav-mobile-links li {
border-top: 1px solid var(--header-nav-active-border); border-top: 1px solid var(--header-nav-active-border);
text-align: left; text-align: left;
} }
header nav[aria-label="Navigation principale"] .nav-mobile-links li a { header nav[aria-label="Navigation principale"] .nav-mobile-links li a {
display: block; display: block;
width: 100%; width: 100%;
padding: var(--space-s) var(--space-s); padding: var(--space-s) var(--space-s);
text-align: left; text-align: left;
} }
/* Animate burger → X */ /* Animate burger → X */
.menu-btn:checked ~ nav[aria-label="Navigation principale"] .menu-icon .navicon { .menu-btn:checked ~ nav[aria-label="Navigation principale"]
background: transparent; .menu-icon
} .navicon {
background: transparent;
}
.menu-btn:checked ~ nav[aria-label="Navigation principale"] .menu-icon .navicon::before { .menu-btn:checked
transform: rotate(-45deg); ~ nav[aria-label="Navigation principale"]
top: 0; .menu-icon
} .navicon::before {
transform: rotate(-45deg);
top: 0;
}
.menu-btn:checked ~ nav[aria-label="Navigation principale"] .menu-icon .navicon::after { .menu-btn:checked
transform: rotate(45deg); ~ nav[aria-label="Navigation principale"]
bottom: 0; .menu-icon
} .navicon::after {
transform: rotate(45deg);
bottom: 0;
}
} }
+12 -4
View File
@@ -39,11 +39,19 @@
} }
/* Indent sub-headings in TOC */ /* Indent sub-headings in TOC */
.toc-list .toc-level-2 { padding-left: var(--space-s); } .toc-list .toc-level-2 {
.toc-list .toc-level-3 { padding-left: var(--space-m); } padding-left: var(--space-s);
}
.toc-list .toc-level-3 {
padding-left: var(--space-m);
}
.toc-list .toc-level-2 a { font-size: var(--step--1); } .toc-list .toc-level-2 a {
.toc-list .toc-level-3 a { font-size: var(--step--2); } font-size: var(--step--1);
}
.toc-list .toc-level-3 a {
font-size: var(--step--2);
}
/* ── Public TOC (details/summary block) ─────────────────────────────────── */ /* ── Public TOC (details/summary block) ─────────────────────────────────── */
.toc { .toc {
+143 -137
View File
@@ -5,56 +5,56 @@
/* Override inherited padding on main-content */ /* Override inherited padding on main-content */
#main-content { #main-content {
padding-top: 0; padding-top: 0;
} }
.page-content { .page-content {
flex: 1; flex: 1;
min-height: 0; min-height: 0;
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
scroll-behavior: smooth; scroll-behavior: smooth;
/* Bottom spacing lives on .page-content > article::after (below): Firefox /* Bottom spacing lives on .page-content > article::after (below): Firefox
drops/clips the scroll container's own padding-bottom in this nested flex drops/clips the scroll container's own padding-bottom in this nested flex
layout, while Chromium honours it — moving the pad into a block pseudo layout, while Chromium honours it — moving the pad into a block pseudo
element keeps both browsers consistent. */ element keeps both browsers consistent. */
padding: var(--space-xl) var(--space-l) 0; padding: var(--space-xl) var(--space-l) 0;
display: grid; display: grid;
grid-template-columns: 180px 1fr; grid-template-columns: 180px 1fr;
gap: var(--space-2xl); gap: var(--space-2xl);
align-items: start; align-items: start;
} }
/* ── TOC styles → components/toc.css (shared with admin) ───────────────── */ /* ── TOC styles → components/toc.css (shared with admin) ───────────────── */
/* Grid column positioning for content pages with sidebar TOC */ /* Grid column positioning for content pages with sidebar TOC */
@media (min-width: 768px) { @media (min-width: 768px) {
.page-content > article { .page-content > article {
grid-column: 2; grid-column: 2;
min-width: 0; min-width: 0;
max-width: 100%; max-width: 100%;
} }
} }
@media (max-width: 767px) { @media (max-width: 767px) {
.page-content { .page-content {
grid-template-columns: 1fr; grid-template-columns: 1fr;
gap: var(--space-l); gap: var(--space-l);
padding: var(--space-m) var(--space-s) 0; padding: var(--space-m) var(--space-s) 0;
} }
.page-content > article { .page-content > article {
grid-column: 1; grid-column: 1;
} }
.toc { .toc {
margin-top: var(--space-s); margin-top: var(--space-s);
} }
} }
/* ── First content child aligns with TOC heading top ───────────────────── */ /* ── First content child aligns with TOC heading top ───────────────────── */
.page-content > article > :first-child { .page-content > article > :first-child {
margin-top: 2.2rem; margin-top: 2.2rem;
} }
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
@@ -62,127 +62,133 @@
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
.page-content > article { .page-content > article {
display: block; display: block;
max-width: 100%; max-width: 100%;
font-family: var(--font-body); font-family: var(--font-body);
font-size: var(--step-0); font-size: var(--step-0);
line-height: 1.6; line-height: 1.6;
color: var(--text-primary); color: var(--text-primary);
font-weight: 300; font-weight: 300;
} }
/* Trailing bottom spacing. Pseudo-element (real content in the scroll area) /* Trailing bottom spacing. Pseudo-element (real content in the scroll area)
rather than the container's padding-bottom, which Firefox clips. */ rather than the container's padding-bottom, which Firefox clips. */
.page-content > article::after { .page-content > article::after {
content: ""; content: "";
display: block; display: block;
height: var(--space-2xl); height: var(--space-2xl);
} }
@media (max-width: 767px) { @media (max-width: 767px) {
.page-content > article::after { .page-content > article::after {
height: var(--space-xl); height: var(--space-xl);
} }
} }
.page-content > article * { .page-content > article * {
max-width: 100%; max-width: 100%;
overflow-wrap: anywhere; overflow-wrap: anywhere;
word-break: break-word; word-break: break-word;
} }
.page-content > article p { .page-content > article p {
margin: 0 0 1em 0; margin: 0 0 1em 0;
} }
.page-content > article p:last-child { .page-content > article p:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
.page-content > article a { .page-content > article a {
color: inherit; color: inherit;
text-decoration: underline; text-decoration: underline;
text-decoration-thickness: 0.08em; text-decoration-thickness: 0.08em;
text-underline-offset: 0.15em; text-underline-offset: 0.15em;
font-weight: 700; font-weight: 700;
} }
.page-content > article a:hover { .page-content > article a:hover {
color: var(--accent-primary); color: var(--accent-primary);
text-decoration-thickness: 0.12em; text-decoration-thickness: 0.12em;
} }
.page-content > article ul, .page-content > article ul,
.page-content > article ol { .page-content > article ol {
padding-left: var(--space-m); padding-left: var(--space-m);
margin-bottom: var(--space-s); margin-bottom: var(--space-s);
} }
.page-content > article li { .page-content > article li {
margin-bottom: 0.3em; margin-bottom: 0.3em;
} }
.page-content > article strong { .page-content > article strong {
font-weight: 700; font-weight: 700;
} }
.page-content > article em { .page-content > article em {
font-style: italic; font-style: italic;
} }
.page-content > article :where(pre, pre code, code) { .page-content > article :where(pre, pre code, code) {
display: block; display: block;
max-width: 100%; max-width: 100%;
overflow-x: auto; overflow-x: auto;
overflow-wrap: normal; overflow-wrap: normal;
word-break: normal; word-break: normal;
font-family: "Courier New", Courier, monospace; font-family: "Courier New", Courier, monospace;
font-size: 0.88em; font-size: 0.88em;
background: color-mix(in srgb, var(--bg-tertiary) 50%, transparent); background: color-mix(in srgb, var(--bg-tertiary) 50%, transparent);
padding: 0.5em 0.75em; padding: 0.5em 0.75em;
border-radius: var(--radius); border-radius: var(--radius);
white-space: pre-wrap; white-space: pre-wrap;
word-wrap: break-word; word-wrap: break-word;
} }
#apropos-intro *, #apropos-intro *,
#apropos-contacts *, #apropos-contacts *,
#apropos-credits * { #apropos-credits * {
overflow-wrap: anywhere; overflow-wrap: anywhere;
word-break: break-word; word-break: break-word;
max-width: 100%; max-width: 100%;
} }
#apropos-contacts, #apropos-contacts,
#apropos-intro { #apropos-intro {
border-bottom: none; border-bottom: none;
} }
/* Section separators (about page only) */ /* Section separators (about page only) */
.page-content > article > section { .page-content > article > section {
/* padding-bottom: var(--space-xl); */ /* padding-bottom: var(--space-xl); */
border-bottom: 1px solid var(--border-primary); border-bottom: 1px solid var(--border-primary);
margin-bottom: var(--space-xl); margin-bottom: var(--space-xl);
} }
.page-content > article > section:last-child { .page-content > article > section:last-child {
border-bottom: none; border-bottom: none;
margin-bottom: 0; margin-bottom: 0;
padding-bottom: var(--space-xl); padding-bottom: var(--space-xl);
} }
/* Scroll margin so anchor links account for the sticky header */ /* Scroll margin so anchor links account for the sticky header */
.page-content > article :where(h1, h2, h3) { .page-content > article :where(h1, h2, h3) {
scroll-margin-top: var(--space-l); scroll-margin-top: var(--space-l);
} }
/* Content-page heading scale — smaller, distinct, no step-system dependency */ /* Content-page heading scale — smaller, distinct, no step-system dependency */
.page-content > article h1 { font-size: clamp(1.7rem, 1.55rem + 0.68vw, 2.1rem); } .page-content > article h1 {
.page-content > article h2 { font-size: clamp(1.35rem, 1.23rem + 0.55vw, 1.65rem); } font-size: clamp(1.7rem, 1.55rem + 0.68vw, 2.1rem);
.page-content > article h3 { font-size: clamp(1.1rem, 1.03rem + 0.34vw, 1.3rem); } }
.page-content > article h2 {
font-size: clamp(1.35rem, 1.23rem + 0.55vw, 1.65rem);
}
.page-content > article h3 {
font-size: clamp(1.1rem, 1.03rem + 0.34vw, 1.3rem);
}
/* Hide CommonMark heading permalink anchors */ /* Hide CommonMark heading permalink anchors */
.heading-permalink { .heading-permalink {
display: none; display: none;
} }
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
@@ -190,12 +196,12 @@
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
.content-section-title { .content-section-title {
font-family: var(--font-display); font-family: var(--font-display);
font-size: clamp(1.35rem, 1.23rem + 0.55vw, 1.65rem); font-size: clamp(1.35rem, 1.23rem + 0.55vw, 1.65rem);
font-weight: 400; font-weight: 400;
color: var(--text-primary); color: var(--text-primary);
margin: 0 0 var(--space-m) 0; margin: 0 0 var(--space-m) 0;
line-height: 1.1; line-height: 1.1;
} }
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
@@ -203,28 +209,28 @@
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
.apropos-contacts-grid { .apropos-contacts-grid {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0; gap: 0;
} }
.apropos-contact-card { .apropos-contact-card {
font-style: normal; font-style: normal;
padding: var(--space-s) 0; padding: var(--space-s) 0;
} }
.apropos-contact-card strong { .apropos-contact-card strong {
display: block; display: block;
font-weight: 600; font-weight: 600;
color: var(--text-primary); color: var(--text-primary);
margin-bottom: var(--space-3xs); margin-bottom: var(--space-3xs);
} }
.apropos-contact-card span { .apropos-contact-card span {
display: block; display: block;
color: var(--text-secondary); color: var(--text-secondary);
line-height: 1.4; line-height: 1.4;
margin-bottom: var(--space-3xs); margin-bottom: var(--space-3xs);
} }
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
@@ -232,33 +238,33 @@
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
.apropos-credits-list { .apropos-credits-list {
margin: 0; margin: 0;
padding: 0; padding: 0;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0; gap: 0;
} }
.apropos-credit-row { .apropos-credit-row {
display: grid; display: grid;
grid-template-columns: 1fr 1.6fr; grid-template-columns: 1fr 1.6fr;
gap: var(--space-s); gap: var(--space-s);
padding: var(--space-s) 0; padding: var(--space-s) 0;
align-items: baseline; align-items: baseline;
} }
.apropos-credits-list dt { .apropos-credits-list dt {
/* font-size: var(--step--1); */ /* font-size: var(--step--1); */
font-weight: 300; font-weight: 300;
letter-spacing: 0.04em; letter-spacing: 0.04em;
text-transform: uppercase; text-transform: uppercase;
} }
.apropos-credits-list dd { .apropos-credits-list dd {
/* font-size: var(--step-; */ /* font-size: var(--step-; */
color: var(--text-primary); color: var(--text-primary);
margin: 0; margin: 0;
line-height: 1.5; line-height: 1.5;
} }
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
@@ -266,7 +272,7 @@
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
.apropos-single { .apropos-single {
max-width: 720px; max-width: 720px;
} }
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
@@ -274,20 +280,20 @@
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
@media (max-width: 600px) { @media (max-width: 600px) {
.page-content { .page-content {
padding: var(--space-m) var(--space-s) 0; padding: var(--space-m) var(--space-s) 0;
} }
.page-content > article { .page-content > article {
font-size: var(--step-0); font-size: var(--step-0);
} }
.content-section-title { .content-section-title {
font-size: clamp(1.2rem, 1.1rem + 0.45vw, 1.45rem); font-size: clamp(1.2rem, 1.1rem + 0.45vw, 1.45rem);
} }
.apropos-credit-row { .apropos-credit-row {
grid-template-columns: 1fr; grid-template-columns: 1fr;
gap: var(--space-3xs); gap: var(--space-3xs);
} }
} }
+184 -182
View File
@@ -5,293 +5,295 @@
/* Cards grid — scrollable main area */ /* Cards grid — scrollable main area */
.home-main { .home-main {
flex: 1; flex: 1;
min-height: 0; min-height: 0;
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
padding: 0; padding: 0;
} }
.cards-container { .cards-container {
display: grid; display: grid;
grid-template-columns: repeat(3, 1fr); grid-template-columns: repeat(3, 1fr);
gap: var(--space-s); gap: var(--space-s);
list-style: none; list-style: none;
margin: 0; margin: 0;
padding: var(--space-xs) var(--space-s) var(--space-m); padding: var(--space-xs) var(--space-s) var(--space-m);
} }
@media (max-width: 768px) { @media (max-width: 768px) {
.cards-container { .cards-container {
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
} }
} }
@media (max-width: 480px) { @media (max-width: 480px) {
.cards-container { .cards-container {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
} }
/* Each card = list item containing a block <a> link */ /* Each card = list item containing a block <a> link */
.card { .card {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
cursor: pointer; cursor: pointer;
border-radius: var(--radius); border-radius: var(--radius);
background: var(--bg-primary); background: var(--bg-primary);
overflow: hidden; overflow: hidden;
transition: transition:
border-color 0.2s ease, border-color 0.2s ease,
box-shadow 0.2s ease; box-shadow 0.2s ease;
} }
.card:hover { .card:hover {
box-shadow: 0 4px 16px var(--accent-secondary); box-shadow: 0 4px 16px var(--accent-secondary);
/* border-color: var(--accent-primary); */ /* border-color: var(--accent-primary); */
} }
.card > a { .card > a {
text-decoration: none; text-decoration: none;
color: inherit; color: inherit;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex: 1; flex: 1;
border-radius: inherit; border-radius: inherit;
} }
/* Media wrapper: <figure> for real images/video, <div class="card__media--gradient"> for placeholders */ /* Media wrapper: <figure> for real images/video, <div class="card__media--gradient"> for placeholders */
.home-body figure { .home-body figure {
width: 100%; width: 100%;
aspect-ratio: 4 / 3; aspect-ratio: 4 / 3;
overflow: hidden; overflow: hidden;
background: var(--bg-tertiary); background: var(--bg-tertiary);
position: relative; position: relative;
margin: 0; /* reset <figure> default margin */ margin: 0; /* reset <figure> default margin */
/* border-radius: 7px 7px 0 0; */ /* border-radius: 7px 7px 0 0; */
border-radius: var(--radius); border-radius: var(--radius);
} }
.home-body figure img, .home-body figure img,
.home-body figure video { .home-body figure video {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: cover; object-fit: cover;
display: block; display: block;
transition: transform 0.3s ease, opacity 300ms ease-in; transition:
transform 0.3s ease,
opacity 300ms ease-in;
} }
/* Cover thumbnails are served as a <picture> (WebP + fallback); keep the /* Cover thumbnails are served as a <picture> (WebP + fallback); keep the
wrapper block-level so the <img> fills the 4:3 figure. */ wrapper block-level so the <img> fills the 4:3 figure. */
.home-body figure picture { .home-body figure picture {
display: block; display: block;
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
.card:hover figure img, .card:hover figure img,
.card:hover figure video { .card:hover figure video {
transform: scale(1.02); transform: scale(1.02);
} }
.card__media--placeholder { .card__media--placeholder {
width: 100%; width: 100%;
height: 100%; height: 100%;
background: linear-gradient(135deg, var(--bg-tertiary), var(--bg-active)); background: linear-gradient(135deg, var(--bg-tertiary), var(--bg-active));
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
color: var(--text-tertiary); color: var(--text-tertiary);
font-size: var(--step-3); font-size: var(--step-3);
} }
/* HTMX lazy-loaded cover: spinner + settle fade-in (mirrors htmx /* HTMX lazy-loaded cover: spinner + settle fade-in (mirrors htmx
docs' `htmx-settling img` transition pattern). */ docs' `htmx-settling img` transition pattern). */
.card__cover-loading { .card__cover-loading {
animation: card-cover-pulse 1.1s ease-in-out infinite; animation: card-cover-pulse 1.1s ease-in-out infinite;
} }
@keyframes card-cover-pulse { @keyframes card-cover-pulse {
0%, 0%,
100% { 100% {
opacity: 0.3; opacity: 0.3;
} }
50% { 50% {
opacity: 1; opacity: 1;
} }
} }
.home-body figure.htmx-settling img { .home-body figure.htmx-settling img {
opacity: 0; opacity: 0;
} }
.card__media--gradient { .card__media--gradient {
width: 100%; width: 100%;
aspect-ratio: 4 / 3; aspect-ratio: 4 / 3;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: var(--space-s); padding: var(--space-s);
text-align: center; text-align: center;
box-sizing: border-box; box-sizing: border-box;
border-radius: 0 0 var(--radius) var(--radius); border-radius: 0 0 var(--radius) var(--radius);
background: linear-gradient( background: linear-gradient(
0deg, 0deg,
rgba(192, 93, 225, 1) 0%, rgba(192, 93, 225, 1) 0%,
rgba(51, 191, 135, 1) 66%, rgba(51, 191, 135, 1) 66%,
rgba(60, 133, 108, 1) 100% rgba(60, 133, 108, 1) 100%
); );
} }
.card__gradient-author { .card__gradient-author {
color: var(--accent-foreground); color: var(--accent-foreground);
font-size: var(--step--2); font-size: var(--step--2);
opacity: 0.85; opacity: 0.85;
margin-bottom: 0.25rem; margin-bottom: 0.25rem;
display: block; display: block;
} }
.card__gradient-title { .card__gradient-title {
color: var(--accent-foreground); color: var(--accent-foreground);
font-size: var(--step--1); font-size: var(--step--1);
font-weight: 600; font-weight: 600;
display: -webkit-box; display: -webkit-box;
-webkit-line-clamp: 3; -webkit-line-clamp: 3;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
overflow: hidden; overflow: hidden;
} }
/* Section label */ /* Section label */
.home-section-label { .home-section-label {
font-style: normal; font-style: normal;
background: transparent; background: transparent;
color: var(--text-primary); color: var(--text-primary);
font-size: var(--step--2); font-size: var(--step--2);
font-weight: 600; font-weight: 600;
letter-spacing: 0.1em; letter-spacing: 0.1em;
text-transform: uppercase; text-transform: uppercase;
padding: var(--space-s) var(--space-s) var(--space-xs); padding: var(--space-s) var(--space-s) var(--space-xs);
border-bottom: 1px solid var(--border-primary); border-bottom: 1px solid var(--border-primary);
margin: 0; margin: 0;
} }
/* Card caption — <p> directly inside the card <a> link, below the media */ /* Card caption — <p> directly inside the card <a> link, below the media */
.home-body li > a > p { .home-body li > a > p {
padding: var(--space-2xs) var(--space-xs) var(--space-xs); padding: var(--space-2xs) var(--space-xs) var(--space-xs);
font-size: var(--step--1); font-size: var(--step--1);
line-height: 1.35; line-height: 1.35;
color: var(--text-primary); color: var(--text-primary);
margin: 0; margin: 0;
font-weight: 400; font-weight: 400;
} }
/* Empty-state message shown when no cards exist */ /* Empty-state message shown when no cards exist */
.cards-empty { .cards-empty {
padding: var(--space-l); padding: var(--space-l);
color: var(--text-tertiary); color: var(--text-tertiary);
font-size: var(--step--1); font-size: var(--step--1);
list-style: none; list-style: none;
} }
/* Filter info */ /* Filter info */
.filter-info { .filter-info {
background: var(--accent-muted); background: var(--accent-muted);
color: var(--accent-secondary); color: var(--accent-secondary);
padding: var(--space-3xs) var(--space-s); padding: var(--space-3xs) var(--space-s);
font-size: var(--step--1); font-size: var(--step--1);
display: flex; display: flex;
align-items: center; align-items: center;
gap: var(--space-s); gap: var(--space-s);
flex-shrink: 0; flex-shrink: 0;
} }
.clear-filter { .clear-filter {
color: var(--accent-secondary); color: var(--accent-secondary);
text-decoration: none; text-decoration: none;
padding: var(--space-3xs) var(--space-2xs); padding: var(--space-3xs) var(--space-2xs);
background: var(--accent-muted); background: var(--accent-muted);
border-radius: var(--radius); border-radius: var(--radius);
font-size: var(--step--1); font-size: var(--step--1);
} }
.clear-filter:hover { .clear-filter:hover {
background: var(--accent-secondary); background: var(--accent-secondary);
color: var(--accent-foreground); color: var(--accent-foreground);
} }
/* Pagination */ /* Pagination */
.pagination-wrap { .pagination-wrap {
border-top: 1px solid var(--border-secondary); border-top: 1px solid var(--border-secondary);
background: var(--bg-primary); background: var(--bg-primary);
flex-shrink: 0; flex-shrink: 0;
} }
.pagination-wrap ul { .pagination-wrap ul {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
gap: var(--space-2xs); gap: var(--space-2xs);
padding: var(--space-s); padding: var(--space-s);
list-style: none; list-style: none;
margin: 0; margin: 0;
} }
.pagination-btn { .pagination-btn {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
min-width: 2.75rem; min-width: 2.75rem;
min-height: 2.75rem; min-height: 2.75rem;
padding: 0 var(--space-2xs); padding: 0 var(--space-2xs);
border: 1px solid var(--border-secondary); border: 1px solid var(--border-secondary);
border-radius: var(--radius); border-radius: var(--radius);
color: var(--text-primary); color: var(--text-primary);
font-size: var(--step--1); font-size: var(--step--1);
text-decoration: none; text-decoration: none;
font-weight: 400; font-weight: 400;
transition: all 0.15s; transition: all 0.15s;
} }
.pagination-btn:hover:not(.disabled) { .pagination-btn:hover:not(.disabled) {
border-color: var(--accent-primary); border-color: var(--accent-primary);
color: var(--accent-primary); color: var(--accent-primary);
} }
.pagination-btn.disabled { .pagination-btn.disabled {
opacity: 0.3; opacity: 0.3;
cursor: not-allowed; cursor: not-allowed;
pointer-events: none; pointer-events: none;
} }
.pagination-info { .pagination-info {
font-size: var(--step--1); font-size: var(--step--1);
color: var(--text-secondary); color: var(--text-secondary);
padding: 0 var(--space-2xs); padding: 0 var(--space-2xs);
} }
.page-current { .page-current {
font-weight: 600; font-weight: 600;
color: var(--text-primary); color: var(--text-primary);
} }
/* Suppress card hover scale for users who prefer reduced motion */ /* Suppress card hover scale for users who prefer reduced motion */
@media (prefers-reduced-motion: reduce) { @media (prefers-reduced-motion: reduce) {
.home-body figure img, .home-body figure img,
.home-body figure video { .home-body figure video {
transition: none; transition: none;
} }
.card:hover figure img, .card:hover figure img,
.card:hover figure video { .card:hover figure video {
transform: none; transform: none;
} }
.card__media--gradient { .card__media--gradient {
transition: none; transition: none;
} }
.card { .card {
transition: none; transition: none;
} }
.card:hover { .card:hover {
transform: none; transform: none;
} }
} }
File diff suppressed because it is too large Load Diff
+341 -335
View File
@@ -4,14 +4,14 @@
============================================================ */ ============================================================ */
.tfe-main { .tfe-main {
display: flex; display: flex;
flex: 1; flex: 1;
min-height: 0; min-height: 0;
overflow: hidden; overflow: hidden;
/* Left padding keeps content aligned with the rest of the page; /* Left padding keeps content aligned with the rest of the page;
no right padding so the right column (and its scrollbar) sits no right padding so the right column (and its scrollbar) sits
flush against the viewport edge. */ flush against the viewport edge. */
padding-left: var(--space-m); padding-left: var(--space-m);
} }
/* Stacked article layout — fills main height */ /* Stacked article layout — fills main height */
@@ -33,28 +33,28 @@
/* Two-column layout: left 40vw (info), right fills remaining (files) */ /* Two-column layout: left 40vw (info), right fills remaining (files) */
.tfe-content-row { .tfe-content-row {
display: grid; display: grid;
grid-template-columns: 49vw 1fr; grid-template-columns: 49vw 1fr;
width: 100%; width: 100%;
height: 100%; height: 100%;
min-height: 0; min-height: 0;
} }
.tfe-left-column { .tfe-left-column {
display: grid; display: grid;
overflow-y: auto; overflow-y: auto;
min-width: 0; min-width: 0;
padding: var(--space-xl) var(--space-m) var(--space-xl) var(--space-m); padding: var(--space-xl) var(--space-m) var(--space-xl) var(--space-m);
padding-right: 0.5ch; padding-right: 0.5ch;
gap: 1ch; gap: 1ch;
} }
.tfe-right-column { .tfe-right-column {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow-y: auto; overflow-y: auto;
min-width: 0; min-width: 0;
padding: var(--space-xl) var(--space-m) var(--space-xl) var(--space-m); padding: var(--space-xl) var(--space-m) var(--space-xl) var(--space-m);
} }
/* Left column: stacks author, title, meta, synopsis — scrolls independently */ /* Left column: stacks author, title, meta, synopsis — scrolls independently */
@@ -72,12 +72,12 @@
/* Files container inside right column: padded on the right so content /* Files container inside right column: padded on the right so content
sits clear of the column's right-edge scrollbar */ sits clear of the column's right-edge scrollbar */
.tfe-files { .tfe-files {
display: grid; display: grid;
gap: var(--space-m); gap: var(--space-m);
} }
.tfe-files:has(.pdf-expanded) { .tfe-files:has(.pdf-expanded) {
height: 100%; height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: var(--space-m); gap: var(--space-m);
@@ -87,309 +87,311 @@
} }
.tfe-file-item { .tfe-file-item {
width: 100%; width: 100%;
min-width: 0; min-width: 0;
border-radius: var(--radius); border-radius: var(--radius);
} }
.tfe-file-item:last-of-type { .tfe-file-item:last-of-type {
padding-bottom: 4ch; padding-bottom: 4ch;
} }
.tfe-file-item:has(.pdf-embed-wrapper) { .tfe-file-item:has(.pdf-embed-wrapper) {
overflow: visible; overflow: visible;
} }
.tfe-file-item:has(.pdf-expanded) { .tfe-file-item:has(.pdf-expanded) {
min-height: 0; min-height: 0;
overflow: visible; overflow: visible;
} }
.tfe-file-item:has(.tfe-website-wrapper) { .tfe-file-item:has(.tfe-website-wrapper) {
min-height: 0; min-height: 0;
overflow: visible; overflow: visible;
} }
/* When a PDF is expanded, freeze the right column and hide /* When a PDF is expanded, freeze the right column and hide
sibling file items so they can't render above the expanded view. sibling file items so they can't render above the expanded view.
Also trim column padding so the PDF fills more vertical space. */ Also trim column padding so the PDF fills more vertical space. */
.tfe-right-column:has(.pdf-expanded) { .tfe-right-column:has(.pdf-expanded) {
overflow: hidden; overflow: hidden;
padding-top: var(--space-xs); padding-top: var(--space-xs);
padding-bottom: var(--space-xs); padding-bottom: var(--space-xs);
} }
.tfe-right-column:has(.pdf-expanded) .tfe-file-item:not(:has(.pdf-expanded)) { .tfe-right-column:has(.pdf-expanded) .tfe-file-item:not(:has(.pdf-expanded)) {
display: none; display: none;
} }
.tfe-file-item img { .tfe-file-item img {
width: 100%; width: 100%;
height: auto; height: auto;
display: block; display: block;
border-radius: var(--radius); border-radius: var(--radius);
user-select: none; user-select: none;
-webkit-user-drag: none; -webkit-user-drag: none;
} }
.tfe-file-item embed, .tfe-file-item embed,
.tfe-file-item video { .tfe-file-item video {
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
display: block; display: block;
border: none; border: none;
} }
.tfe-file-item video { .tfe-file-item video {
max-height: 500px; max-height: 500px;
} }
.tfe-file-item embed, .tfe-file-item embed,
.tfe-file-item iframe { .tfe-file-item iframe {
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
height: 100%; height: 100%;
min-height: 400px; min-height: 400px;
display: block; display: block;
border: none; border: none;
} }
/* ── Website embed wrapper (like PDF overlay) ── */ /* ── Website embed wrapper (like PDF overlay) ── */
.tfe-website-wrapper { .tfe-website-wrapper {
position: relative; position: relative;
width: 100%; width: 100%;
display: grid; display: grid;
background: var(--surface); background: var(--surface);
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: var(--radius); border-radius: var(--radius);
overflow: hidden; overflow: hidden;
} }
.tfe-website-badge { .tfe-website-badge {
position: absolute; position: absolute;
top: var(--space-xs); top: var(--space-xs);
left: var(--space-xs); left: var(--space-xs);
z-index: 2; z-index: 2;
display: inline-block; display: inline-block;
padding: 0.15em 0.6em; padding: 0.15em 0.6em;
font-size: var(--step--2); font-size: var(--step--2);
font-weight: 500; font-weight: 500;
line-height: 1.4; line-height: 1.4;
color: color-mix(in srgb, var(--accent-primary) 90%, #000); color: color-mix(in srgb, var(--accent-primary) 90%, #000);
background: color-mix(in srgb, var(--accent-primary) 12%, transparent); background: color-mix(in srgb, var(--accent-primary) 12%, transparent);
border: 1px solid color-mix(in srgb, var(--accent-primary) 25%, transparent); border: 1px solid color-mix(in srgb, var(--accent-primary) 25%, transparent);
border-radius: var(--radius); border-radius: var(--radius);
} }
.tfe-website-open-btn { .tfe-website-open-btn {
position: absolute; position: absolute;
bottom: var(--space-xs); bottom: var(--space-xs);
right: var(--space-xs); right: var(--space-xs);
z-index: 2; z-index: 2;
display: grid; display: grid;
place-items: center; place-items: center;
width: 40px; width: 40px;
height: 40px; height: 40px;
background: var(--accent-primary); background: var(--accent-primary);
color: #fff; color: #fff;
border: none; border: none;
border-radius: var(--radius); border-radius: var(--radius);
text-decoration: none; text-decoration: none;
cursor: pointer; cursor: pointer;
box-shadow: 0 2px 8px rgb(0 0 0 / 0.25); box-shadow: 0 2px 8px rgb(0 0 0 / 0.25);
transition: transform 0.15s, box-shadow 0.15s; transition:
transform 0.15s,
box-shadow 0.15s;
} }
.tfe-website-open-btn:hover { .tfe-website-open-btn:hover {
transform: translateY(-1px); transform: translateY(-1px);
box-shadow: 0 4px 12px rgb(0 0 0 / 0.35); box-shadow: 0 4px 12px rgb(0 0 0 / 0.35);
background: var(--accent-primary); background: var(--accent-primary);
color: #fff; color: #fff;
} }
.tfe-file-item figcaption { .tfe-file-item figcaption {
font-size: var(--step--2); font-size: var(--step--2);
color: var(--text-secondary); color: var(--text-secondary);
margin: var(--space-3xs) 0 0; margin: var(--space-3xs) 0 0;
font-style: italic; font-style: italic;
} }
/* Contextual note above synopsis */ /* Contextual note above synopsis */
.tfe-context-note { .tfe-context-note {
font-style: italic; font-style: italic;
font-size: var(--step--1); font-size: var(--step--1);
line-height: 1.6; line-height: 1.6;
color: var(--text-secondary); color: var(--text-secondary);
margin: 0; margin: 0;
padding: var(--space-xs) var(--space-s); padding: var(--space-xs) var(--space-s);
background: color-mix(in srgb, var(--accent-primary) 10%, var(--bg-primary)); background: color-mix(in srgb, var(--accent-primary) 10%, var(--bg-primary));
border-radius: var(--radius); border-radius: var(--radius);
} }
/* Author (p) — inline with title */ /* Author (p) — inline with title */
.tfe-author { .tfe-author {
font-size: var(--step-1); font-size: var(--step-1);
font-weight: 400; font-weight: 400;
color: var(--text-primary); color: var(--text-primary);
margin: 0; margin: 0;
line-height: 1.3; line-height: 1.3;
word-break: normal; word-break: normal;
overflow-wrap: break-word; overflow-wrap: break-word;
hyphens: auto; hyphens: auto;
} }
/* Title (h1) — inherits global scale from base.css */ /* Title (h1) — inherits global scale from base.css */
.tfe-title { .tfe-title {
margin: 0; margin: 0;
font-size: var(--step-2); font-size: var(--step-2);
word-break: normal; word-break: normal;
overflow-wrap: break-word; overflow-wrap: break-word;
hyphens: auto; hyphens: auto;
} }
/* Metadata block */ /* Metadata block */
.tfe-meta { .tfe-meta {
display: grid; display: grid;
gap: var(--space-3xs); gap: var(--space-3xs);
font-size: var(--step--1); font-size: var(--step--1);
line-height: 1.4; line-height: 1.4;
margin: 0; margin: 0;
} }
/* Each metadata line */ /* Each metadata line */
.tfe-meta-item { .tfe-meta-item {
margin: 0; margin: 0;
font-weight: 700; font-weight: 700;
word-break: normal; word-break: normal;
overflow-wrap: break-word; overflow-wrap: break-word;
hyphens: auto; hyphens: auto;
} }
.tfe-meta-label { .tfe-meta-label {
font-weight: 300; font-weight: 300;
} }
.tfe-meta-item a { .tfe-meta-item a {
color: inherit; color: inherit;
font-weight: 700; font-weight: 700;
text-decoration: none; text-decoration: none;
} }
.tfe-meta-item a:hover { .tfe-meta-item a:hover {
color: var(--accent-primary); color: var(--accent-primary);
} }
/* Note field: align label to top, value in italics */ /* Note field: align label to top, value in italics */
.tfe-meta-item.tfe-meta-note { .tfe-meta-item.tfe-meta-note {
align-items: start; align-items: start;
} }
.tfe-note-value { .tfe-note-value {
font-style: italic; font-style: italic;
} }
/* Synopsis paragraph */ /* Synopsis paragraph */
.tfe-synopsis-text { .tfe-synopsis-text {
font-size: var(--step--1); font-size: var(--step--1);
line-height: 1.7; line-height: 1.7;
color: var(--text-primary); color: var(--text-primary);
margin: 0; margin: 0;
} }
/* Audio player */ /* Audio player */
.tfe-audio { .tfe-audio {
width: 100%; width: 100%;
margin: 0; margin: 0;
display: block; display: block;
} }
/* "Not available" and "no files" notices */ /* "Not available" and "no files" notices */
.tfe-restricted, .tfe-restricted,
.tfe-no-files { .tfe-no-files {
font-size: var(--step--1); font-size: var(--step--1);
color: var(--text-secondary); color: var(--text-secondary);
font-style: italic; font-style: italic;
padding: var(--space-s) 0; padding: var(--space-s) 0;
margin: 0; margin: 0;
} }
/* ============================================================ /* ============================================================
RESTRICTED ACCESS UI RESTRICTED ACCESS UI
============================================================ */ ============================================================ */
.tfe-restricted-access { .tfe-restricted-access {
background: var(--surface); background: var(--surface);
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: var(--radius); border-radius: var(--radius);
padding: var(--space-m); padding: var(--space-m);
display: grid; display: grid;
gap: var(--space-m); gap: var(--space-m);
} }
.tfe-restricted-message { .tfe-restricted-message {
font-size: var(--step--1); font-size: var(--step--1);
color: var(--text-secondary); color: var(--text-secondary);
line-height: 1.6; line-height: 1.6;
margin: 0; margin: 0;
} }
.tfe-restricted-message strong { .tfe-restricted-message strong {
color: var(--text-primary); color: var(--text-primary);
display: block; display: block;
margin-bottom: var(--space-3xs); margin-bottom: var(--space-3xs);
font-size: var(--step-0); font-size: var(--step-0);
} }
.tfe-access-request-form { .tfe-access-request-form {
display: grid; display: grid;
gap: var(--space-s); gap: var(--space-s);
} }
.tfe-access-request-form .form-group { .tfe-access-request-form .form-group {
display: grid; display: grid;
gap: var(--space-3xs); gap: var(--space-3xs);
} }
.tfe-access-request-form label { .tfe-access-request-form label {
font-size: var(--step--1); font-size: var(--step--1);
font-weight: 400; font-weight: 400;
color: var(--text-primary); color: var(--text-primary);
} }
.tfe-access-request-form input[type="email"], .tfe-access-request-form input[type="email"],
.tfe-access-request-form textarea { .tfe-access-request-form textarea {
padding: var(--space-2xs) var(--space-3xs); padding: var(--space-2xs) var(--space-3xs);
} }
.tfe-btn-request-access { .tfe-btn-request-access {
margin-top: var(--space-3xs); margin-top: var(--space-3xs);
} }
.tfe-btn-request-access:disabled { .tfe-btn-request-access:disabled {
opacity: 0.6; opacity: 0.6;
cursor: not-allowed; cursor: not-allowed;
} }
.tfe-access-message { .tfe-access-message {
font-size: var(--step--1); font-size: var(--step--1);
padding: var(--space-2xs); padding: var(--space-2xs);
border-radius: var(--radius); border-radius: var(--radius);
margin-top: var(--space-3xs); margin-top: var(--space-3xs);
} }
.tfe-access-success { .tfe-access-success {
background: #f0fff4; background: #f0fff4;
border: 1px solid #48bb78; border: 1px solid #48bb78;
color: #22543d; color: #22543d;
} }
.tfe-access-error { .tfe-access-error {
background: #fff5f5; background: #fff5f5;
border: 1px solid #fc8181; border: 1px solid #fc8181;
color: #742a2a; color: #742a2a;
} }
.tfe-access-request-form input.input-error { .tfe-access-request-form input.input-error {
border-color: #fc8181; border-color: #fc8181;
outline-color: #fc8181; outline-color: #fc8181;
} }
/* ============================================================ /* ============================================================
@@ -398,231 +400,235 @@
/*── Base wrapper ───────────────────────────── */ /*── Base wrapper ───────────────────────────── */
.pdf-embed-wrapper { .pdf-embed-wrapper {
position: relative; position: relative;
width: 100%; width: 100%;
height: auto; height: auto;
display: grid; display: grid;
background: var(--surface); background: var(--surface);
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: var(--radius); border-radius: var(--radius);
transition: height 0.35s ease, border-color 0.35s ease; transition:
outline: none; height 0.35s ease,
border-color 0.35s ease;
outline: none;
} }
/* ── Collapsed state: thumbnail tile ────────── */ /* ── Collapsed state: thumbnail tile ────────── */
.pdf-collapsed { .pdf-collapsed {
cursor: pointer; cursor: pointer;
overflow: hidden; overflow: hidden;
display: grid; display: grid;
place-items: center; place-items: center;
min-height: 200px; min-height: 200px;
max-height: 350px; max-height: 350px;
} }
.pdf-thumbnail { .pdf-thumbnail {
display: block; display: block;
max-width: 100%; max-width: 100%;
max-height: 100%; max-height: 100%;
object-fit: contain; object-fit: contain;
} }
/* ── Overlay veil + enter button ────────────── */ /* ── Overlay veil + enter button ────────────── */
.pdf-overlay { .pdf-overlay {
position: absolute; position: absolute;
inset: 0; inset: 0;
z-index: 1; z-index: 1;
display: grid; display: grid;
place-items: center; place-items: center;
background: rgb(0 0 0 / 0.15); background: rgb(0 0 0 / 0.15);
backdrop-filter: blur(4px) saturate(0.6); backdrop-filter: blur(4px) saturate(0.6);
transition: background 0.2s; transition: background 0.2s;
} }
.pdf-overlay:hover { .pdf-overlay:hover {
background: rgb(0 0 0 / 0.08); background: rgb(0 0 0 / 0.08);
} }
/* Document type pill — top-left of the overlay */ /* Document type pill — top-left of the overlay */
.pdf-overlay-badge { .pdf-overlay-badge {
position: absolute; position: absolute;
top: var(--space-xs); top: var(--space-xs);
left: var(--space-xs); left: var(--space-xs);
z-index: 2; z-index: 2;
display: inline-block; display: inline-block;
padding: 0.15em 0.6em; padding: 0.15em 0.6em;
font-size: var(--step--2); font-size: var(--step--2);
font-weight: 500; font-weight: 500;
line-height: 1.4; line-height: 1.4;
color: color-mix(in srgb, var(--accent-primary) 90%, #000); color: color-mix(in srgb, var(--accent-primary) 90%, #000);
background: color-mix(in srgb, var(--accent-primary) 12%, transparent); background: color-mix(in srgb, var(--accent-primary) 12%, transparent);
border: 1px solid color-mix(in srgb, var(--accent-primary) 25%, transparent); border: 1px solid color-mix(in srgb, var(--accent-primary) 25%, transparent);
border-radius: var(--radius); border-radius: var(--radius);
} }
.pdf-enter-btn { .pdf-enter-btn {
display: inline-grid; display: inline-grid;
grid-auto-flow: column; grid-auto-flow: column;
align-items: center; align-items: center;
gap: var(--space-2xs); gap: var(--space-2xs);
padding: var(--space-xs) var(--space-m); padding: var(--space-xs) var(--space-m);
background: var(--accent-primary); background: var(--accent-primary);
color: #fff; color: #fff;
border: none; border: none;
border-radius: var(--radius); border-radius: var(--radius);
font-size: var(--step-0); font-size: var(--step-0);
font-weight: 500; font-weight: 500;
cursor: pointer; cursor: pointer;
box-shadow: 0 2px 8px rgb(0 0 0 / 0.2); box-shadow: 0 2px 8px rgb(0 0 0 / 0.2);
transition: transform 0.15s, box-shadow 0.15s; transition:
transform 0.15s,
box-shadow 0.15s;
} }
.pdf-enter-btn:hover { .pdf-enter-btn:hover {
transform: translateY(-1px); transform: translateY(-1px);
box-shadow: 0 4px 12px rgb(0 0 0 / 0.25); box-shadow: 0 4px 12px rgb(0 0 0 / 0.25);
} }
/* ── Expanded state: wrapper becomes scroll panel ── */ /* ── Expanded state: wrapper becomes scroll panel ── */
/* Disable root-level overscroll (rubberbanding) while a PDF is open. */ /* Disable root-level overscroll (rubberbanding) while a PDF is open. */
body.pdf-viewer-open { body.pdf-viewer-open {
overscroll-behavior: none; overscroll-behavior: none;
} }
.pdf-expanded { .pdf-expanded {
height: 100%; height: 100%;
min-height: 400px; min-height: 400px;
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
overscroll-behavior-y: contain; overscroll-behavior-y: contain;
border: 2px solid var(--accent-primary); border: 2px solid var(--accent-primary);
display: grid; display: grid;
justify-items: center; justify-items: center;
background: color-mix(in srgb, var(--accent-secondary) 22%, transparent); background: color-mix(in srgb, var(--accent-secondary) 22%, transparent);
} }
/* ── Toolbar ────────────────────────────────── */ /* ── Toolbar ────────────────────────────────── */
.pdf-toolbar { .pdf-toolbar {
position: sticky; position: sticky;
justify-self: stretch; justify-self: stretch;
top: 0; top: 0;
z-index: 2; z-index: 2;
display: flex; display: flex;
align-items: center; align-items: center;
gap: var(--space-3xs); gap: var(--space-3xs);
padding: var(--space-2xs) var(--space-xs); padding: var(--space-2xs) var(--space-xs);
background: var(--bg-primary); background: var(--bg-primary);
border-bottom: 1px solid var(--border); border-bottom: 1px solid var(--border);
border-radius: var(--radius); border-radius: var(--radius);
flex-shrink: 0; flex-shrink: 0;
font-size: var(--step--1); font-size: var(--step--1);
user-select: none; user-select: none;
overscroll-behavior: none; overscroll-behavior: none;
} }
.pdf-toolbar-btn { .pdf-toolbar-btn {
display: inline-grid; display: inline-grid;
place-items: center; place-items: center;
width: 2em; width: 2em;
height: 2em; height: 2em;
padding: 0; padding: 0;
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: var(--radius); border-radius: var(--radius);
background: var(--surface); background: var(--surface);
color: var(--text-primary); color: var(--text-primary);
cursor: pointer; cursor: pointer;
font-size: inherit; font-size: inherit;
line-height: 1; line-height: 1;
transition: background 0.15s; transition: background 0.15s;
} }
.pdf-toolbar-btn:hover { .pdf-toolbar-btn:hover {
background: color-mix(in srgb, var(--accent-primary) 15%, var(--surface)); background: color-mix(in srgb, var(--accent-primary) 15%, var(--surface));
} }
.pdf-toolbar-close { .pdf-toolbar-close {
margin-right: var(--space-xs); margin-right: var(--space-xs);
} }
.pdf-toolbar-label { .pdf-toolbar-label {
min-width: 4.5em; min-width: 4.5em;
text-align: center; text-align: center;
color: var(--text-secondary); color: var(--text-secondary);
font-variant-numeric: tabular-nums; font-variant-numeric: tabular-nums;
} }
.pdf-toolbar-scale { .pdf-toolbar-scale {
min-width: 3em; min-width: 3em;
} }
/* ── Canvas ─────────────────────────────────── */ /* ── Canvas ─────────────────────────────────── */
.pdf-canvas { .pdf-canvas {
display: block; display: block;
width: 100%; width: 100%;
height: auto; height: auto;
box-shadow: 0 1px 4px rgb(0 0 0 / 0.12); box-shadow: 0 1px 4px rgb(0 0 0 / 0.12);
background: #fff; background: #fff;
flex-shrink: 0; flex-shrink: 0;
} }
.pdf-canvas:first-of-type { .pdf-canvas:first-of-type {
margin-top: var(--space-xs); margin-top: var(--space-xs);
} }
.pdf-canvas:last-of-type { .pdf-canvas:last-of-type {
margin-bottom: var(--space-xs); margin-bottom: var(--space-xs);
} }
.pdf-canvas + .pdf-canvas { .pdf-canvas + .pdf-canvas {
margin-top: var(--space-2xs); margin-top: var(--space-2xs);
} }
/* ── Responsive ─────────────────────────────── */ /* ── Responsive ─────────────────────────────── */
@media (max-width: 900px) { @media (max-width: 900px) {
.tfe-main { .tfe-main {
overflow-y: auto; overflow-y: auto;
} }
.tfe-content-row { .tfe-content-row {
grid-template-columns: 1fr; grid-template-columns: 1fr;
height: auto; height: auto;
} }
.tfe-left-column, .tfe-left-column,
.tfe-right-column { .tfe-right-column {
overflow-y: visible; overflow-y: visible;
padding: var(--space-3xs); padding: var(--space-3xs);
} }
.tfe-title { .tfe-title {
font-size: var(--step-2); font-size: var(--step-2);
} }
/* PDF expands to full viewport on mobile */ /* PDF expands to full viewport on mobile */
.pdf-expanded { .pdf-expanded {
position: fixed; position: fixed;
inset: 0; inset: 0;
z-index: 100; z-index: 100;
height: auto; height: auto;
min-height: unset; min-height: unset;
background: color-mix(in srgb, var(--accent-secondary) 92%, #000 8%); background: color-mix(in srgb, var(--accent-secondary) 92%, #000 8%);
border: none; border: none;
border-radius: 0; border-radius: 0;
} }
.pdf-toolbar { .pdf-toolbar {
border-radius: 0 0 var(--radius) var(--radius); border-radius: 0 0 var(--radius) var(--radius);
} }
.tfe-file-iframe { .tfe-file-iframe {
height: 100dvh; height: 100dvh;
} }
} }
@media (max-width: 600px) { @media (max-width: 600px) {
.tfe-main { .tfe-main {
padding: var(--space-m) var(--space-s) var(--space-l); padding: var(--space-m) var(--space-s) var(--space-l);
} }
.tfe-title { .tfe-title {
font-size: var(--step-1); font-size: var(--step-1);
} }
} }
+1 -2
View File
@@ -46,8 +46,7 @@
// Update active tab class after each HTMX swap on #sys-log-view // Update active tab class after each HTMX swap on #sys-log-view
document.body.addEventListener("htmx:afterSwap", (evt) => { document.body.addEventListener("htmx:afterSwap", (evt) => {
if (!(evt.detail.target && evt.detail.target.id === "sys-log-view")) if (!(evt.detail.target && evt.detail.target.id === "sys-log-view")) return;
return;
var rc = evt.detail.requestConfig; var rc = evt.detail.requestConfig;
var tab = null; var tab = null;
// Tab clicks carry ?tab=… in the path // Tab clicks carry ?tab=… in the path
@@ -904,9 +904,12 @@
var inputId = inputIdMap[queueType] || null; var inputId = inputIdMap[queueType] || null;
var input = inputId ? document.getElementById(inputId) : null; var input = inputId ? document.getElementById(inputId) : null;
console.log( console.log(
"[relink] looking for input | queueType=" + queueType + "[relink] looking for input | queueType=" +
" | inputId=" + inputId + queueType +
" | found=" + !!input, " | inputId=" +
inputId +
" | found=" +
!!input,
); );
var closeModal = () => { var closeModal = () => {
var modal = document.getElementById("relink-modal"); var modal = document.getElementById("relink-modal");
@@ -917,17 +920,19 @@
console.log(`[relink] looking for pond | found=${!!pond}`); console.log(`[relink] looking for pond | found=${!!pond}`);
if (pond) { if (pond) {
pond pond
.addFiles([{ .addFiles([
source: String(data.id), {
options: { source: String(data.id),
type: "local", options: {
file: { type: "local",
name: fileName, file: {
size: fileSize, name: fileName,
type: mimeType, size: fileSize,
type: mimeType,
},
}, },
}, },
}]) ])
.then(() => { .then(() => {
console.log( console.log(
"[relink] addFile resolved | source=" + "[relink] addFile resolved | source=" +
@@ -1028,17 +1033,19 @@
var pond = FilePond.find(input); var pond = FilePond.find(input);
if (pond) { if (pond) {
pond pond
.addFiles([{ .addFiles([
source: String(data.id), {
options: { source: String(data.id),
type: "local", options: {
file: { type: "local",
name: name, file: {
size: 0, name: name,
type: "video/mp4", size: 0,
type: "video/mp4",
},
}, },
}, },
}]) ])
.then(() => { .then(() => {
console.log("[pt-relink] addFile resolved"); console.log("[pt-relink] addFile resolved");
closeModal(); closeModal();
+3 -1
View File
@@ -360,7 +360,9 @@
}); });
const oldToolbar = container.querySelector(".pdf-toolbar"); const oldToolbar = container.querySelector(".pdf-toolbar");
if (oldToolbar) oldToolbar.remove(); if (oldToolbar) oldToolbar.remove();
renderAllPages(container, pdfDoc).then(() => buildToolbar(container, pdfDoc)); renderAllPages(container, pdfDoc).then(() =>
buildToolbar(container, pdfDoc),
);
} }
// ── Bootstrap ────────────────────────────────────────────────── // ── Bootstrap ──────────────────────────────────────────────────
+1 -2
View File
@@ -33,8 +33,7 @@
* DYNAMIC_CLASS_PREFIXES -> string[] prefix patterns (x--*) kept * DYNAMIC_CLASS_PREFIXES -> string[] prefix patterns (x--*) kept
*/ */
import { readFileSync } from "node:fs"; import { readdirSync, readFileSync, statSync } from "node:fs";
import { readdirSync, statSync } from "node:fs";
import { dirname, extname, join, relative, resolve } from "node:path"; import { dirname, extname, join, relative, resolve } from "node:path";
import { fileURLToPath } from "node:url"; import { fileURLToPath } from "node:url";
+1 -1
View File
@@ -22,7 +22,7 @@
* (no args => all dist/*.min.css) * (no args => all dist/*.min.css)
*/ */
import { readFileSync, readdirSync } from "node:fs"; import { readdirSync, readFileSync } from "node:fs";
import { dirname, resolve } from "node:path"; import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url"; import { fileURLToPath } from "node:url";
import { transform } from "lightningcss"; import { transform } from "lightningcss";