mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-08-10 07:11:18 +02:00
- fix page nav buttons, smaller default pages, violet bg
- Build toolbar after renderAllPages so it queries existing canvases;
query canvases fresh in the scroll handler so page tracking works
after re-render (zoom in/out).
- Default data-pdf-scale 0.85 (JS fallback 0.8) so pages are a bit
smaller by default.
- Add dark transparent violet background (accent-secondary 22%) to
.pdf-expanded, behind the pages.
- expand to fill column top-to-bottom via CSS flex
Use a flex chain (.tfe-files flex:1, .tfe-file-item:has(.pdf-expanded)
flex:1) so the expanded PDF wrapper fills the right column from under
the header to the bottom of the viewport, instead of viewport-based
clamp math that didn't account for the header height.
- fill right column, center pages, freeze column on expand
The expanded viewer now stays inside the right column instead of
growing the page: the column switches to overflow:hidden while the
PDF panel scrolls internally. Pages are centered horizontally via
flexbox align-items: center.
- fix toolbar not full-width, hide sibling file items
The toolbar was constrained by the parent's align-items:center; fixed
with align-self:stretch. Hiding sibling .tfe-file-item elements when
a PDF is expanded prevents them from rendering above the overlay.
- disable overscroll on expanded view
- use overscroll-behavior-y on container, none on toolbar
- disable body overscroll via .pdf-viewer-open class
- mobile full-viewport, iframe matches pdf height
- mobile overlay above everything via position:fixed
- opaque dark-violet bg on mobile overlay
- tfe: add 'Open in new tab' link above website iframes
- trim column padding when expanded for more vertical space
- 5% zoom increments, subtle padding on expanded column
- prevent horizontal overflow/overscroll
588 lines
12 KiB
CSS
588 lines
12 KiB
CSS
/* ============================================================
|
|
TFE INDIVIDUAL PAGE (tfe.php)
|
|
Root class: .tfe-main
|
|
============================================================ */
|
|
|
|
.tfe-main {
|
|
flex: 1;
|
|
min-height: 0;
|
|
overflow: hidden;
|
|
padding: 0 var(--space-m) 0 var(--space-m);
|
|
}
|
|
|
|
/* Stacked article layout — fills main height */
|
|
.tfe-layout {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-xl);
|
|
width: 100%;
|
|
height: 100%;
|
|
min-height: 0;
|
|
}
|
|
|
|
/* Row 1: Author above Title (kept for backward compat, no longer used) */
|
|
.tfe-header-row {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-3xs);
|
|
}
|
|
|
|
/* Two-column layout: left 40vw (info), right fills remaining (files) */
|
|
.tfe-content-row {
|
|
display: grid;
|
|
grid-template-columns: 40vw 1fr;
|
|
gap: var(--space-xl);
|
|
flex: 1;
|
|
min-height: 0;
|
|
}
|
|
.tfe-left-column,
|
|
.tfe-right-column {
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow-y: auto;
|
|
min-width: 0;
|
|
padding-top: var(--space-l);
|
|
padding-bottom: var(--space-xl);
|
|
}
|
|
|
|
/* Left column: stacks author, title, meta, synopsis — scrolls independently */
|
|
.tfe-left-column {
|
|
gap: var(--space-m);
|
|
/* to space the edge of the text and the scrollbar */
|
|
padding-right: 0.5ch;
|
|
}
|
|
|
|
/* Files container inside right column */
|
|
.tfe-files {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-m);
|
|
flex: 1;
|
|
min-height: 0;
|
|
}
|
|
|
|
.tfe-file-item {
|
|
width: 100%;
|
|
min-width: 0;
|
|
overflow: hidden;
|
|
border-radius: var(--radius);
|
|
}
|
|
|
|
.tfe-file-item:has(.pdf-embed-wrapper) {
|
|
overflow: visible;
|
|
}
|
|
|
|
.tfe-file-item:has(.pdf-expanded) {
|
|
flex: 1;
|
|
min-height: 0;
|
|
overflow: visible;
|
|
}
|
|
|
|
.tfe-file-item:has(.tfe-file-iframe) {
|
|
flex: 1;
|
|
min-height: 0;
|
|
overflow: visible;
|
|
}
|
|
|
|
/* When a PDF is expanded, freeze the right column and hide
|
|
sibling file items so they can't render above the expanded view.
|
|
Also trim column padding so the PDF fills more vertical space. */
|
|
.tfe-right-column:has(.pdf-expanded) {
|
|
overflow: hidden;
|
|
padding-top: var(--space-xs);
|
|
padding-bottom: var(--space-xs);
|
|
}
|
|
.tfe-right-column:has(.pdf-expanded) .tfe-file-item:not(:has(.pdf-expanded)) {
|
|
display: none;
|
|
}
|
|
|
|
.tfe-file-item img {
|
|
width: 100%;
|
|
height: auto;
|
|
display: block;
|
|
border-radius: var(--radius);
|
|
user-select: none;
|
|
-webkit-user-drag: none;
|
|
}
|
|
|
|
.tfe-file-item embed,
|
|
.tfe-file-item video {
|
|
width: 100%;
|
|
max-width: 100%;
|
|
display: block;
|
|
border: none;
|
|
}
|
|
|
|
.tfe-file-item video {
|
|
max-height: 500px;
|
|
}
|
|
|
|
.tfe-file-item embed,
|
|
.tfe-file-iframe {
|
|
width: 100%;
|
|
max-width: 100%;
|
|
height: 100%;
|
|
min-height: 400px;
|
|
display: block;
|
|
border: none;
|
|
}
|
|
|
|
.tfe-website-link {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-3xs);
|
|
padding: var(--space-2xs) var(--space-xs);
|
|
font-size: var(--step--1);
|
|
color: var(--accent-primary);
|
|
text-decoration: none;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius);
|
|
margin-bottom: var(--space-2xs);
|
|
}
|
|
|
|
.tfe-website-link:hover {
|
|
background: color-mix(in srgb, var(--accent-primary) 10%, var(--bg-primary));
|
|
}
|
|
|
|
.tfe-file-item figcaption {
|
|
font-size: var(--step--2);
|
|
color: var(--text-secondary);
|
|
margin: var(--space-3xs) 0 0;
|
|
font-style: italic;
|
|
}
|
|
|
|
/* Synopsis column wrapper (context note + synopsis) */
|
|
.tfe-synopsis-column {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-xs);
|
|
}
|
|
|
|
/* Contextual note above synopsis */
|
|
.tfe-context-note {
|
|
font-style: italic;
|
|
font-size: var(--step--1);
|
|
line-height: 1.6;
|
|
color: var(--text-secondary);
|
|
margin: 0;
|
|
padding: var(--space-xs) var(--space-s);
|
|
background: color-mix(in srgb, var(--accent-primary) 10%, var(--bg-primary));
|
|
border-radius: var(--radius);
|
|
}
|
|
|
|
.tfe-synopsis-empty {
|
|
/* placeholder to maintain grid column */
|
|
}
|
|
|
|
/* Author (p) — inline with title */
|
|
.tfe-author {
|
|
font-family: var(--font-display);
|
|
font-size: var(--step-1);
|
|
font-weight: 400;
|
|
color: var(--text-primary);
|
|
margin: 0;
|
|
line-height: 1.3;
|
|
}
|
|
|
|
/* Title (h1) — inherits global scale from base.css */
|
|
.tfe-title {
|
|
margin: 0;
|
|
}
|
|
|
|
/* Metadata block */
|
|
.tfe-meta {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-3xs);
|
|
font-size: var(--step--1);
|
|
line-height: 1.4;
|
|
margin: 0;
|
|
}
|
|
|
|
/* Each metadata line */
|
|
.tfe-meta-item {
|
|
margin: 0;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.tfe-meta-label {
|
|
font-weight: 300;
|
|
}
|
|
|
|
.tfe-meta-item a {
|
|
color: inherit;
|
|
font-weight: 700;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.tfe-meta-item a:hover {
|
|
color: var(--accent-primary);
|
|
}
|
|
|
|
/* Note field: align label to top, value in italics */
|
|
.tfe-meta-item.tfe-meta-note {
|
|
align-items: start;
|
|
}
|
|
|
|
.tfe-note-value {
|
|
font-style: italic;
|
|
}
|
|
|
|
/* Synopsis paragraph */
|
|
.tfe-synopsis-text {
|
|
font-size: var(--step--1);
|
|
line-height: 1.7;
|
|
color: var(--text-primary);
|
|
margin: 0;
|
|
}
|
|
|
|
/* Audio player */
|
|
.tfe-audio {
|
|
width: 100%;
|
|
margin: 0;
|
|
display: block;
|
|
}
|
|
|
|
/* "Not available" and "no files" notices */
|
|
.tfe-restricted,
|
|
.tfe-no-files {
|
|
font-size: var(--step--1);
|
|
color: var(--text-secondary);
|
|
font-style: italic;
|
|
padding: var(--space-s) 0;
|
|
margin: 0;
|
|
}
|
|
|
|
/* ============================================================
|
|
RESTRICTED ACCESS UI
|
|
============================================================ */
|
|
.tfe-restricted-access {
|
|
background: var(--surface);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius);
|
|
padding: var(--space-m);
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-m);
|
|
}
|
|
|
|
.tfe-restricted-message {
|
|
font-size: var(--step--1);
|
|
color: var(--text-secondary);
|
|
line-height: 1.6;
|
|
margin: 0;
|
|
}
|
|
|
|
.tfe-restricted-message strong {
|
|
color: var(--text-primary);
|
|
display: block;
|
|
margin-bottom: var(--space-3xs);
|
|
font-size: var(--step-0);
|
|
}
|
|
|
|
.tfe-access-request-form {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-s);
|
|
}
|
|
|
|
.tfe-access-request-form .form-group {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-3xs);
|
|
}
|
|
|
|
.tfe-access-request-form label {
|
|
font-size: var(--step--1);
|
|
font-weight: 400;
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.tfe-access-request-form input[type="email"],
|
|
.tfe-access-request-form textarea {
|
|
padding: var(--space-2xs) var(--space-3xs);
|
|
}
|
|
|
|
.tfe-btn-request-access {
|
|
/* deprecated alias for .btn--primary; kept for backward-compat */
|
|
margin-top: var(--space-3xs);
|
|
}
|
|
|
|
.tfe-btn-request-access:hover:not(:disabled) {
|
|
/* handled by .btn--primary */
|
|
}
|
|
|
|
.tfe-btn-request-access:disabled {
|
|
opacity: 0.6;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
.tfe-access-message {
|
|
font-size: var(--step--1);
|
|
padding: var(--space-2xs);
|
|
border-radius: var(--radius);
|
|
margin-top: var(--space-3xs);
|
|
}
|
|
|
|
.tfe-access-success {
|
|
background: #f0fff4;
|
|
border: 1px solid #48bb78;
|
|
color: #22543d;
|
|
}
|
|
|
|
.tfe-access-error {
|
|
background: #fff5f5;
|
|
border: 1px solid #fc8181;
|
|
color: #742a2a;
|
|
}
|
|
|
|
.tfe-access-request-form input.input-error {
|
|
border-color: #fc8181;
|
|
outline-color: #fc8181;
|
|
}
|
|
|
|
/* ============================================================
|
|
PDF.js IN-PAGE VIEWER (pdf-viewer.js)
|
|
============================================================ */
|
|
|
|
/*── Base wrapper ───────────────────────────── */
|
|
|
|
.pdf-embed-wrapper {
|
|
position: relative;
|
|
width: 100%;
|
|
height: auto;
|
|
display: flex;
|
|
flex-direction: column;
|
|
background: var(--surface);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius);
|
|
transition: height 0.35s ease, border-color 0.35s ease;
|
|
outline: none;
|
|
}
|
|
|
|
/* ── Collapsed state: thumbnail tile ────────── */
|
|
|
|
.pdf-collapsed {
|
|
cursor: pointer;
|
|
overflow: hidden;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
position: relative;
|
|
min-height: 200px;
|
|
max-height: 350px;
|
|
}
|
|
|
|
.pdf-thumbnail {
|
|
display: block;
|
|
max-width: 100%;
|
|
max-height: 100%;
|
|
object-fit: contain;
|
|
}
|
|
|
|
/* ── Overlay veil + enter button ────────────── */
|
|
|
|
.pdf-overlay {
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: rgb(0 0 0 / 0.15);
|
|
backdrop-filter: blur(4px) saturate(0.6);
|
|
transition: background 0.2s;
|
|
}
|
|
|
|
.pdf-overlay:hover {
|
|
background: rgb(0 0 0 / 0.08);
|
|
}
|
|
|
|
/* Document type pill — top-left of the overlay */
|
|
|
|
.pdf-overlay-badge {
|
|
position: absolute;
|
|
top: var(--space-xs);
|
|
left: var(--space-xs);
|
|
z-index: 2;
|
|
display: inline-block;
|
|
padding: 0.15em 0.6em;
|
|
font-size: var(--step--2);
|
|
font-weight: 500;
|
|
line-height: 1.4;
|
|
color: color-mix(in srgb, var(--accent-primary) 90%, #000);
|
|
background: color-mix(in srgb, var(--accent-primary) 12%, transparent);
|
|
border: 1px solid color-mix(in srgb, var(--accent-primary) 25%, transparent);
|
|
border-radius: var(--radius);
|
|
}
|
|
|
|
.pdf-enter-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-2xs);
|
|
padding: var(--space-xs) var(--space-m);
|
|
background: var(--accent-primary);
|
|
color: #fff;
|
|
border: none;
|
|
border-radius: var(--radius);
|
|
font-size: var(--step-0);
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
box-shadow: 0 2px 8px rgb(0 0 0 / 0.2);
|
|
transition: transform 0.15s, box-shadow 0.15s;
|
|
}
|
|
|
|
.pdf-enter-btn:hover {
|
|
transform: translateY(-1px);
|
|
box-shadow: 0 4px 12px rgb(0 0 0 / 0.25);
|
|
}
|
|
|
|
/* ── Expanded state: wrapper becomes scroll panel ── */
|
|
|
|
/* Disable root-level overscroll (rubberbanding) while a PDF is open. */
|
|
body.pdf-viewer-open {
|
|
overscroll-behavior: none;
|
|
}
|
|
|
|
.pdf-expanded {
|
|
/* Fill the right column from top to bottom (under the header). */
|
|
height: 100%;
|
|
min-height: 400px;
|
|
overflow-y: auto;
|
|
overflow-x: hidden;
|
|
overscroll-behavior-y: contain;
|
|
border: 2px solid var(--accent-primary);
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
background: color-mix(in srgb, var(--accent-secondary) 22%, transparent);
|
|
}
|
|
|
|
/* ── Toolbar ────────────────────────────────── */
|
|
|
|
.pdf-toolbar {
|
|
position: sticky;
|
|
align-self: stretch;
|
|
top: 0;
|
|
z-index: 2;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-3xs);
|
|
padding: var(--space-2xs) var(--space-xs);
|
|
background: var(--bg-primary);
|
|
border-bottom: 1px solid var(--border);
|
|
border-radius: var(--radius);
|
|
flex-shrink: 0;
|
|
font-size: var(--step--1);
|
|
user-select: none;
|
|
overscroll-behavior: none;
|
|
}
|
|
|
|
.pdf-toolbar-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 2em;
|
|
height: 2em;
|
|
padding: 0;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius);
|
|
background: var(--surface);
|
|
color: var(--text-primary);
|
|
cursor: pointer;
|
|
font-size: inherit;
|
|
line-height: 1;
|
|
transition: background 0.15s;
|
|
}
|
|
|
|
.pdf-toolbar-btn:hover {
|
|
background: color-mix(in srgb, var(--accent-primary) 15%, var(--surface));
|
|
}
|
|
|
|
.pdf-toolbar-close {
|
|
margin-right: var(--space-xs);
|
|
}
|
|
|
|
.pdf-toolbar-label {
|
|
min-width: 4.5em;
|
|
text-align: center;
|
|
color: var(--text-secondary);
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
.pdf-toolbar-scale {
|
|
min-width: 3em;
|
|
}
|
|
|
|
/* ── Scroll container ────────────────────────── */
|
|
|
|
.pdf-canvas {
|
|
display: block;
|
|
width: 100%;
|
|
height: auto;
|
|
box-shadow: 0 1px 4px rgb(0 0 0 / 0.12);
|
|
background: #fff;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.pdf-canvas:first-of-type {
|
|
margin-top: var(--space-xs);
|
|
}
|
|
|
|
.pdf-canvas:last-of-type {
|
|
margin-bottom: var(--space-xs);
|
|
}
|
|
|
|
.pdf-canvas + .pdf-canvas {
|
|
margin-top: var(--space-2xs);
|
|
}
|
|
|
|
/* Responsive */
|
|
@media (max-width: 900px) {
|
|
.tfe-main {
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.tfe-layout {
|
|
height: auto;
|
|
min-height: auto;
|
|
}
|
|
|
|
.tfe-content-row {
|
|
grid-template-columns: 1fr;
|
|
flex: none;
|
|
}
|
|
|
|
.tfe-left-column,
|
|
.tfe-right-column {
|
|
overflow-y: visible;
|
|
}
|
|
|
|
.tfe-title {
|
|
font-size: var(--step-2);
|
|
}
|
|
|
|
/* PDF expands to full viewport height on mobile, above everything */
|
|
.pdf-expanded {
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: 100;
|
|
height: auto;
|
|
min-height: unset;
|
|
background: color-mix(in srgb, var(--accent-secondary) 92%, #000 8%);
|
|
}
|
|
.tfe-file-iframe {
|
|
height: 100dvh;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 600px) {
|
|
.tfe-main {
|
|
padding: var(--space-m) var(--space-s) var(--space-l);
|
|
}
|
|
|
|
.tfe-title {
|
|
font-size: var(--step-1);
|
|
}
|
|
}
|