Files
xamxam/app/public/assets/css/tfe.css
T
Pontoporeia 20873f94af pdf-viewer: various visual and usability changes
- 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
2026-07-08 22:41:52 +02:00

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);
}
}