mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-08-10 07:11:18 +02:00
justfile: standardise test recipes to lint-php/lint-css/lint-js/test + add fix recipe
- Removed ambiguous aliases: phpstan, cs-check, syntax - Split lint-biome into lint-css and lint-js with correct paths - Added lint meta-recipe and fix recipe (biome --unsafe + php-cs-fixer) - Fixed FormBootstrap dead null check, CSS shorthand override bug - Updated phpstan baseline, suppressed noDescendingSpecificity/noInnerDeclarations - Applied ~74 biome auto-fixes across CSS/JS
This commit is contained in:
+1
-1
File diff suppressed because one or more lines are too long
@@ -18,4 +18,4 @@
|
|||||||
- [x] Add bulk select/delete to tmp cleanup dialog (like admin/index.php pattern)
|
- [x] Add bulk select/delete to tmp cleanup dialog (like admin/index.php pattern)
|
||||||
- [x] Move cleanup UI from modal to dedicated page (like add.php/edit.php)
|
- [x] Move cleanup UI from modal to dedicated page (like add.php/edit.php)
|
||||||
- [x] Replace <details> with <fieldset>/<legend> in cleanup fragments (like contenus.php)
|
- [x] Replace <details> with <fieldset>/<legend> in cleanup fragments (like contenus.php)
|
||||||
- [x] Standardise test group recipes: lint-php, lint-css, lint-js, test + add fix recipe
|
- [x] Standardise test group recipes: lint-php, lint-css, lint-js, test + add fix recipe + make lint pass clean
|
||||||
|
|||||||
+1247
-1210
File diff suppressed because it is too large
Load Diff
@@ -5,72 +5,85 @@
|
|||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
/* Full-height flex layout: header → main → (optional footer) */
|
/* Full-height flex layout: header → main → (optional footer) */
|
||||||
html, body {
|
html,
|
||||||
height: 100%;
|
body {
|
||||||
overflow: hidden;
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Discreet scrollbars ─────────────────────────────────────────── */
|
/* ── Discreet scrollbars ─────────────────────────────────────────── */
|
||||||
/* WebKit browsers */
|
/* WebKit browsers */
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 5px;
|
width: 5px;
|
||||||
height: 5px;
|
height: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-track {
|
::-webkit-scrollbar-track {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
background: var(--text-tertiary);
|
background: var(--text-tertiary);
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb:hover {
|
::-webkit-scrollbar-thumb:hover {
|
||||||
background: var(--text-secondary);
|
background: var(--text-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Firefox */
|
/* Firefox */
|
||||||
* {
|
* {
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
scrollbar-color: var(--text-tertiary) transparent;
|
scrollbar-color: var(--text-tertiary) transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
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) 92%,
|
rgba(0, 0, 0, 0) 92%,
|
||||||
rgba(149, 87, 181, 1) 100%
|
rgba(149, 87, 181, 1) 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 { font-size: var(--step-4); }
|
h1 {
|
||||||
h2 { font-size: var(--step-3); }
|
font-size: var(--step-4);
|
||||||
h3 { font-size: var(--step-2); }
|
}
|
||||||
h4 { font-size: var(--step-1); }
|
h2 {
|
||||||
h5 { font-size: var(--step-0); }
|
font-size: var(--step-3);
|
||||||
h6 { font-size: var(--step--1); }
|
}
|
||||||
|
h3 {
|
||||||
|
font-size: var(--step-2);
|
||||||
|
}
|
||||||
|
h4 {
|
||||||
|
font-size: var(--step-1);
|
||||||
|
}
|
||||||
|
h5 {
|
||||||
|
font-size: var(--step-0);
|
||||||
|
}
|
||||||
|
h6 {
|
||||||
|
font-size: var(--step--1);
|
||||||
|
}
|
||||||
|
|
||||||
: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-l) 0;
|
margin: 0 0 var(--space-l) 0;
|
||||||
line-height: 1.15;
|
line-height: 1.15;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,80 +4,80 @@
|
|||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
/* Backgrounds */
|
/* Backgrounds */
|
||||||
--bg-primary: #ffffff;
|
--bg-primary: #ffffff;
|
||||||
--bg-secondary: #f5f5f5;
|
--bg-secondary: #f5f5f5;
|
||||||
--bg-tertiary: #e8e8e8;
|
--bg-tertiary: #e8e8e8;
|
||||||
--bg-active: #d0d0d0;
|
--bg-active: #d0d0d0;
|
||||||
|
|
||||||
/* Text */
|
/* Text */
|
||||||
--text-primary: #111111;
|
--text-primary: #111111;
|
||||||
--text-secondary: #666666;
|
--text-secondary: #666666;
|
||||||
--text-tertiary: #999999;
|
--text-tertiary: #999999;
|
||||||
|
|
||||||
/* Borders */
|
/* Borders */
|
||||||
--border-primary: #dddddd;
|
--border-primary: #dddddd;
|
||||||
--border-secondary: #cccccc;
|
--border-secondary: #cccccc;
|
||||||
|
|
||||||
/* Border radius */
|
/* Border radius */
|
||||||
--radius: 10px;
|
--radius: 10px;
|
||||||
|
|
||||||
/* Status */
|
/* Status */
|
||||||
--success: #5cd69d;
|
--success: #5cd69d;
|
||||||
--error: #f25a5a;
|
--error: #f25a5a;
|
||||||
--warning: #fbca51;
|
--warning: #fbca51;
|
||||||
|
|
||||||
/* Accent */
|
/* Accent */
|
||||||
--accent-primary: #9557b5;
|
--accent-primary: #9557b5;
|
||||||
--accent-secondary: #683d7f;
|
--accent-secondary: #683d7f;
|
||||||
--accent-foreground: #ffffff;
|
--accent-foreground: #ffffff;
|
||||||
--accent-muted: rgba(149, 87, 181, 0.12);
|
--accent-muted: rgba(149, 87, 181, 0.12);
|
||||||
--accent-blue: #41adff;
|
--accent-blue: #41adff;
|
||||||
--accent-green: #4caf50;
|
--accent-green: #4caf50;
|
||||||
--accent-yellow: #f39c12;
|
--accent-yellow: #f39c12;
|
||||||
--accent-red: #f25a5a;
|
--accent-red: #f25a5a;
|
||||||
|
|
||||||
/* Gradient (header) */
|
/* Gradient (header) */
|
||||||
--gradient-1: #42963f;
|
--gradient-1: #42963f;
|
||||||
--gradient-2: #65e478;
|
--gradient-2: #65e478;
|
||||||
--gradient-3: #57abc7;
|
--gradient-3: #57abc7;
|
||||||
--gradient-4: #db53ed;
|
--gradient-4: #db53ed;
|
||||||
|
|
||||||
/* Header decorative */
|
/* Header decorative */
|
||||||
--header-gradient-fade: rgba(149, 87, 181, 0);
|
--header-gradient-fade: rgba(149, 87, 181, 0);
|
||||||
--header-shadow-strong: rgba(119, 70, 145, 1);
|
--header-shadow-strong: rgba(119, 70, 145, 1);
|
||||||
--header-shadow-soft: rgba(119, 70, 145, 0.8);
|
--header-shadow-soft: rgba(119, 70, 145, 0.8);
|
||||||
--header-nav-active-border: rgba(255, 255, 255, 0.6);
|
--header-nav-active-border: rgba(255, 255, 255, 0.6);
|
||||||
|
|
||||||
/* Search error block */
|
/* Search error block */
|
||||||
--search-error-bg: #fff0f0;
|
--search-error-bg: #fff0f0;
|
||||||
--search-error-border: #cc0000;
|
--search-error-border: #cc0000;
|
||||||
--search-error-color: #cc0000;
|
--search-error-color: #cc0000;
|
||||||
|
|
||||||
/* System page — log/config syntax highlight */
|
/* System page — log/config syntax highlight */
|
||||||
--sys-syntax-comment: #999999;
|
--sys-syntax-comment: #999999;
|
||||||
--sys-syntax-directive: #1a6fb5;
|
--sys-syntax-directive: #1a6fb5;
|
||||||
--sys-syntax-block: #7a2fa0;
|
--sys-syntax-block: #7a2fa0;
|
||||||
--sys-syntax-value: #a05c00;
|
--sys-syntax-value: #a05c00;
|
||||||
--sys-syntax-location: #1a7a6b;
|
--sys-syntax-location: #1a7a6b;
|
||||||
--sys-syntax-notice: #3a6ea8;
|
--sys-syntax-notice: #3a6ea8;
|
||||||
--sys-syntax-crit: #c0392b;
|
--sys-syntax-crit: #c0392b;
|
||||||
|
|
||||||
/* Muted alpha overlays — derived from semantic tokens */
|
/* Muted alpha overlays — derived from semantic tokens */
|
||||||
--success-muted-bg: rgba(92, 214, 157, 0.12);
|
--success-muted-bg: rgba(92, 214, 157, 0.12);
|
||||||
--success-muted-border: rgba(92, 214, 157, 0.35);
|
--success-muted-border: rgba(92, 214, 157, 0.35);
|
||||||
--warning-muted-bg: rgba(251, 202, 81, 0.12);
|
--warning-muted-bg: rgba(251, 202, 81, 0.12);
|
||||||
--warning-muted-border: rgba(251, 202, 81, 0.35);
|
--warning-muted-border: rgba(251, 202, 81, 0.35);
|
||||||
--error-muted-bg: rgba(242, 90, 90, 0.12);
|
--error-muted-bg: rgba(242, 90, 90, 0.12);
|
||||||
--error-muted-border: rgba(242, 90, 90, 0.35);
|
--error-muted-border: rgba(242, 90, 90, 0.35);
|
||||||
--blue-muted-bg: rgba(65, 173, 255, 0.12);
|
--blue-muted-bg: rgba(65, 173, 255, 0.12);
|
||||||
--blue-muted-border: rgba(65, 173, 255, 0.3);
|
--blue-muted-border: rgba(65, 173, 255, 0.3);
|
||||||
--blue-muted-bg-hover: rgba(65, 173, 255, 0.22);
|
--blue-muted-bg-hover: rgba(65, 173, 255, 0.22);
|
||||||
--yellow-muted-bg: rgba(243, 156, 18, 0.12);
|
--yellow-muted-bg: rgba(243, 156, 18, 0.12);
|
||||||
--yellow-muted-border: rgba(243, 156, 18, 0.3);
|
--yellow-muted-border: rgba(243, 156, 18, 0.3);
|
||||||
--yellow-muted-bg-hover: rgba(243, 156, 18, 0.22);
|
--yellow-muted-bg-hover: rgba(243, 156, 18, 0.22);
|
||||||
--green-muted-bg: rgba(76, 175, 80, 0.12);
|
--green-muted-bg: rgba(76, 175, 80, 0.12);
|
||||||
--green-muted-border: rgba(76, 175, 80, 0.3);
|
--green-muted-border: rgba(76, 175, 80, 0.3);
|
||||||
--green-muted-bg-hover: rgba(76, 175, 80, 0.22);
|
--green-muted-bg-hover: rgba(76, 175, 80, 0.22);
|
||||||
--danger-border-muted: rgba(242, 90, 90, 0.35);
|
--danger-border-muted: rgba(242, 90, 90, 0.35);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,45 +4,45 @@
|
|||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
.status-badge {
|
.status-badge {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: var(--space-3xs) var(--space-2xs);
|
padding: var(--space-3xs) var(--space-2xs);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-published {
|
.status-published {
|
||||||
background: var(--green-muted-bg);
|
background: var(--green-muted-bg);
|
||||||
color: var(--accent-green);
|
color: var(--accent-green);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-pending {
|
.status-pending {
|
||||||
background: var(--warning-muted-bg);
|
background: var(--warning-muted-bg);
|
||||||
color: var(--warning);
|
color: var(--warning);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-access {
|
.status-access {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
padding: var(--space-3xs) var(--space-3xs);
|
padding: var(--space-3xs) var(--space-3xs);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
background: var(--bg-tertiary);
|
background: var(--bg-tertiary);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
letter-spacing: 0.03em;
|
letter-spacing: 0.03em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-access--libre {
|
.status-access--libre {
|
||||||
background: var(--green-muted-bg);
|
background: var(--green-muted-bg);
|
||||||
color: var(--accent-green);
|
color: var(--accent-green);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-access--interne {
|
.status-access--interne {
|
||||||
background: var(--blue-muted-bg);
|
background: var(--blue-muted-bg);
|
||||||
color: var(--accent-blue);
|
color: var(--accent-blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-access--interdit {
|
.status-access--interdit {
|
||||||
background: var(--error-muted-bg);
|
background: var(--error-muted-bg);
|
||||||
color: var(--error);
|
color: var(--error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,142 +5,165 @@
|
|||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: var(--space-3xs);
|
gap: var(--space-3xs);
|
||||||
padding: var(--space-xs);
|
padding: var(--space-xs);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
border: none;
|
border: none;
|
||||||
transition: background 0.15s, opacity 0.15s, box-shadow 0.15s, filter 0.15s;
|
transition:
|
||||||
width: fit-content;
|
background 0.15s,
|
||||||
|
opacity 0.15s,
|
||||||
|
box-shadow 0.15s,
|
||||||
|
filter 0.15s;
|
||||||
|
width: fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn:hover { filter: brightness(0.92); }
|
.btn:hover {
|
||||||
|
filter: brightness(0.92);
|
||||||
|
}
|
||||||
|
|
||||||
/* Primary: accent background, white text */
|
/* Primary: accent background, white text */
|
||||||
.btn--primary {
|
.btn--primary {
|
||||||
background: var(--accent-primary);
|
background: var(--accent-primary);
|
||||||
color: var(--accent-foreground);
|
color: var(--accent-foreground);
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn--primary:hover {
|
.btn--primary:hover {
|
||||||
background: var(--accent-secondary);
|
background: var(--accent-secondary);
|
||||||
filter: none;
|
filter: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Secondary: light background with border */
|
/* Secondary: light background with border */
|
||||||
.btn--secondary {
|
.btn--secondary {
|
||||||
background: var(--bg-primary);
|
background: var(--bg-primary);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
border: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn--secondary:hover {
|
.btn--secondary:hover {
|
||||||
border-color: var(--text-secondary);
|
border-color: var(--text-secondary);
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
filter: none;
|
filter: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Muted secondary: bg-secondary background */
|
/* Muted secondary: bg-secondary background */
|
||||||
.btn--muted {
|
.btn--muted {
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
border: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn--muted:hover {
|
.btn--muted:hover {
|
||||||
background: var(--bg-tertiary);
|
background: var(--bg-tertiary);
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
filter: none;
|
filter: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ghost: transparent bg, border, for links styled as buttons */
|
/* Ghost: transparent bg, border, for links styled as buttons */
|
||||||
.btn--ghost {
|
.btn--ghost {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
border: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn--ghost:hover {
|
.btn--ghost:hover {
|
||||||
border-color: var(--text-secondary);
|
border-color: var(--text-secondary);
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
filter: none;
|
filter: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Danger: red background */
|
/* Danger: red background */
|
||||||
.btn--danger {
|
.btn--danger {
|
||||||
background: var(--accent-red);
|
background: var(--accent-red);
|
||||||
color: var(--accent-foreground);
|
color: var(--accent-foreground);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn--danger:hover { filter: brightness(0.9); }
|
.btn--danger:hover {
|
||||||
|
filter: brightness(0.9);
|
||||||
|
}
|
||||||
|
|
||||||
/* Warning: yellow background */
|
/* Warning: yellow background */
|
||||||
.btn--warning {
|
.btn--warning {
|
||||||
background: var(--accent-yellow);
|
background: var(--accent-yellow);
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn--warning:hover { filter: brightness(0.9); }
|
.btn--warning:hover {
|
||||||
|
filter: brightness(0.9);
|
||||||
|
}
|
||||||
|
|
||||||
/* Success: green background */
|
/* Success: green background */
|
||||||
.btn--success {
|
.btn--success {
|
||||||
background: var(--accent-green);
|
background: var(--accent-green);
|
||||||
color: var(--accent-foreground);
|
color: var(--accent-foreground);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn--success:hover { filter: brightness(0.9); }
|
.btn--success:hover {
|
||||||
|
filter: brightness(0.9);
|
||||||
|
}
|
||||||
|
|
||||||
/* Small size modifier */
|
/* Small size modifier */
|
||||||
.btn--sm {
|
.btn--sm {
|
||||||
padding: var(--space-2xs) var(--space-xs);
|
padding: var(--space-2xs) var(--space-xs);
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Large size modifier */
|
/* Large size modifier */
|
||||||
.btn--lg {
|
.btn--lg {
|
||||||
padding: var(--space-s) var(--space-m);
|
padding: var(--space-s) var(--space-m);
|
||||||
font-size: var(--step-0);
|
font-size: var(--step-0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Semantic colour modifiers on muted base (for table/action buttons) */
|
/* Semantic colour modifiers on muted base (for table/action buttons) */
|
||||||
.btn--blue {
|
.btn--blue {
|
||||||
background: var(--blue-muted-bg);
|
background: var(--blue-muted-bg);
|
||||||
color: var(--accent-blue);
|
color: var(--accent-blue);
|
||||||
border: 1px solid var(--blue-muted-border);
|
border: 1px solid var(--blue-muted-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn--blue:hover { background: var(--blue-muted-bg-hover); filter: none; }
|
.btn--blue:hover {
|
||||||
|
background: var(--blue-muted-bg-hover);
|
||||||
|
filter: none;
|
||||||
|
}
|
||||||
|
|
||||||
.btn--yellow {
|
.btn--yellow {
|
||||||
background: var(--yellow-muted-bg);
|
background: var(--yellow-muted-bg);
|
||||||
color: var(--accent-yellow);
|
color: var(--accent-yellow);
|
||||||
border: 1px solid var(--yellow-muted-border);
|
border: 1px solid var(--yellow-muted-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn--yellow:hover { background: var(--yellow-muted-bg-hover); filter: none; }
|
.btn--yellow:hover {
|
||||||
|
background: var(--yellow-muted-bg-hover);
|
||||||
|
filter: none;
|
||||||
|
}
|
||||||
|
|
||||||
.btn--green {
|
.btn--green {
|
||||||
background: var(--green-muted-bg);
|
background: var(--green-muted-bg);
|
||||||
color: var(--accent-green);
|
color: var(--accent-green);
|
||||||
border: 1px solid var(--green-muted-border);
|
border: 1px solid var(--green-muted-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn--green:hover { background: var(--green-muted-bg-hover); filter: none; }
|
.btn--green:hover {
|
||||||
|
background: var(--green-muted-bg-hover);
|
||||||
|
filter: none;
|
||||||
|
}
|
||||||
|
|
||||||
.btn--red {
|
.btn--red {
|
||||||
background: var(--error-muted-bg);
|
background: var(--error-muted-bg);
|
||||||
color: var(--error);
|
color: var(--error);
|
||||||
border: 1px solid var(--danger-border-muted);
|
border: 1px solid var(--danger-border-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn--red:hover { filter: brightness(0.9); }
|
.btn--red:hover {
|
||||||
|
filter: brightness(0.9);
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,41 +4,43 @@
|
|||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
details > summary {
|
details > summary {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
details > summary::-webkit-details-marker {
|
details > summary::-webkit-details-marker {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
details {
|
details {
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
border-radius: var(--radius, 6px);
|
border-radius: var(--radius, 6px);
|
||||||
background: var(--bg-secondary, var(--surface));
|
background: var(--bg-secondary, var(--surface));
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
details[open] {
|
details[open] {
|
||||||
padding-bottom: var(--space-s);
|
padding-bottom: var(--space-s);
|
||||||
}
|
}
|
||||||
|
|
||||||
details > :not(summary) {
|
details > :not(summary) {
|
||||||
padding-left: var(--space-s);
|
padding-left: var(--space-s);
|
||||||
padding-right: var(--space-s);
|
padding-right: var(--space-s);
|
||||||
}
|
}
|
||||||
|
|
||||||
summary {
|
summary {
|
||||||
font-family: var(--font-display);
|
font-family: var(--font-display);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
transition: color 0.15s, background 0.15s;
|
transition:
|
||||||
padding: var(--space-s);
|
color 0.15s,
|
||||||
cursor: pointer;
|
background 0.15s;
|
||||||
|
padding: var(--space-s);
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
summary:hover {
|
summary:hover {
|
||||||
color: var(--accent-primary);
|
color: var(--accent-primary);
|
||||||
background: var(--hover-bg, rgba(0, 0, 0, 0.03));
|
background: var(--hover-bg, rgba(0, 0, 0, 0.03));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,14 +4,14 @@
|
|||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
dialog {
|
dialog {
|
||||||
border: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
background: var(--bg-primary);
|
background: var(--bg-primary);
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
padding: 0;
|
padding: 0;
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog::backdrop {
|
dialog::backdrop {
|
||||||
background: rgba(0, 0, 0, 0.45);
|
background: rgba(0, 0, 0, 0.45);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
:focus-visible {
|
:focus-visible {
|
||||||
outline: none;
|
outline: none;
|
||||||
box-shadow: 0 0 0 2px var(--accent-primary);
|
box-shadow: 0 0 0 2px var(--accent-primary);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
padding: var(--space-3xs) var(--space-xs);
|
padding: var(--space-3xs) var(--space-xs);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,107 +7,119 @@
|
|||||||
/* ── Labels ─────────────────────────────────────────────────────────── */
|
/* ── Labels ─────────────────────────────────────────────────────────── */
|
||||||
|
|
||||||
label {
|
label {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: var(--space-3xs);
|
margin-bottom: var(--space-3xs);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Text inputs, selects, textareas ────────────────────────────────── */
|
/* ── Text inputs, selects, textareas ────────────────────────────────── */
|
||||||
|
|
||||||
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="hidden"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="color"]),
|
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not(
|
||||||
|
[type="hidden"]
|
||||||
|
):not([type="submit"]):not([type="button"]):not([type="reset"]):not(
|
||||||
|
[type="color"]
|
||||||
|
),
|
||||||
textarea {
|
textarea {
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
padding: var(--space-2xs) var(--space-xs);
|
padding: var(--space-2xs) var(--space-xs);
|
||||||
border: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
transition: border-color 0.15s;
|
transition: border-color 0.15s;
|
||||||
}
|
}
|
||||||
|
|
||||||
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="hidden"]):not([type="submit"]):not([type="button"]):not([type="reset"]):not([type="color"]):focus,
|
input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not(
|
||||||
|
[type="hidden"]
|
||||||
|
):not([type="submit"]):not([type="button"]):not([type="reset"]):not(
|
||||||
|
[type="color"]
|
||||||
|
):focus,
|
||||||
textarea:focus {
|
textarea:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border: 2px solid var(--accent-primary);
|
border: 2px solid var(--accent-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
input::placeholder,
|
input::placeholder,
|
||||||
textarea::placeholder {
|
textarea::placeholder {
|
||||||
color: var(--text-tertiary);
|
color: var(--text-tertiary);
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
min-height: 80px;
|
min-height: 80px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Select ─────────────────────────────────────────────────────────── */
|
/* ── Select ─────────────────────────────────────────────────────────── */
|
||||||
|
|
||||||
select {
|
select {
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
padding: var(--space-2xs) var(--space-xs);
|
padding: var(--space-2xs) var(--space-xs);
|
||||||
padding-right: 1.75rem;
|
padding-right: 1.75rem;
|
||||||
border: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-image: url("/assets/icons/select-chevron.svg");
|
background-image: url("/assets/icons/select-chevron.svg");
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: right 0.55rem center;
|
background-position: right 0.55rem center;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
transition: border-color 0.15s;
|
transition: border-color 0.15s;
|
||||||
}
|
}
|
||||||
|
|
||||||
select:focus {
|
select:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border: 2px solid var(--accent-primary);
|
border: 2px solid var(--accent-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Checkboxes & radios ────────────────────────────────────────────── */
|
/* ── Checkboxes & radios ────────────────────────────────────────────── */
|
||||||
|
|
||||||
input[type="checkbox"],
|
input[type="checkbox"],
|
||||||
input[type="radio"] {
|
input[type="radio"] {
|
||||||
accent-color: var(--accent-primary);
|
accent-color: var(--accent-primary);
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"] { border-radius: 50%; }
|
input[type="radio"] {
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Fieldsets & legends ──────────────────────────────────────────────── */
|
/* ── Fieldsets & legends ──────────────────────────────────────────────── */
|
||||||
|
|
||||||
fieldset {
|
fieldset {
|
||||||
border: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
padding: 0 var(--space-m) var(--space-m) var(--space-m);
|
padding: 0 var(--space-m) var(--space-m) var(--space-m);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldset > *:not(:last-child) { margin-bottom: var(--space-xs); }
|
fieldset > *:not(:last-child) {
|
||||||
|
margin-bottom: var(--space-xs);
|
||||||
|
}
|
||||||
|
|
||||||
legend {
|
legend {
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
padding: 0 var(--space-2xs);
|
padding: 0 var(--space-2xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Small / help text ──────────────────────────────────────────────────── */
|
/* ── Small / help text ──────────────────────────────────────────────────── */
|
||||||
|
|
||||||
small {
|
small {
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
display: block;
|
display: block;
|
||||||
margin-top: var(--space-3xs);
|
margin-top: var(--space-3xs);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,81 +6,81 @@
|
|||||||
/* ── 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);
|
||||||
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) ──────────────────────── */
|
||||||
@@ -94,132 +94,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"]
|
header
|
||||||
.nav-left-links
|
nav[aria-label="Navigation principale"]
|
||||||
li:not(:first-child) {
|
.nav-left-links
|
||||||
display: none;
|
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
|
.menu-btn:checked
|
||||||
~ nav[aria-label="Navigation principale"]
|
~ nav[aria-label="Navigation principale"]
|
||||||
.nav-mobile-links {
|
.nav-mobile-links {
|
||||||
max-height: 300px;
|
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
|
.menu-btn:checked ~ nav[aria-label="Navigation principale"]
|
||||||
~ nav[aria-label="Navigation principale"]
|
.menu-icon
|
||||||
.menu-icon
|
.navicon {
|
||||||
.navicon {
|
background: transparent;
|
||||||
background: transparent;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.menu-btn:checked
|
.menu-btn:checked
|
||||||
~ nav[aria-label="Navigation principale"]
|
~ nav[aria-label="Navigation principale"]
|
||||||
.menu-icon
|
.menu-icon
|
||||||
.navicon::before {
|
.navicon::before {
|
||||||
transform: rotate(-45deg);
|
transform: rotate(-45deg);
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-btn:checked
|
.menu-btn:checked
|
||||||
~ nav[aria-label="Navigation principale"]
|
~ nav[aria-label="Navigation principale"]
|
||||||
.menu-icon
|
.menu-icon
|
||||||
.navicon::after {
|
.navicon::after {
|
||||||
transform: rotate(45deg);
|
transform: rotate(45deg);
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
a:hover {
|
a:hover {
|
||||||
color: var(--accent-primary);
|
color: var(--accent-primary);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
:where(video, audio, iframe) {
|
:where(video, audio, iframe) {
|
||||||
border: 1px solid var(--bg-primary);
|
border: 1px solid var(--bg-primary);
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
audio::-webkit-media-controls-enclosure {
|
audio::-webkit-media-controls-enclosure {
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,55 +4,57 @@
|
|||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
.pagination-wrap {
|
.pagination-wrap {
|
||||||
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-m) 0 var(--space-2xs);
|
padding: var(--space-m) 0 var(--space-2xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination-wrap ul {
|
.pagination-wrap ul {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--space-3xs);
|
gap: var(--space-3xs);
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 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);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
transition: border-color 0.15s, color 0.15s;
|
transition:
|
||||||
|
border-color 0.15s,
|
||||||
|
color 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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,55 +6,61 @@
|
|||||||
/* Public search bar icon (in partials/search-bar.php) */
|
/* Public search bar icon (in partials/search-bar.php) */
|
||||||
/* Scoped to forms that are NOT inside .header-search-wrap */
|
/* Scoped to forms that are NOT inside .header-search-wrap */
|
||||||
.search-bar-icon {
|
.search-bar-icon {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
fill: var(--accent-primary);
|
fill: var(--accent-primary);
|
||||||
margin-right: var(--space-2xs);
|
margin-right: var(--space-2xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
form[role="search"]:not(.header-search-form) {
|
form[role="search"]:not(.header-search-form) {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-search-wrap {
|
.header-search-wrap {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
background: linear-gradient(180deg, rgba(192, 93, 225, 1) 0%, rgba(255, 255, 255, 1) 100%);
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
rgba(192, 93, 225, 1) 0%,
|
||||||
|
rgba(255, 255, 255, 1) 100%
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-search-form { width: 100%; }
|
.header-search-form {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.header-search-input-wrap {
|
.header-search-input-wrap {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-search-icon {
|
.header-search-icon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: var(--space-s);
|
left: var(--space-s);
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
fill: var(--accent-primary);
|
fill: var(--accent-primary);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-search-input-wrap input {
|
.header-search-input-wrap input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: var(--space-2xs) var(--space-s) !important;
|
padding: var(--space-2xs) var(--space-s);
|
||||||
padding-left: calc(18px + var(--space-l)) !important;
|
padding-left: calc(18px + var(--space-l));
|
||||||
border: 1px solid var(--accent-primary) !important;
|
border: 1px solid var(--accent-primary);
|
||||||
border-radius: var(--radius) !important;
|
border-radius: var(--radius);
|
||||||
background: var(--bg-primary) !important;
|
background: var(--bg-primary);
|
||||||
font-size: var(--step-0) !important;
|
font-size: var(--step-0);
|
||||||
color: var(--text-primary) !important;
|
color: var(--text-primary);
|
||||||
font-family: inherit !important;
|
font-family: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-search-input-wrap input::placeholder {
|
.header-search-input-wrap input::placeholder {
|
||||||
color: var(--accent-primary) !important;
|
color: var(--accent-primary);
|
||||||
font-family: var(--font-body);
|
font-family: var(--font-body);
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,39 +4,39 @@
|
|||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
table {
|
table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
}
|
}
|
||||||
|
|
||||||
th {
|
th {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
letter-spacing: 0.08em;
|
letter-spacing: 0.08em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
padding: var(--space-3xs) var(--space-xs);
|
padding: var(--space-3xs) var(--space-xs);
|
||||||
border-bottom: 1px solid var(--border-primary);
|
border-bottom: 1px solid var(--border-primary);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
td {
|
td {
|
||||||
padding: var(--space-2xs) var(--space-xs);
|
padding: var(--space-2xs) var(--space-xs);
|
||||||
border-bottom: 1px solid var(--border-primary);
|
border-bottom: 1px solid var(--border-primary);
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sticky header — border-collapse:collapse blocks position:sticky in Chrome.
|
/* Sticky header — border-collapse:collapse blocks position:sticky in Chrome.
|
||||||
--sticky-top is set by JS when a bulk actions bar appears above the table. */
|
--sticky-top is set by JS when a bulk actions bar appears above the table. */
|
||||||
.admin-table--sticky {
|
.admin-table--sticky {
|
||||||
border-collapse: separate;
|
border-collapse: separate;
|
||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-table--sticky thead th {
|
.admin-table--sticky thead th {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: var(--sticky-top, 0px);
|
top: var(--sticky-top, 0px);
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
background: var(--bg-primary);
|
background: var(--bg-primary);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,68 +4,80 @@
|
|||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
#toast-region {
|
#toast-region {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: var(--space-l);
|
bottom: var(--space-l);
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
z-index: 10000;
|
z-index: 10000;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--space-xs);
|
gap: var(--space-xs);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
max-width: min(560px, calc(100vw - 2 * var(--space-l)));
|
max-width: min(560px, calc(100vw - 2 * var(--space-l)));
|
||||||
}
|
}
|
||||||
|
|
||||||
.toast {
|
.toast {
|
||||||
padding: var(--space-s) var(--space-m);
|
padding: var(--space-s) var(--space-m);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
font-size: var(--step-0);
|
font-size: var(--step-0);
|
||||||
border-left: 4px solid;
|
border-left: 4px solid;
|
||||||
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.25);
|
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.25);
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
/* enter then fade out — total visible ~6.35s */
|
/* enter then fade out — total visible ~6.35s */
|
||||||
animation: toast-enter 0.35s ease-out,
|
animation:
|
||||||
toast-exit 0.5s ease-in 6s forwards;
|
toast-enter 0.35s ease-out,
|
||||||
|
toast-exit 0.5s ease-in 6s forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toast--error {
|
.toast--error {
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
border-color: var(--error);
|
border-color: var(--error);
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.toast--success {
|
.toast--success {
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
border-color: var(--success);
|
border-color: var(--success);
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.toast--warning {
|
.toast--warning {
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
border-color: var(--warning);
|
border-color: var(--warning);
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
animation: toast-enter 0.35s ease-out;
|
animation: toast-enter 0.35s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toast--warning a {
|
.toast--warning a {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
transition: color 0.15s;
|
transition: color 0.15s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toast--warning a:hover {
|
.toast--warning a:hover {
|
||||||
color: var(--accent-primary);
|
color: var(--accent-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes toast-enter {
|
@keyframes toast-enter {
|
||||||
from { opacity: 0; transform: translateY(12px); }
|
from {
|
||||||
to { opacity: 1; transform: translateY(0); }
|
opacity: 0;
|
||||||
|
transform: translateY(12px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes toast-exit {
|
@keyframes toast-exit {
|
||||||
from { opacity: 1; }
|
from {
|
||||||
to { opacity: 0; pointer-events: none; }
|
opacity: 1;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,138 +8,138 @@
|
|||||||
/* ── Shared list styles (.toc-list) ─────────────────────────────────────── */
|
/* ── Shared list styles (.toc-list) ─────────────────────────────────────── */
|
||||||
.toc-list,
|
.toc-list,
|
||||||
.toc ul {
|
.toc ul {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--space-3xs);
|
gap: var(--space-3xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc-list a,
|
.toc-list a,
|
||||||
.toc ul a {
|
.toc ul a {
|
||||||
display: block;
|
display: block;
|
||||||
font-family: var(--font-body);
|
font-family: var(--font-body);
|
||||||
font-size: var(--step-0);
|
font-size: var(--step-0);
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding: var(--space-3xs) 0;
|
padding: var(--space-3xs) 0;
|
||||||
transition: color 0.15s;
|
transition: color 0.15s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc-list a:hover {
|
.toc-list a:hover {
|
||||||
color: var(--accent-primary);
|
color: var(--accent-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc-list a.toc-active,
|
.toc-list a.toc-active,
|
||||||
.toc ul a.toc-active {
|
.toc ul a.toc-active {
|
||||||
color: var(--accent-primary);
|
color: var(--accent-primary);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Public TOC (details/summary block) ─────────────────────────────────── */
|
/* ── Public TOC (details/summary block) ─────────────────────────────────── */
|
||||||
.toc {
|
.toc {
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc[open] {
|
.toc[open] {
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc > :not(summary) {
|
.toc > :not(summary) {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc summary {
|
.toc summary {
|
||||||
font-family: var(--font-display);
|
font-family: var(--font-display);
|
||||||
font-size: var(--step-1);
|
font-size: var(--step-1);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
padding: 0 0 var(--space-2xs) 0;
|
padding: 0 0 var(--space-2xs) 0;
|
||||||
border-bottom: 1px solid var(--text-primary);
|
border-bottom: 1px solid var(--text-primary);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--space-2xs);
|
gap: var(--space-2xs);
|
||||||
background: transparent;
|
background: transparent;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc summary::-webkit-details-marker {
|
.toc summary::-webkit-details-marker {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc summary:hover {
|
.toc summary:hover {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Caret icon inside summary — visible only on mobile */
|
/* Caret icon inside summary — visible only on mobile */
|
||||||
.toc-caret {
|
.toc-caret {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
transition: transform 0.2s ease;
|
transition: transform 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc[open] > summary .toc-caret {
|
.toc[open] > summary .toc-caret {
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sidebar links (about page — custom links below TOC) */
|
/* Sidebar links (about page — custom links below TOC) */
|
||||||
.toc-sidebar-link:first-of-type {
|
.toc-sidebar-link:first-of-type {
|
||||||
padding-top: var(--space-s);
|
padding-top: var(--space-s);
|
||||||
border-top: 1px solid var(--border-primary);
|
border-top: 1px solid var(--border-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc-sidebar-link + .toc-sidebar-link {
|
.toc-sidebar-link + .toc-sidebar-link {
|
||||||
padding-top: var(--space-xs);
|
padding-top: var(--space-xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc-sidebar-link a {
|
.toc-sidebar-link a {
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
color: var(--accent-primary);
|
color: var(--accent-primary);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
transition: opacity 0.15s;
|
transition: opacity 0.15s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc-sidebar-link a:hover {
|
.toc-sidebar-link a:hover {
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Desktop: sticky sidebar with independent scroll ──────────────────── */
|
/* ── Desktop: sticky sidebar with independent scroll ──────────────────── */
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.toc {
|
.toc {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: var(--space-l);
|
top: var(--space-l);
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
max-height: calc(100vh - var(--space-xl) - var(--space-2xl));
|
max-height: calc(100vh - var(--space-xl) - var(--space-2xl));
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overscroll-behavior: contain;
|
overscroll-behavior: contain;
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc summary {
|
.toc summary {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc-caret {
|
.toc-caret {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Mobile: collapsible TOC ────────────────────────────────────────────── */
|
/* ── Mobile: collapsible TOC ────────────────────────────────────────────── */
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
.toc {
|
.toc {
|
||||||
position: static;
|
position: static;
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc summary {
|
.toc summary {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
list-style: revert;
|
list-style: revert;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,52 +5,52 @@
|
|||||||
|
|
||||||
/* 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;
|
||||||
padding: var(--space-xl) var(--space-l) var(--space-2xl);
|
padding: var(--space-xl) var(--space-l) var(--space-2xl);
|
||||||
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) var(--space-xl);
|
padding: var(--space-m) var(--space-s) var(--space-xl);
|
||||||
}
|
}
|
||||||
|
|
||||||
.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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
@@ -58,107 +58,107 @@
|
|||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
.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;
|
||||||
padding-bottom: var(--space-xl);
|
padding-bottom: 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 :where(h1, h2, h3) {
|
.page-content > article :where(h1, h2, h3) {
|
||||||
margin: 1.5em 0 0.5em 0;
|
margin: 1.5em 0 0.5em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-content > article a {
|
.page-content > article a {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
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: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.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%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hide CommonMark heading permalink anchors */
|
/* Hide CommonMark heading permalink anchors */
|
||||||
.heading-permalink {
|
.heading-permalink {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
@@ -166,12 +166,12 @@
|
|||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
.content-section-title {
|
.content-section-title {
|
||||||
font-family: var(--font-display);
|
font-family: var(--font-display);
|
||||||
font-size: var(--step-3);
|
font-size: var(--step-3);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
@@ -179,48 +179,48 @@
|
|||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
.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;
|
||||||
border-bottom: 1px solid var(--border-primary);
|
border-bottom: 1px solid var(--border-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.apropos-contact-card:first-child {
|
.apropos-contact-card:first-child {
|
||||||
border-top: 1px solid var(--border-primary);
|
border-top: 1px solid var(--border-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.apropos-contact-card strong {
|
.apropos-contact-card strong {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: var(--step-0);
|
font-size: var(--step-0);
|
||||||
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;
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
.apropos-contact-card a {
|
.apropos-contact-card a {
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
color: inherit;
|
color: inherit;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
transition: color 0.15s;
|
transition: color 0.15s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.apropos-contact-card a:hover {
|
.apropos-contact-card a:hover {
|
||||||
color: var(--accent-primary);
|
color: var(--accent-primary);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
@@ -228,39 +228,39 @@
|
|||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
.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;
|
||||||
border-bottom: 1px solid var(--border-primary);
|
border-bottom: 1px solid var(--border-primary);
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.apropos-credit-row:first-child {
|
.apropos-credit-row:first-child {
|
||||||
border-top: 1px solid var(--border-primary);
|
border-top: 1px solid var(--border-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.apropos-credits-list dt {
|
.apropos-credits-list dt {
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--text-tertiary);
|
color: var(--text-tertiary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.apropos-credits-list dd {
|
.apropos-credits-list dd {
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
@@ -268,7 +268,7 @@
|
|||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
.apropos-single {
|
.apropos-single {
|
||||||
max-width: 720px;
|
max-width: 720px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
@@ -276,20 +276,20 @@
|
|||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
.page-content {
|
.page-content {
|
||||||
padding: var(--space-m) var(--space-s) var(--space-xl);
|
padding: var(--space-m) var(--space-s) var(--space-xl);
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-content > article {
|
.page-content > article {
|
||||||
font-size: var(--step-0);
|
font-size: var(--step-0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-section-title {
|
.content-section-title {
|
||||||
font-size: var(--step-2);
|
font-size: var(--step-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.apropos-credit-row {
|
.apropos-credit-row {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
gap: var(--space-3xs);
|
gap: var(--space-3xs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,245 +3,247 @@
|
|||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
.access-req-stats {
|
.access-req-stats {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||||
gap: var(--space-m);
|
gap: var(--space-m);
|
||||||
margin-bottom: var(--space-l);
|
margin-bottom: var(--space-l);
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-stat-card {
|
.access-req-stat-card {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: var(--space-m);
|
padding: var(--space-m);
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
border: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-stat-number {
|
.access-req-stat-number {
|
||||||
font-size: var(--step-2);
|
font-size: var(--step-2);
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-stat-label {
|
.access-req-stat-label {
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
margin-top: var(--space-3xs);
|
margin-top: var(--space-3xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tab navigation */
|
/* Tab navigation */
|
||||||
.access-req-tabs {
|
.access-req-tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--space-xs);
|
gap: var(--space-xs);
|
||||||
margin-bottom: var(--space-l);
|
margin-bottom: var(--space-l);
|
||||||
border-bottom: 2px solid var(--border-primary);
|
border-bottom: 2px solid var(--border-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-tab {
|
.access-req-tab {
|
||||||
padding: var(--space-2xs) var(--space-s);
|
padding: var(--space-2xs) var(--space-s);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
border-bottom: 2px solid transparent;
|
border-bottom: 2px solid transparent;
|
||||||
margin-bottom: -2px;
|
margin-bottom: -2px;
|
||||||
transition: color 0.2s, border-color 0.2s;
|
transition:
|
||||||
|
color 0.2s,
|
||||||
|
border-color 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-tab:hover {
|
.access-req-tab:hover {
|
||||||
color: var(--accent-primary);
|
color: var(--accent-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-tab.active {
|
.access-req-tab.active {
|
||||||
color: var(--accent-primary);
|
color: var(--accent-primary);
|
||||||
border-bottom-color: var(--accent-primary);
|
border-bottom-color: var(--accent-primary);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Empty state */
|
/* Empty state */
|
||||||
.access-req-empty {
|
.access-req-empty {
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
border: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
padding: var(--space-xl);
|
padding: var(--space-xl);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Request list */
|
/* Request list */
|
||||||
.access-req-list {
|
.access-req-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--space-m);
|
gap: var(--space-m);
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-card {
|
.access-req-card {
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
border: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
padding: var(--space-m);
|
padding: var(--space-m);
|
||||||
transition: box-shadow 0.2s;
|
transition: box-shadow 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-card:hover {
|
.access-req-card:hover {
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-card__header {
|
.access-req-card__header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: var(--space-m);
|
gap: var(--space-m);
|
||||||
margin-bottom: var(--space-s);
|
margin-bottom: var(--space-s);
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-card__thesis h3 {
|
.access-req-card__thesis h3 {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
margin: 0 0 var(--space-3xs) 0;
|
margin: 0 0 var(--space-3xs) 0;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-card__authors {
|
.access-req-card__authors {
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-card__meta {
|
.access-req-card__meta {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-badge {
|
.access-req-badge {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: var(--space-3xs) var(--space-2xs);
|
padding: var(--space-3xs) var(--space-2xs);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.05em;
|
letter-spacing: 0.05em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-badge--pending {
|
.access-req-badge--pending {
|
||||||
background: #fef3c7;
|
background: #fef3c7;
|
||||||
color: #92400e;
|
color: #92400e;
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-badge--approved {
|
.access-req-badge--approved {
|
||||||
background: #d1fae5;
|
background: #d1fae5;
|
||||||
color: #065f46;
|
color: #065f46;
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-badge--rejected {
|
.access-req-badge--rejected {
|
||||||
background: #fee2e2;
|
background: #fee2e2;
|
||||||
color: #991b1b;
|
color: #991b1b;
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-card__body {
|
.access-req-card__body {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--space-s);
|
gap: var(--space-s);
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-card__info {
|
.access-req-card__info {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: var(--space-m);
|
gap: var(--space-m);
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-card__info strong {
|
.access-req-card__info strong {
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
margin-right: var(--space-3xs);
|
margin-right: var(--space-3xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-card__info a {
|
.access-req-card__info a {
|
||||||
color: var(--accent-primary);
|
color: var(--accent-primary);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-card__info a:hover {
|
.access-req-card__info a:hover {
|
||||||
color: var(--accent-primary);
|
color: var(--accent-primary);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-card__justification,
|
.access-req-card__justification,
|
||||||
.access-req-card__admin-notes {
|
.access-req-card__admin-notes {
|
||||||
background: var(--bg-primary);
|
background: var(--bg-primary);
|
||||||
padding: var(--space-s);
|
padding: var(--space-s);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-card__justification strong,
|
.access-req-card__justification strong,
|
||||||
.access-req-card__admin-notes strong {
|
.access-req-card__admin-notes strong {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: var(--space-3xs);
|
margin-bottom: var(--space-3xs);
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-card__justification p,
|
.access-req-card__justification p,
|
||||||
.access-req-card__admin-notes p {
|
.access-req-card__admin-notes p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-card__actions {
|
.access-req-card__actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--space-s);
|
gap: var(--space-s);
|
||||||
margin-top: var(--space-s);
|
margin-top: var(--space-s);
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-btn {
|
.access-req-btn {
|
||||||
/* deprecated alias for .btn; kept for backward-compat */
|
/* deprecated alias for .btn; kept for backward-compat */
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-btn--approve {
|
.access-req-btn--approve {
|
||||||
/* deprecated alias for .btn--primary */
|
/* deprecated alias for .btn--primary */
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-btn--reject {
|
.access-req-btn--reject {
|
||||||
/* deprecated alias for .btn--danger */
|
/* deprecated alias for .btn--danger */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pagination */
|
/* Pagination */
|
||||||
.access-req-pagination {
|
.access-req-pagination {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--space-m);
|
gap: var(--space-m);
|
||||||
margin-top: var(--space-l);
|
margin-top: var(--space-l);
|
||||||
padding: var(--space-s) 0;
|
padding: var(--space-s) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-pagination__link {
|
.access-req-pagination__link {
|
||||||
padding: var(--space-2xs) var(--space-s);
|
padding: var(--space-2xs) var(--space-s);
|
||||||
color: var(--accent-primary);
|
color: var(--accent-primary);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
transition: color 0.2s;
|
transition: color 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-pagination__link:hover {
|
.access-req-pagination__link:hover {
|
||||||
color: var(--accent-primary);
|
color: var(--accent-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.access-req-pagination__info {
|
.access-req-pagination__info {
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dialog textarea/label enhancements */
|
/* Dialog textarea/label enhancements */
|
||||||
.admin-dialog textarea {
|
.admin-dialog textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: var(--space-2xs);
|
padding: var(--space-2xs);
|
||||||
margin: var(--space-s) 0;
|
margin: var(--space-s) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-dialog label {
|
.admin-dialog label {
|
||||||
display: block;
|
display: block;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
margin-bottom: var(--space-3xs);
|
margin-bottom: var(--space-3xs);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,293 +7,293 @@
|
|||||||
/* ── Recap files table ─────────────────────────────────────────── */
|
/* ── Recap files table ─────────────────────────────────────────── */
|
||||||
|
|
||||||
.recap-files-table {
|
.recap-files-table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.recap-files-table thead th {
|
.recap-files-table thead th {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.05em;
|
letter-spacing: 0.05em;
|
||||||
padding: var(--space-xs) var(--space-s);
|
padding: var(--space-xs) var(--space-s);
|
||||||
border-bottom: 2px solid var(--border-primary);
|
border-bottom: 2px solid var(--border-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.recap-files-table tbody td {
|
.recap-files-table tbody td {
|
||||||
padding: var(--space-xs) var(--space-s);
|
padding: var(--space-xs) var(--space-s);
|
||||||
border-bottom: 1px solid var(--border-secondary);
|
border-bottom: 1px solid var(--border-secondary);
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recap-files-table tbody tr:last-child td {
|
.recap-files-table tbody tr:last-child td {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recap-files-icon {
|
.recap-files-icon {
|
||||||
width: 1px;
|
width: 1px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recap-files-icon-emoji {
|
.recap-files-icon-emoji {
|
||||||
font-size: 1.3rem;
|
font-size: 1.3rem;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 2.2rem;
|
width: 2.2rem;
|
||||||
height: 2.2rem;
|
height: 2.2rem;
|
||||||
background: var(--accent-muted);
|
background: var(--accent-muted);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
.recap-files-thumb {
|
.recap-files-thumb {
|
||||||
max-width: 80px;
|
max-width: 80px;
|
||||||
max-height: 60px;
|
max-height: 60px;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
.recap-files-name {
|
.recap-files-name {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recap-files-name a {
|
.recap-files-name a {
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recap-files-name a:hover {
|
.recap-files-name a:hover {
|
||||||
color: var(--accent-primary);
|
color: var(--accent-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.recap-files-peertube-id {
|
.recap-files-peertube-id {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
color: var(--text-tertiary);
|
color: var(--text-tertiary);
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recap-files-label {
|
.recap-files-label {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recap-files-type {
|
.recap-files-type {
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
color: var(--text-tertiary);
|
color: var(--text-tertiary);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recap-files-size {
|
.recap-files-size {
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
color: var(--text-tertiary);
|
color: var(--text-tertiary);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recap-files-date {
|
.recap-files-date {
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
color: var(--text-tertiary);
|
color: var(--text-tertiary);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── File browser (relink) ──────────────────────────────────────── */
|
/* ── File browser (relink) ──────────────────────────────────────── */
|
||||||
|
|
||||||
.file-browser-trigger {
|
.file-browser-trigger {
|
||||||
margin-top: var(--space-2xs);
|
margin-top: var(--space-2xs);
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.relink-modal {
|
.relink-modal {
|
||||||
width: min(90vw, 700px);
|
width: min(90vw, 700px);
|
||||||
max-height: 80vh;
|
max-height: 80vh;
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
background: var(--bg-primary);
|
background: var(--bg-primary);
|
||||||
padding: 0;
|
padding: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
}
|
}
|
||||||
.relink-modal::backdrop {
|
.relink-modal::backdrop {
|
||||||
background: rgba(0,0,0,0.5);
|
background: rgba(0, 0, 0, 0.5);
|
||||||
}
|
}
|
||||||
.relink-modal-header {
|
.relink-modal-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: var(--space-s) var(--space-m);
|
padding: var(--space-s) var(--space-m);
|
||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
}
|
}
|
||||||
.relink-modal-header h3 {
|
.relink-modal-header h3 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: var(--step-0);
|
font-size: var(--step-0);
|
||||||
}
|
}
|
||||||
.relink-modal-footer {
|
.relink-modal-footer {
|
||||||
padding: var(--space-xs) var(--space-m);
|
padding: var(--space-xs) var(--space-m);
|
||||||
border-top: 1px solid var(--border);
|
border-top: 1px solid var(--border);
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
}
|
}
|
||||||
#relink-modal-body {
|
#relink-modal-body {
|
||||||
padding: var(--space-s) var(--space-m);
|
padding: var(--space-s) var(--space-m);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
max-height: 60vh;
|
max-height: 60vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── File browser tree ─────────────────────────────────────────── */
|
/* ── File browser tree ─────────────────────────────────────────── */
|
||||||
|
|
||||||
.file-browser {
|
.file-browser {
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
}
|
}
|
||||||
.file-browser-hint,
|
.file-browser-hint,
|
||||||
.file-browser-empty,
|
.file-browser-empty,
|
||||||
.file-browser-loading,
|
.file-browser-loading,
|
||||||
.file-browser-error {
|
.file-browser-error {
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: var(--space-m);
|
padding: var(--space-m);
|
||||||
}
|
}
|
||||||
.file-browser-error {
|
.file-browser-error {
|
||||||
color: var(--error);
|
color: var(--error);
|
||||||
}
|
}
|
||||||
.file-browser-breadcrumb {
|
.file-browser-breadcrumb {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--space-2xs);
|
gap: var(--space-2xs);
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
padding-bottom: var(--space-s);
|
padding-bottom: var(--space-s);
|
||||||
margin-bottom: var(--space-s);
|
margin-bottom: var(--space-s);
|
||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
}
|
}
|
||||||
.file-browser-breadcrumb a {
|
.file-browser-breadcrumb a {
|
||||||
color: var(--accent-blue, var(--link));
|
color: var(--accent-blue, var(--link));
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.file-browser-breadcrumb a:hover {
|
.file-browser-breadcrumb a:hover {
|
||||||
color: var(--accent-primary);
|
color: var(--accent-primary);
|
||||||
}
|
}
|
||||||
.file-browser-sep {
|
.file-browser-sep {
|
||||||
color: var(--text-tertiary);
|
color: var(--text-tertiary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-browser-list {
|
.file-browser-list {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
.file-browser-entry {
|
.file-browser-entry {
|
||||||
border-bottom: 1px solid var(--border-subtle);
|
border-bottom: 1px solid var(--border-subtle);
|
||||||
}
|
}
|
||||||
.file-browser-entry a,
|
.file-browser-entry a,
|
||||||
.file-browser-select-btn {
|
.file-browser-select-btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--space-xs);
|
gap: var(--space-xs);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: var(--space-xs) var(--space-2xs);
|
padding: var(--space-xs) var(--space-2xs);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
transition: background 0.15s;
|
transition: background 0.15s;
|
||||||
}
|
}
|
||||||
.file-browser-entry a:hover,
|
.file-browser-entry a:hover,
|
||||||
.file-browser-select-btn:hover {
|
.file-browser-select-btn:hover {
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
}
|
}
|
||||||
.file-browser-icon {
|
.file-browser-icon {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
font-size: var(--step-0);
|
font-size: var(--step-0);
|
||||||
}
|
}
|
||||||
.file-browser-name {
|
.file-browser-name {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.file-browser-size {
|
.file-browser-size {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
color: var(--text-tertiary);
|
color: var(--text-tertiary);
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
}
|
}
|
||||||
.file-browser-file .file-browser-select-btn {
|
.file-browser-file .file-browser-select-btn {
|
||||||
color: var(--accent-green, var(--success));
|
color: var(--accent-green, var(--success));
|
||||||
}
|
}
|
||||||
.file-browser-file .file-browser-select-btn:hover {
|
.file-browser-file .file-browser-select-btn:hover {
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Full-page editor (contenus-edit overtype) ─────────────────────── */
|
/* ── Full-page editor (contenus-edit overtype) ─────────────────────── */
|
||||||
|
|
||||||
/* Make the main content area a flex column so the form fills remaining height */
|
/* Make the main content area a flex column so the form fills remaining height */
|
||||||
.admin-body .full-editor-page {
|
.admin-body .full-editor-page {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-form--full-editor {
|
.admin-form--full-editor {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-form--full-editor #editor {
|
.admin-form--full-editor #editor {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-form--full-editor #editor .n-container {
|
.admin-form--full-editor #editor .n-container {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-form--full-editor #editor .n-wrapper {
|
.admin-form--full-editor #editor .n-wrapper {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-form--full-editor #editor .n-input {
|
.admin-form--full-editor #editor .n-input {
|
||||||
height: 100% !important;
|
height: 100%;
|
||||||
overflow-y: auto !important;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-form--full-editor #editor .n-preview {
|
.admin-form--full-editor #editor .n-preview {
|
||||||
height: 100% !important;
|
height: 100%;
|
||||||
overflow-y: auto !important;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.full-editor-toolbar {
|
.full-editor-toolbar {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--space-s);
|
gap: var(--space-s);
|
||||||
padding-bottom: var(--space-s);
|
padding-bottom: var(--space-s);
|
||||||
border-bottom: 1px solid var(--border-primary);
|
border-bottom: 1px solid var(--border-primary);
|
||||||
margin-bottom: var(--space-s);
|
margin-bottom: var(--space-s);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.full-editor-label {
|
.full-editor-label {
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.full-editor-toolbar .btn--primary {
|
.full-editor-toolbar .btn--primary {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|||||||
+686
-682
File diff suppressed because it is too large
Load Diff
+172
-172
@@ -5,267 +5,267 @@
|
|||||||
|
|
||||||
/* 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: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
background: var(--bg-primary);
|
background: var(--bg-primary);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
transition:
|
transition:
|
||||||
box-shadow 0.2s ease,
|
box-shadow 0.2s ease,
|
||||||
transform 0.2s ease;
|
transform 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card:hover {
|
.card:hover {
|
||||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.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;
|
||||||
}
|
}
|
||||||
|
|
||||||
.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;
|
transition: transform 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.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);
|
||||||
}
|
}
|
||||||
|
|
||||||
.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: 7px 7px 0 0;
|
border-radius: 7px 7px 0 0;
|
||||||
background: linear-gradient(
|
background: linear-gradient(
|
||||||
180deg,
|
180deg,
|
||||||
rgba(60, 133, 108, 1) 0%,
|
rgba(60, 133, 108, 1) 0%,
|
||||||
rgba(51, 191, 135, 1) 25%,
|
rgba(51, 191, 135, 1) 25%,
|
||||||
rgba(192, 93, 225, 1) 75%,
|
rgba(192, 93, 225, 1) 75%,
|
||||||
rgba(149, 87, 181, 1) 100%
|
rgba(149, 87, 181, 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;
|
||||||
border-top: 1px solid var(--border-primary);
|
border-top: 1px solid var(--border-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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
@@ -3,102 +3,131 @@
|
|||||||
originally used). Do not modify this file.
|
originally used). Do not modify this file.
|
||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
*, ::before, ::after {
|
*,
|
||||||
box-sizing: border-box;
|
::before,
|
||||||
|
::after {
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
font-family: system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';
|
font-family:
|
||||||
line-height: 1.15;
|
system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif,
|
||||||
-webkit-text-size-adjust: 100%;
|
"Apple Color Emoji", "Segoe UI Emoji";
|
||||||
tab-size: 4;
|
line-height: 1.15;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
tab-size: 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
b, strong {
|
b,
|
||||||
font-weight: bolder;
|
strong {
|
||||||
|
font-weight: bolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
code, kbd, pre, samp {
|
code,
|
||||||
font-family: ui-monospace, SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace;
|
kbd,
|
||||||
font-size: 1em;
|
pre,
|
||||||
|
samp {
|
||||||
|
font-family:
|
||||||
|
ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace;
|
||||||
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
small {
|
small {
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub, sup {
|
sub,
|
||||||
font-size: 75%;
|
sup {
|
||||||
line-height: 0;
|
font-size: 75%;
|
||||||
position: relative;
|
line-height: 0;
|
||||||
vertical-align: baseline;
|
position: relative;
|
||||||
|
vertical-align: baseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub { bottom: -0.25em; }
|
sub {
|
||||||
sup { top: -0.5em; }
|
bottom: -0.25em;
|
||||||
|
}
|
||||||
|
sup {
|
||||||
|
top: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
border-color: currentcolor;
|
border-color: currentcolor;
|
||||||
}
|
}
|
||||||
|
|
||||||
button, input, optgroup, select, textarea {
|
button,
|
||||||
font-family: inherit;
|
input,
|
||||||
font-size: 100%;
|
optgroup,
|
||||||
line-height: 1.15;
|
select,
|
||||||
margin: 0;
|
textarea {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 100%;
|
||||||
|
line-height: 1.15;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[type=button], [type=reset], [type=submit], button {
|
[type="button"],
|
||||||
-webkit-appearance: button;
|
[type="reset"],
|
||||||
|
[type="submit"],
|
||||||
|
button {
|
||||||
|
-webkit-appearance: button;
|
||||||
}
|
}
|
||||||
|
|
||||||
legend {
|
legend {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
progress {
|
progress {
|
||||||
vertical-align: baseline;
|
vertical-align: baseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-inner-spin-button,
|
::-webkit-inner-spin-button,
|
||||||
::-webkit-outer-spin-button {
|
::-webkit-outer-spin-button {
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
[type=search] {
|
[type="search"] {
|
||||||
-webkit-appearance: textfield;
|
-webkit-appearance: textfield;
|
||||||
outline-offset: -2px;
|
outline-offset: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-search-decoration {
|
::-webkit-search-decoration {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-file-upload-button {
|
::-webkit-file-upload-button {
|
||||||
-webkit-appearance: button;
|
-webkit-appearance: button;
|
||||||
font: inherit;
|
font: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
summary {
|
summary {
|
||||||
display: list-item;
|
display: list-item;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Additional minimal resets not in modern-normalize */
|
/* Additional minimal resets not in modern-normalize */
|
||||||
|
|
||||||
img, svg, video, canvas, audio, iframe, embed, object {
|
img,
|
||||||
display: block;
|
svg,
|
||||||
vertical-align: middle;
|
video,
|
||||||
|
canvas,
|
||||||
|
audio,
|
||||||
|
iframe,
|
||||||
|
embed,
|
||||||
|
object {
|
||||||
|
display: block;
|
||||||
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
img, video {
|
img,
|
||||||
max-width: 100%;
|
video {
|
||||||
height: auto;
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
[hidden] {
|
[hidden] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
+280
-233
@@ -4,352 +4,399 @@
|
|||||||
|
|
||||||
/* ── System page tabs ──────────────────────────────────────────────────── */
|
/* ── System page tabs ──────────────────────────────────────────────────── */
|
||||||
.sys-tabs {
|
.sys-tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0;
|
gap: 0;
|
||||||
border-bottom: 1px solid var(--border-primary);
|
border-bottom: 1px solid var(--border-primary);
|
||||||
margin-bottom: var(--space-m);
|
margin-bottom: var(--space-m);
|
||||||
}
|
}
|
||||||
.sys-tab {
|
.sys-tab {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: var(--space-3xs) var(--space-s);
|
padding: var(--space-3xs) var(--space-s);
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
border-bottom: 2px solid transparent;
|
border-bottom: 2px solid transparent;
|
||||||
margin-bottom: -1px;
|
margin-bottom: -1px;
|
||||||
transition: color .15s, border-color .15s;
|
transition:
|
||||||
|
color 0.15s,
|
||||||
|
border-color 0.15s;
|
||||||
}
|
}
|
||||||
.sys-tab:hover {
|
.sys-tab:hover {
|
||||||
color: var(--accent-primary);
|
color: var(--accent-primary);
|
||||||
}
|
}
|
||||||
.sys-tab.active {
|
.sys-tab.active {
|
||||||
color: var(--accent-primary);
|
color: var(--accent-primary);
|
||||||
border-bottom-color: var(--accent-primary);
|
border-bottom-color: var(--accent-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Status section (always-visible panel above tabs) ─────────────────── */
|
/* ── Status section (always-visible panel above tabs) ─────────────────── */
|
||||||
.sys-status-section {
|
.sys-status-section {
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
border: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
padding: var(--space-s) var(--space-m);
|
padding: var(--space-s) var(--space-m);
|
||||||
margin-bottom: var(--space-m);
|
margin-bottom: var(--space-m);
|
||||||
}
|
}
|
||||||
.sys-status-header {
|
.sys-status-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: var(--space-s);
|
margin-bottom: var(--space-s);
|
||||||
}
|
}
|
||||||
.sys-status-toggle {
|
.sys-status-toggle {
|
||||||
background: none;
|
background: none;
|
||||||
border: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
padding: var(--space-3xs) var(--space-2xs);
|
padding: var(--space-3xs) var(--space-2xs);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
transition: color .15s, border-color .15s;
|
transition:
|
||||||
|
color 0.15s,
|
||||||
|
border-color 0.15s;
|
||||||
}
|
}
|
||||||
.sys-status-toggle:hover {
|
.sys-status-toggle:hover {
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
border-color: var(--border-secondary);
|
border-color: var(--border-secondary);
|
||||||
}
|
}
|
||||||
.sys-status-meta {
|
.sys-status-meta {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
gap: var(--space-m) var(--space-l);
|
gap: var(--space-m) var(--space-l);
|
||||||
margin-top: var(--space-m);
|
margin-top: var(--space-m);
|
||||||
padding-top: var(--space-m);
|
padding-top: var(--space-m);
|
||||||
border-top: 1px solid var(--border-primary);
|
border-top: 1px solid var(--border-primary);
|
||||||
}
|
}
|
||||||
@media (max-width: 700px) {
|
@media (max-width: 700px) {
|
||||||
.sys-status-meta { grid-template-columns: 1fr; }
|
.sys-status-meta {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Status cards ──────────────────────────────────────────────────────── */
|
/* ── Status cards ──────────────────────────────────────────────────────── */
|
||||||
.srv-grid {
|
.srv-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||||
gap: var(--space-s);
|
gap: var(--space-s);
|
||||||
margin-bottom: var(--space-l);
|
margin-bottom: var(--space-l);
|
||||||
}
|
}
|
||||||
.srv-card {
|
.srv-card {
|
||||||
background: var(--bg-primary);
|
background: var(--bg-primary);
|
||||||
border: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
padding: var(--space-s) var(--space-m);
|
padding: var(--space-s) var(--space-m);
|
||||||
}
|
}
|
||||||
.srv-card__header {
|
.srv-card__header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: var(--space-3xs);
|
margin-bottom: var(--space-3xs);
|
||||||
}
|
}
|
||||||
.srv-card__name {
|
.srv-card__name {
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: .07em;
|
letter-spacing: 0.07em;
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
.srv-card__detail {
|
.srv-card__detail {
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
color: var(--text-tertiary);
|
color: var(--text-tertiary);
|
||||||
margin-top: var(--space-3xs);
|
margin-top: var(--space-3xs);
|
||||||
font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
|
font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
|
||||||
|
}
|
||||||
|
.status-ok {
|
||||||
|
color: var(--accent-green);
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: var(--step--1);
|
||||||
|
}
|
||||||
|
.status-warn {
|
||||||
|
color: var(--warning);
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: var(--step--1);
|
||||||
|
}
|
||||||
|
.status-err {
|
||||||
|
color: var(--error);
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: var(--step--1);
|
||||||
|
}
|
||||||
|
.status-unknown {
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: var(--step--1);
|
||||||
}
|
}
|
||||||
.status-ok { color: var(--accent-green); font-weight: 600; font-size: var(--step--1); }
|
|
||||||
.status-warn { color: var(--warning); font-weight: 600; font-size: var(--step--1); }
|
|
||||||
.status-err { color: var(--error); font-weight: 600; font-size: var(--step--1); }
|
|
||||||
.status-unknown { color: var(--text-tertiary); font-weight: 600; font-size: var(--step--1); }
|
|
||||||
|
|
||||||
.srv-section-title {
|
.srv-section-title {
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: .1em;
|
letter-spacing: 0.1em;
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
border-bottom: 1px solid var(--border-primary);
|
border-bottom: 1px solid var(--border-primary);
|
||||||
padding-bottom: var(--space-3xs);
|
padding-bottom: var(--space-3xs);
|
||||||
margin: 0 0 var(--space-s);
|
margin: 0 0 var(--space-s);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
/* Compact variant: no border, no margin — used inside sys-status-header */
|
/* Compact variant: no border, no margin — used inside sys-status-header */
|
||||||
.srv-section-title--compact {
|
.srv-section-title--compact {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border: none;
|
border: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
/* Sub-section variant: tighter bottom margin — used for PHP/disk sub-headings */
|
/* Sub-section variant: tighter bottom margin — used for PHP/disk sub-headings */
|
||||||
.srv-section-title--sub { margin-bottom: var(--space-xs); }
|
.srv-section-title--sub {
|
||||||
|
margin-bottom: var(--space-xs);
|
||||||
|
}
|
||||||
|
|
||||||
/* ── PHP info grid ─────────────────────────────────────────────────────── */
|
/* ── PHP info grid ─────────────────────────────────────────────────────── */
|
||||||
.php-grid {
|
.php-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
||||||
gap: var(--space-3xs) var(--space-xs);
|
gap: var(--space-3xs) var(--space-xs);
|
||||||
margin-bottom: var(--space-l);
|
margin-bottom: var(--space-l);
|
||||||
}
|
}
|
||||||
/* Flush variant: no bottom margin — used inside sys-status-meta cell */
|
/* Flush variant: no bottom margin — used inside sys-status-meta cell */
|
||||||
.php-grid--flush { margin-bottom: 0; }
|
.php-grid--flush {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
.php-item {
|
.php-item {
|
||||||
background: var(--bg-primary);
|
background: var(--bg-primary);
|
||||||
border: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
padding: var(--space-3xs) var(--space-xs);
|
padding: var(--space-3xs) var(--space-xs);
|
||||||
}
|
}
|
||||||
.php-item__key {
|
.php-item__key {
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: .06em;
|
letter-spacing: 0.06em;
|
||||||
color: var(--text-tertiary);
|
color: var(--text-tertiary);
|
||||||
}
|
}
|
||||||
.php-item__val {
|
.php-item__val {
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
|
font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
margin-top: var(--space-3xs);
|
margin-top: var(--space-3xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Disk bar ──────────────────────────────────────────────────────────── */
|
/* ── Disk bar ──────────────────────────────────────────────────────────── */
|
||||||
.disk-bar-wrap {
|
.disk-bar-wrap {
|
||||||
background: var(--border-primary);
|
background: var(--border-primary);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
height: 6px;
|
height: 6px;
|
||||||
margin-top: var(--space-2xs);
|
margin-top: var(--space-2xs);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.disk-bar {
|
.disk-bar {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
width: var(--disk-pct, 0%);
|
width: var(--disk-pct, 0%);
|
||||||
background: var(--disk-color, var(--accent-green));
|
background: var(--disk-color, var(--accent-green));
|
||||||
transition: width .3s;
|
transition: width 0.3s;
|
||||||
}
|
}
|
||||||
.disk-stats {
|
.disk-stats {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
margin-top: var(--space-3xs);
|
margin-top: var(--space-3xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Tab panel loading state ───────────────────────────────────────────── */
|
/* ── Tab panel loading state ───────────────────────────────────────────── */
|
||||||
#sys-tab-panel {
|
#sys-tab-panel {
|
||||||
min-height: 8rem;
|
min-height: 8rem;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
#sys-tab-panel.htmx-request {
|
#sys-tab-panel.htmx-request {
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
transition: opacity 0.1s;
|
transition: opacity 0.1s;
|
||||||
}
|
}
|
||||||
#sys-tab-panel.htmx-request::after {
|
#sys-tab-panel.htmx-request::after {
|
||||||
content: '';
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
background: repeating-linear-gradient(
|
background: repeating-linear-gradient(
|
||||||
-45deg,
|
-45deg,
|
||||||
transparent,
|
transparent,
|
||||||
transparent 6px,
|
transparent 6px,
|
||||||
rgba(0,0,0,0.03) 6px,
|
rgba(0, 0, 0, 0.03) 6px,
|
||||||
rgba(0,0,0,0.03) 12px
|
rgba(0, 0, 0, 0.03) 12px
|
||||||
);
|
);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
animation: sys-panel-shimmer 1s linear infinite;
|
animation: sys-panel-shimmer 1s linear infinite;
|
||||||
background-size: 200% 200%;
|
background-size: 200% 200%;
|
||||||
}
|
}
|
||||||
@keyframes sys-panel-shimmer {
|
@keyframes sys-panel-shimmer {
|
||||||
0% { background-position: 0 0; }
|
0% {
|
||||||
100% { background-position: 100% 100%; }
|
background-position: 0 0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
background-position: 100% 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Log viewer ────────────────────────────────────────────────────────── */
|
/* ── Log viewer ────────────────────────────────────────────────────────── */
|
||||||
.log-toolbar {
|
.log-toolbar {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--space-2xs);
|
gap: var(--space-2xs);
|
||||||
margin-bottom: var(--space-m);
|
margin-bottom: var(--space-m);
|
||||||
}
|
}
|
||||||
.log-toolbar label {
|
.log-toolbar label {
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
}
|
}
|
||||||
.log-toolbar select {
|
.log-toolbar select {
|
||||||
padding: var(--space-3xs) var(--space-xs);
|
padding: var(--space-3xs) var(--space-xs);
|
||||||
|
}
|
||||||
|
.log-toolbar select:focus {
|
||||||
|
outline: 2px solid var(--accent-primary);
|
||||||
}
|
}
|
||||||
.log-toolbar select:focus { outline: 2px solid var(--accent-primary); }
|
|
||||||
|
|
||||||
.log-meta {
|
.log-meta {
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
color: var(--text-tertiary);
|
color: var(--text-tertiary);
|
||||||
font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
|
font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
|
||||||
margin-bottom: var(--space-xs);
|
margin-bottom: var(--space-xs);
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--space-m);
|
gap: var(--space-m);
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.log-meta span::before {
|
||||||
|
content: attr(data-label) ": ";
|
||||||
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
.log-meta span::before { content: attr(data-label) ": "; opacity: .6; }
|
|
||||||
|
|
||||||
.log-unavailable {
|
.log-unavailable {
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
border: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
padding: var(--space-m);
|
padding: var(--space-m);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
}
|
}
|
||||||
.log-unavail-path {
|
.log-unavail-path {
|
||||||
font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
|
font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
margin-top: var(--space-3xs);
|
margin-top: var(--space-3xs);
|
||||||
opacity: .7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
.log-unavail-dev {
|
.log-unavail-dev {
|
||||||
margin-top: var(--space-2xs);
|
margin-top: var(--space-2xs);
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
opacity: .7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
.log-empty {
|
.log-empty {
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
padding: var(--space-s) 0;
|
padding: var(--space-s) 0;
|
||||||
}
|
}
|
||||||
.log-output {
|
.log-output {
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
border: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
padding: var(--space-s);
|
padding: var(--space-s);
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
font-family: ui-monospace, "SFMono-Regular", Consolas, "Courier New", monospace;
|
font-family:
|
||||||
font-size: var(--step--2);
|
ui-monospace, "SFMono-Regular", Consolas, "Courier New", monospace;
|
||||||
line-height: 1.55;
|
font-size: var(--step--2);
|
||||||
max-height: 62vh;
|
line-height: 1.55;
|
||||||
overflow-y: auto;
|
max-height: 62vh;
|
||||||
position: relative;
|
overflow-y: auto;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
.log-line {
|
.log-line {
|
||||||
display: block;
|
display: block;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
padding: var(--space-3xs) var(--space-3xs);
|
padding: var(--space-3xs) var(--space-3xs);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
.log-line + .log-line {
|
||||||
|
border-top: 1px solid var(--border-primary);
|
||||||
|
}
|
||||||
|
.log-crit {
|
||||||
|
color: var(--sys-syntax-crit);
|
||||||
|
background: var(--error-muted-bg);
|
||||||
|
}
|
||||||
|
.log-error {
|
||||||
|
color: var(--error);
|
||||||
|
}
|
||||||
|
.log-warn {
|
||||||
|
color: var(--warning);
|
||||||
|
}
|
||||||
|
.log-notice {
|
||||||
|
color: var(--sys-syntax-notice);
|
||||||
}
|
}
|
||||||
.log-line + .log-line { border-top: 1px solid var(--border-primary); }
|
|
||||||
.log-crit { color: var(--sys-syntax-crit); background: var(--error-muted-bg); }
|
|
||||||
.log-error { color: var(--error); }
|
|
||||||
.log-warn { color: var(--warning); }
|
|
||||||
.log-notice { color: var(--sys-syntax-notice); }
|
|
||||||
.log-line::before {
|
.log-line::before {
|
||||||
content: attr(data-n);
|
content: attr(data-n);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
min-width: 4ch;
|
min-width: 4ch;
|
||||||
margin-right: var(--space-xs);
|
margin-right: var(--space-xs);
|
||||||
opacity: .3;
|
opacity: 0.3;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
.log-count-badge {
|
.log-count-badge {
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
border: 1px solid var(--border-primary);
|
border: 1px solid var(--border-primary);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
padding: var(--space-3xs) var(--space-2xs);
|
padding: var(--space-3xs) var(--space-2xs);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
font-family: ui-monospace, monospace;
|
font-family: ui-monospace, monospace;
|
||||||
}
|
}
|
||||||
.log-copy-btn {
|
.log-copy-btn {
|
||||||
/* uses .btn--secondary .btn--sm but with absolute positioning overrides */
|
/* uses .btn--secondary .btn--sm but with absolute positioning overrides */
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: var(--space-2xs);
|
top: var(--space-2xs);
|
||||||
right: var(--space-2xs);
|
right: var(--space-2xs);
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
.log-copy-btn:hover {
|
.log-copy-btn:hover {
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
border-color: var(--accent-primary);
|
border-color: var(--accent-primary);
|
||||||
}
|
}
|
||||||
.log-copy-btn.copied {
|
.log-copy-btn.copied {
|
||||||
color: var(--accent-green);
|
color: var(--accent-green);
|
||||||
border-color: var(--accent-green);
|
border-color: var(--accent-green);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sys-refresh-note {
|
.sys-refresh-note {
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
margin-bottom: var(--space-m);
|
margin-bottom: var(--space-m);
|
||||||
}
|
}
|
||||||
.sys-refresh-note a {
|
.sys-refresh-note a {
|
||||||
color: var(--accent-primary);
|
color: var(--accent-primary);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.sys-refresh-note a:hover {
|
||||||
|
color: var(--accent-primary);
|
||||||
}
|
}
|
||||||
.sys-refresh-note a:hover { color: var(--accent-primary); }
|
|
||||||
|
|
||||||
/* ── Cache freshness badges ────────────────────────────────────────────── */
|
/* ── Cache freshness badges ────────────────────────────────────────────── */
|
||||||
.sys-cache-badge {
|
.sys-cache-badge {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: var(--step--2);
|
font-size: var(--step--2);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-family: ui-monospace, monospace;
|
font-family: ui-monospace, monospace;
|
||||||
padding: var(--space-3xs) var(--space-3xs);
|
padding: var(--space-3xs) var(--space-3xs);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
margin-left: var(--space-xs);
|
margin-left: var(--space-xs);
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
}
|
}
|
||||||
.sys-cache-badge--hit {
|
.sys-cache-badge--hit {
|
||||||
background: var(--warning-muted-bg);
|
background: var(--warning-muted-bg);
|
||||||
color: var(--warning);
|
color: var(--warning);
|
||||||
border: 1px solid var(--warning-muted-border);
|
border: 1px solid var(--warning-muted-border);
|
||||||
}
|
}
|
||||||
.sys-cache-badge--miss {
|
.sys-cache-badge--miss {
|
||||||
background: var(--success-muted-bg);
|
background: var(--success-muted-bg);
|
||||||
color: var(--success);
|
color: var(--success);
|
||||||
border: 1px solid var(--success-muted-border);
|
border: 1px solid var(--success-muted-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+141
-141
@@ -4,292 +4,292 @@
|
|||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
.tfe-main {
|
.tfe-main {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: var(--space-l) var(--space-m) var(--space-xl);
|
padding: var(--space-l) var(--space-m) var(--space-xl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stacked article layout */
|
/* Stacked article layout */
|
||||||
.tfe-layout {
|
.tfe-layout {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--space-xl);
|
gap: var(--space-xl);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Row 1: Author above Title */
|
/* Row 1: Author above Title */
|
||||||
.tfe-header-row {
|
.tfe-header-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--space-3xs);
|
gap: var(--space-3xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Row 2: Two columns — meta left, synopsis right */
|
/* Row 2: Two columns — meta left, synopsis right */
|
||||||
.tfe-content-row {
|
.tfe-content-row {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
gap: var(--space-xl);
|
gap: var(--space-xl);
|
||||||
align-items: start;
|
align-items: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Row 3: Files flex container */
|
/* Row 3: Files flex container */
|
||||||
.tfe-files {
|
.tfe-files {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: var(--space-m);
|
gap: var(--space-m);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tfe-file-item {
|
.tfe-file-item {
|
||||||
flex: 1 1 300px;
|
flex: 1 1 300px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
.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%;
|
||||||
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 {
|
||||||
height: clamp(300px, 80vh, 700px);
|
height: clamp(300px, 80vh, 700px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Synopsis column wrapper (context note + synopsis) */
|
/* Synopsis column wrapper (context note + synopsis) */
|
||||||
.tfe-synopsis-column {
|
.tfe-synopsis-column {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--space-xs);
|
gap: var(--space-xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tfe-synopsis-empty {
|
.tfe-synopsis-empty {
|
||||||
/* placeholder to maintain grid column */
|
/* placeholder to maintain grid column */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Author (p) — inline with title */
|
/* Author (p) — inline with title */
|
||||||
.tfe-author {
|
.tfe-author {
|
||||||
font-family: var(--font-display);
|
font-family: var(--font-display);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Title (h1) — inherits global scale from base.css */
|
/* Title (h1) — inherits global scale from base.css */
|
||||||
.tfe-title {
|
.tfe-title {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Metadata block */
|
/* Metadata block */
|
||||||
.tfe-meta {
|
.tfe-meta {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
.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: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
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: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--space-s);
|
gap: var(--space-s);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tfe-access-request-form .form-group {
|
.tfe-access-request-form .form-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
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 {
|
||||||
/* deprecated alias for .btn--primary; kept for backward-compat */
|
/* deprecated alias for .btn--primary; kept for backward-compat */
|
||||||
margin-top: var(--space-3xs);
|
margin-top: var(--space-3xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tfe-btn-request-access:hover:not(:disabled) {
|
.tfe-btn-request-access:hover:not(:disabled) {
|
||||||
/* handled by .btn--primary */
|
/* handled by .btn--primary */
|
||||||
}
|
}
|
||||||
|
|
||||||
.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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Responsive */
|
/* Responsive */
|
||||||
@media (max-width: 900px) {
|
@media (max-width: 900px) {
|
||||||
.tfe-content-row {
|
.tfe-content-row {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
gap: var(--space-l);
|
gap: var(--space-l);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tfe-file-item {
|
.tfe-file-item {
|
||||||
flex: 1 1 100%;
|
flex: 1 1 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tfe-title {
|
.tfe-title {
|
||||||
font-size: var(--step-2);
|
font-size: var(--step-2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,85 +7,85 @@
|
|||||||
/* ── Font faces ─────────────────────────────────────────────────────── */
|
/* ── Font faces ─────────────────────────────────────────────────────── */
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Ductus";
|
font-family: "Ductus";
|
||||||
src: url("../fonts/DuctusRegular.otf") format("opentype");
|
src: url("../fonts/DuctusRegular.otf") format("opentype");
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 398;
|
font-weight: 398;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "BBBDMSans";
|
font-family: "BBBDMSans";
|
||||||
src: url("../fonts/BBBDMSans-Light.otf") format("opentype");
|
src: url("../fonts/BBBDMSans-Light.otf") format("opentype");
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 298;
|
font-weight: 298;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "BBBDMSans";
|
font-family: "BBBDMSans";
|
||||||
src: url("/assets/fonts/BBBDMSans-Regular.otf") format("opentype");
|
src: url("/assets/fonts/BBBDMSans-Regular.otf") format("opentype");
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 398;
|
font-weight: 398;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "BBBDMSans";
|
font-family: "BBBDMSans";
|
||||||
src: url("../fonts/BBBDMSans-Medium.otf") format("opentype");
|
src: url("../fonts/BBBDMSans-Medium.otf") format("opentype");
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 498;
|
font-weight: 498;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "BBBDMSans";
|
font-family: "BBBDMSans";
|
||||||
src: url("../fonts/BBBDMSans-Bold.otf") format("opentype");
|
src: url("../fonts/BBBDMSans-Bold.otf") format("opentype");
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 698;
|
font-weight: 698;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Named font-size scale ──────────────────────────────────────────── */
|
/* ── Named font-size scale ──────────────────────────────────────────── */
|
||||||
/* @link https://utopia.fyi/type/calculator?c=360,18,1.2,1240,20,1.25,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
|
/* @link https://utopia.fyi/type/calculator?c=360,18,1.2,1240,20,1.25,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--step--2: clamp(0.7813rem, 0.7736rem + 0.0341vw, 0.8rem);
|
--step--2: clamp(0.7813rem, 0.7736rem + 0.0341vw, 0.8rem);
|
||||||
--step--1: clamp(0.9375rem, 0.9119rem + 0.1136vw, 1rem);
|
--step--1: clamp(0.9375rem, 0.9119rem + 0.1136vw, 1rem);
|
||||||
--step-0: clamp(1.125rem, 1.0739rem + 0.2273vw, 1.25rem);
|
--step-0: clamp(1.125rem, 1.0739rem + 0.2273vw, 1.25rem);
|
||||||
--step-1: clamp(1.35rem, 1.2631rem + 0.3864vw, 1.5625rem);
|
--step-1: clamp(1.35rem, 1.2631rem + 0.3864vw, 1.5625rem);
|
||||||
--step-2: clamp(1.62rem, 1.4837rem + 0.6057vw, 1.9531rem);
|
--step-2: clamp(1.62rem, 1.4837rem + 0.6057vw, 1.9531rem);
|
||||||
--step-3: clamp(1.944rem, 1.7405rem + 0.9044vw, 2.4414rem);
|
--step-3: clamp(1.944rem, 1.7405rem + 0.9044vw, 2.4414rem);
|
||||||
--step-4: clamp(2.3328rem, 2.0387rem + 1.3072vw, 3.0518rem);
|
--step-4: clamp(2.3328rem, 2.0387rem + 1.3072vw, 3.0518rem);
|
||||||
--step-5: clamp(2.7994rem, 2.384rem + 1.8461vw, 3.8147rem);
|
--step-5: clamp(2.7994rem, 2.384rem + 1.8461vw, 3.8147rem);
|
||||||
|
|
||||||
/* ── Named spacing scale ─────────────────────────────────────────── */
|
/* ── Named spacing scale ─────────────────────────────────────────── */
|
||||||
/* @link https://utopia.fyi/space/calculator?c=360,18,1.2,1240,20,1.25,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
|
/* @link https://utopia.fyi/space/calculator?c=360,18,1.2,1240,20,1.25,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
|
||||||
|
|
||||||
--space-3xs: clamp(0.3125rem, 0.3125rem + 0vw, 0.3125rem);
|
--space-3xs: clamp(0.3125rem, 0.3125rem + 0vw, 0.3125rem);
|
||||||
--space-2xs: clamp(0.5625rem, 0.5369rem + 0.1136vw, 0.625rem);
|
--space-2xs: clamp(0.5625rem, 0.5369rem + 0.1136vw, 0.625rem);
|
||||||
--space-xs: clamp(0.875rem, 0.8494rem + 0.1136vw, 0.9375rem);
|
--space-xs: clamp(0.875rem, 0.8494rem + 0.1136vw, 0.9375rem);
|
||||||
--space-s: clamp(1.125rem, 1.0739rem + 0.2273vw, 1.25rem);
|
--space-s: clamp(1.125rem, 1.0739rem + 0.2273vw, 1.25rem);
|
||||||
--space-m: clamp(1.6875rem, 1.6108rem + 0.3409vw, 1.875rem);
|
--space-m: clamp(1.6875rem, 1.6108rem + 0.3409vw, 1.875rem);
|
||||||
--space-l: clamp(2.25rem, 2.1477rem + 0.4545vw, 2.5rem);
|
--space-l: clamp(2.25rem, 2.1477rem + 0.4545vw, 2.5rem);
|
||||||
--space-xl: clamp(3.375rem, 3.2216rem + 0.6818vw, 3.75rem);
|
--space-xl: clamp(3.375rem, 3.2216rem + 0.6818vw, 3.75rem);
|
||||||
--space-2xl: clamp(4.5rem, 4.2955rem + 0.9091vw, 5rem);
|
--space-2xl: clamp(4.5rem, 4.2955rem + 0.9091vw, 5rem);
|
||||||
--space-3xl: clamp(6.75rem, 6.4432rem + 1.3636vw, 7.5rem);
|
--space-3xl: clamp(6.75rem, 6.4432rem + 1.3636vw, 7.5rem);
|
||||||
|
|
||||||
/* One-up pairs */
|
/* One-up pairs */
|
||||||
--space-3xs-2xs: clamp(0.3125rem, 0.1847rem + 0.5682vw, 0.625rem);
|
--space-3xs-2xs: clamp(0.3125rem, 0.1847rem + 0.5682vw, 0.625rem);
|
||||||
--space-2xs-xs: clamp(0.5625rem, 0.4091rem + 0.6818vw, 0.9375rem);
|
--space-2xs-xs: clamp(0.5625rem, 0.4091rem + 0.6818vw, 0.9375rem);
|
||||||
--space-xs-s: clamp(0.875rem, 0.7216rem + 0.6818vw, 1.25rem);
|
--space-xs-s: clamp(0.875rem, 0.7216rem + 0.6818vw, 1.25rem);
|
||||||
--space-s-m: clamp(1.125rem, 0.8182rem + 1.3636vw, 1.875rem);
|
--space-s-m: clamp(1.125rem, 0.8182rem + 1.3636vw, 1.875rem);
|
||||||
--space-m-l: clamp(1.6875rem, 1.3551rem + 1.4773vw, 2.5rem);
|
--space-m-l: clamp(1.6875rem, 1.3551rem + 1.4773vw, 2.5rem);
|
||||||
--space-l-xl: clamp(2.25rem, 1.6364rem + 2.7273vw, 3.75rem);
|
--space-l-xl: clamp(2.25rem, 1.6364rem + 2.7273vw, 3.75rem);
|
||||||
--space-xl-2xl: clamp(3.375rem, 2.7102rem + 2.9545vw, 5rem);
|
--space-xl-2xl: clamp(3.375rem, 2.7102rem + 2.9545vw, 5rem);
|
||||||
--space-2xl-3xl: clamp(4.5rem, 3.2727rem + 5.4545vw, 7.5rem);
|
--space-2xl-3xl: clamp(4.5rem, 3.2727rem + 5.4545vw, 7.5rem);
|
||||||
|
|
||||||
/* Custom pairs */
|
/* Custom pairs */
|
||||||
--space-s-l: clamp(1.125rem, 0.5625rem + 2.5vw, 2.5rem);
|
--space-s-l: clamp(1.125rem, 0.5625rem + 2.5vw, 2.5rem);
|
||||||
|
|
||||||
/* Font families */
|
/* Font families */
|
||||||
--font-body: "BBBDMSans", sans-serif;
|
--font-body: "BBBDMSans", sans-serif;
|
||||||
--font-display: "Ductus", sans-serif;
|
--font-display: "Ductus", sans-serif;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,47 +5,47 @@
|
|||||||
|
|
||||||
/* Visually-hidden but screen-reader-accessible */
|
/* Visually-hidden but screen-reader-accessible */
|
||||||
.sr-only {
|
.sr-only {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 1px;
|
width: 1px;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: -1px;
|
margin: -1px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
clip: rect(0, 0, 0, 0);
|
clip: rect(0, 0, 0, 0);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip-to-content link (visible only on keyboard focus) */
|
/* Skip-to-content link (visible only on keyboard focus) */
|
||||||
.skip-link {
|
.skip-link {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -999px;
|
top: -999px;
|
||||||
left: 1rem;
|
left: 1rem;
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
padding: var(--space-2xs) var(--space-s);
|
padding: var(--space-2xs) var(--space-s);
|
||||||
background: var(--accent-primary);
|
background: var(--accent-primary);
|
||||||
color: var(--accent-foreground);
|
color: var(--accent-foreground);
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
border-radius: 0 0 4px 4px;
|
border-radius: 0 0 4px 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.skip-link:focus {
|
.skip-link:focus {
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.skip-link:hover {
|
.skip-link:hover {
|
||||||
color: var(--accent-primary);
|
color: var(--accent-primary);
|
||||||
background: var(--accent-foreground);
|
background: var(--accent-foreground);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Respect user motion preferences */
|
/* Respect user motion preferences */
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
*,
|
*,
|
||||||
*::before,
|
*::before,
|
||||||
*::after {
|
*::after {
|
||||||
transition-duration: 0.01ms !important;
|
transition-duration: 0.01ms;
|
||||||
animation-duration: 0.01ms !important;
|
animation-duration: 0.01ms;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,43 +4,45 @@
|
|||||||
* Provides: dialog openers, clipboard copy, password dialog.
|
* Provides: dialog openers, clipboard copy, password dialog.
|
||||||
*/
|
*/
|
||||||
(() => {
|
(() => {
|
||||||
var createBtn = document.getElementById('open-create-dialog');
|
var createBtn = document.getElementById("open-create-dialog");
|
||||||
if (createBtn) {
|
if (createBtn) {
|
||||||
createBtn.addEventListener('click', () => {
|
createBtn.addEventListener("click", () => {
|
||||||
document.getElementById('create-dialog').showModal();
|
document.getElementById("create-dialog").showModal();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
var _pendingDeleteLinkId = null;
|
var _pendingDeleteLinkId = null;
|
||||||
|
|
||||||
function openDeleteLinkDialog(id) {
|
function _openDeleteLinkDialog(id) {
|
||||||
_pendingDeleteLinkId = id;
|
_pendingDeleteLinkId = id;
|
||||||
document.getElementById('delete-link-dialog').showModal();
|
document.getElementById("delete-link-dialog").showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
function _executeDeleteLink() {
|
function _executeDeleteLink() {
|
||||||
var form = document.getElementById('delete-link-form-' + _pendingDeleteLinkId);
|
var form = document.getElementById(
|
||||||
if (form) form.submit();
|
`delete-link-form-${_pendingDeleteLinkId}`,
|
||||||
|
);
|
||||||
|
if (form) form.submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyUrl(id) {
|
function _copyUrl(id) {
|
||||||
var input = document.getElementById('url-' + id);
|
var input = document.getElementById(`url-${id}`);
|
||||||
navigator.clipboard.writeText(input.value).then(() => {
|
navigator.clipboard.writeText(input.value).then(() => {
|
||||||
var btn = event.target.closest('button');
|
var btn = event.target.closest("button");
|
||||||
var orig = btn.textContent;
|
var orig = btn.textContent;
|
||||||
btn.textContent = '✓ Copié';
|
btn.textContent = "✓ Copié";
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
btn.textContent = orig;
|
btn.textContent = orig;
|
||||||
}, 1200);
|
}, 1200);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function openPasswordDialog(id, hasPassword) {
|
function _openPasswordDialog(id, hasPassword) {
|
||||||
document.getElementById('password-link-id').value = id;
|
document.getElementById("password-link-id").value = id;
|
||||||
var info = document.getElementById('password-current-info');
|
var info = document.getElementById("password-current-info");
|
||||||
info.textContent = hasPassword
|
info.textContent = hasPassword
|
||||||
? 'Un mot de passe est actuellement configuré. Entrez-en un nouveau ou laissez vide pour le supprimer.'
|
? "Un mot de passe est actuellement configuré. Entrez-en un nouveau ou laissez vide pour le supprimer."
|
||||||
: 'Aucun mot de passe configuré.';
|
: "Aucun mot de passe configuré.";
|
||||||
document.getElementById('password-dialog').showModal();
|
document.getElementById("password-dialog").showModal();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,99 +7,105 @@
|
|||||||
* <meta name="acces-new-link-slug" content="...">
|
* <meta name="acces-new-link-slug" content="...">
|
||||||
*/
|
*/
|
||||||
(() => {
|
(() => {
|
||||||
var baseUrlMeta = document.querySelector('meta[name="acces-base-url"]');
|
var baseUrlMeta = document.querySelector('meta[name="acces-base-url"]');
|
||||||
var passwordMeta = document.querySelector('meta[name="acces-new-link-password"]');
|
var passwordMeta = document.querySelector(
|
||||||
var slugMeta = document.querySelector('meta[name="acces-new-link-slug"]');
|
'meta[name="acces-new-link-password"]',
|
||||||
|
);
|
||||||
|
var slugMeta = document.querySelector('meta[name="acces-new-link-slug"]');
|
||||||
|
|
||||||
// Show result dialog after redirect (new link created)
|
// Show result dialog after redirect (new link created)
|
||||||
if (passwordMeta && slugMeta && passwordMeta.content && slugMeta.content) {
|
if (passwordMeta && slugMeta && passwordMeta.content && slugMeta.content) {
|
||||||
document.getElementById('create-result-password').value = passwordMeta.content;
|
document.getElementById("create-result-password").value =
|
||||||
document.getElementById('create-result-url').value =
|
passwordMeta.content;
|
||||||
(baseUrlMeta ? baseUrlMeta.content : '') + '/partage/' + slugMeta.content;
|
document.getElementById("create-result-url").value =
|
||||||
document.getElementById('create-result-dialog').showModal();
|
`${baseUrlMeta ? baseUrlMeta.content : ""}/partage/${slugMeta.content}`;
|
||||||
}
|
document.getElementById("create-result-dialog").showModal();
|
||||||
|
}
|
||||||
|
|
||||||
// Create dialog opener
|
// Create dialog opener
|
||||||
var createBtn = document.getElementById('open-create-dialog');
|
var createBtn = document.getElementById("open-create-dialog");
|
||||||
if (createBtn) {
|
if (createBtn) {
|
||||||
createBtn.addEventListener('click', () => {
|
createBtn.addEventListener("click", () => {
|
||||||
document.getElementById('create-dialog').showModal();
|
document.getElementById("create-dialog").showModal();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
function copyUrl(id) {
|
function _copyUrl(id) {
|
||||||
var input = document.getElementById('url-' + id);
|
var input = document.getElementById(`url-${id}`);
|
||||||
navigator.clipboard.writeText(input.value).then(() => {
|
navigator.clipboard.writeText(input.value).then(() => {
|
||||||
var btn = event.target.closest('button');
|
var btn = event.target.closest("button");
|
||||||
if (btn) {
|
if (btn) {
|
||||||
var orig = btn.getAttribute('title') || '';
|
const orig = btn.getAttribute("title") || "";
|
||||||
btn.setAttribute('title', '✓ Copié');
|
btn.setAttribute("title", "✓ Copié");
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
btn.setAttribute('title', orig);
|
btn.setAttribute("title", orig);
|
||||||
}, 1200);
|
}, 1200);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyUrlFrom(el) {
|
function _copyUrlFrom(el) {
|
||||||
navigator.clipboard.writeText(el.value).then(() => {
|
navigator.clipboard.writeText(el.value).then(() => {
|
||||||
var btn = el.nextElementSibling;
|
const btn = el.nextElementSibling;
|
||||||
if (btn) {
|
if (btn) {
|
||||||
var orig = btn.textContent;
|
const orig = btn.textContent;
|
||||||
btn.textContent = '✓ Copié';
|
btn.textContent = "✓ Copié";
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
btn.textContent = orig;
|
btn.textContent = orig;
|
||||||
}, 1200);
|
}, 1200);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyTextToClipboard(text) {
|
function _copyTextToClipboard(text) {
|
||||||
navigator.clipboard.writeText(text)
|
navigator.clipboard
|
||||||
.then(() => {
|
.writeText(text)
|
||||||
var btn = event && event.target ? event.target.closest('button') : null;
|
.then(() => {
|
||||||
if (btn) {
|
const btn = event?.target ? event.target.closest("button") : null;
|
||||||
var orig = btn.getAttribute('title') || '';
|
if (btn) {
|
||||||
btn.setAttribute('title', '✓ Copié');
|
const orig = btn.getAttribute("title") || "";
|
||||||
setTimeout(() => {
|
btn.setAttribute("title", "✓ Copié");
|
||||||
btn.setAttribute('title', orig);
|
setTimeout(() => {
|
||||||
}, 1200);
|
btn.setAttribute("title", orig);
|
||||||
}
|
}, 1200);
|
||||||
})
|
}
|
||||||
.catch(() => {});
|
})
|
||||||
|
.catch(() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
function openEditDialog(id, name, hasPassword, expiresVal) {
|
function _openEditDialog(id, name, _hasPassword, expiresVal) {
|
||||||
document.getElementById('edit-link-id').value = id;
|
document.getElementById("edit-link-id").value = id;
|
||||||
document.getElementById('edit-name').value = name || '';
|
document.getElementById("edit-name").value = name || "";
|
||||||
document.getElementById('edit-expires').value = expiresVal || '';
|
document.getElementById("edit-expires").value = expiresVal || "";
|
||||||
document.getElementById('edit-dialog').showModal();
|
document.getElementById("edit-dialog").showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
function openApproveDialog(requestId) {
|
function _openApproveDialog(requestId) {
|
||||||
document.getElementById('approve-request-id').value = requestId;
|
document.getElementById("approve-request-id").value = requestId;
|
||||||
document.getElementById('approve-dialog').showModal();
|
document.getElementById("approve-dialog").showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
function openRejectDialog(requestId) {
|
function _openRejectDialog(requestId) {
|
||||||
document.getElementById('reject-request-id').value = requestId;
|
document.getElementById("reject-request-id").value = requestId;
|
||||||
document.getElementById('reject-dialog').showModal();
|
document.getElementById("reject-dialog").showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
var _pendingArchiveLinkId = null;
|
var _pendingArchiveLinkId = null;
|
||||||
|
|
||||||
function openArchiveLinkDialog(id) {
|
function _openArchiveLinkDialog(id) {
|
||||||
_pendingArchiveLinkId = id;
|
_pendingArchiveLinkId = id;
|
||||||
document.getElementById('archive-link-dialog').showModal();
|
document.getElementById("archive-link-dialog").showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
function _executeArchiveLink() {
|
function _executeArchiveLink() {
|
||||||
var form = document.getElementById('archive-link-form-' + _pendingArchiveLinkId);
|
var form = document.getElementById(
|
||||||
if (form) form.submit();
|
`archive-link-form-${_pendingArchiveLinkId}`,
|
||||||
|
);
|
||||||
|
if (form) form.submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
function openDeleteArchivedLinkDialog(id) {
|
function _openDeleteArchivedLinkDialog(id) {
|
||||||
document.getElementById('delete-archived-link-id').value = id;
|
document.getElementById("delete-archived-link-id").value = id;
|
||||||
document.getElementById('delete-archived-link-dialog').showModal();
|
document.getElementById("delete-archived-link-dialog").showModal();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,67 +5,72 @@
|
|||||||
* All functions are attached to `window` for onclick handlers in PHP templates.
|
* All functions are attached to `window` for onclick handlers in PHP templates.
|
||||||
*/
|
*/
|
||||||
(() => {
|
(() => {
|
||||||
function cleanupToggleAll(src, group) {
|
function cleanupToggleAll(src, group) {
|
||||||
const selector = group === 'filepond'
|
const selector =
|
||||||
? 'input[name="filepond_dirs[]"]'
|
group === "filepond"
|
||||||
: 'input[name="trash_files[]"]';
|
? 'input[name="filepond_dirs[]"]'
|
||||||
document.querySelectorAll(selector).forEach((cb) => {
|
: 'input[name="trash_files[]"]';
|
||||||
cb.checked = src.checked;
|
document.querySelectorAll(selector).forEach((cb) => {
|
||||||
});
|
cb.checked = src.checked;
|
||||||
cleanupUpdateBulk();
|
});
|
||||||
}
|
cleanupUpdateBulk();
|
||||||
|
}
|
||||||
|
|
||||||
function cleanupUpdateBulk() {
|
function cleanupUpdateBulk() {
|
||||||
const bar = document.getElementById('cleanup-bulk-actions');
|
const bar = document.getElementById("cleanup-bulk-actions");
|
||||||
const countEl = document.getElementById('cleanup-selected-count');
|
const countEl = document.getElementById("cleanup-selected-count");
|
||||||
if (!bar || !countEl) return;
|
if (!bar || !countEl) return;
|
||||||
|
|
||||||
const n = document.querySelectorAll(
|
const n = document.querySelectorAll(
|
||||||
'input[name="filepond_dirs[]"]:checked, input[name="trash_files[]"]:checked'
|
'input[name="filepond_dirs[]"]:checked, input[name="trash_files[]"]:checked',
|
||||||
).length;
|
).length;
|
||||||
countEl.textContent = n;
|
countEl.textContent = n;
|
||||||
bar.style.display = n > 0 ? 'flex' : 'none';
|
bar.style.display = n > 0 ? "flex" : "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanupBulkDelete() {
|
function cleanupBulkDelete() {
|
||||||
const form = document.getElementById('cleanup-bulk-form');
|
const form = document.getElementById("cleanup-bulk-form");
|
||||||
const container = document.getElementById('cleanup-bulk-checkboxes');
|
const container = document.getElementById("cleanup-bulk-checkboxes");
|
||||||
if (!form || !container) return;
|
if (!form || !container) return;
|
||||||
|
|
||||||
// Populate hidden inputs from checked checkboxes
|
// Populate hidden inputs from checked checkboxes
|
||||||
container.innerHTML = '';
|
container.innerHTML = "";
|
||||||
document.querySelectorAll(
|
document
|
||||||
'input[name="filepond_dirs[]"]:checked, input[name="trash_files[]"]:checked'
|
.querySelectorAll(
|
||||||
).forEach((cb) => {
|
'input[name="filepond_dirs[]"]:checked, input[name="trash_files[]"]:checked',
|
||||||
const inp = document.createElement('input');
|
)
|
||||||
inp.type = 'hidden';
|
.forEach((cb) => {
|
||||||
inp.name = cb.name; // "filepond_dirs[]" or "trash_files[]"
|
const inp = document.createElement("input");
|
||||||
inp.value = cb.value;
|
inp.type = "hidden";
|
||||||
container.appendChild(inp);
|
inp.name = cb.name; // "filepond_dirs[]" or "trash_files[]"
|
||||||
});
|
inp.value = cb.value;
|
||||||
|
container.appendChild(inp);
|
||||||
|
});
|
||||||
|
|
||||||
// Submit via HTMX
|
// Submit via HTMX
|
||||||
htmx.trigger(form, 'submit');
|
htmx.trigger(form, "submit");
|
||||||
}
|
}
|
||||||
|
|
||||||
function reattachListeners() {
|
function reattachListeners() {
|
||||||
document.querySelectorAll(
|
document
|
||||||
'input[name="filepond_dirs[]"], input[name="trash_files[]"]'
|
.querySelectorAll(
|
||||||
).forEach((cb) => {
|
'input[name="filepond_dirs[]"], input[name="trash_files[]"]',
|
||||||
cb.addEventListener('change', cleanupUpdateBulk);
|
)
|
||||||
});
|
.forEach((cb) => {
|
||||||
cleanupUpdateBulk();
|
cb.addEventListener("change", cleanupUpdateBulk);
|
||||||
}
|
});
|
||||||
|
cleanupUpdateBulk();
|
||||||
|
}
|
||||||
|
|
||||||
document.addEventListener('htmx:afterSwap', (evt) => {
|
document.addEventListener("htmx:afterSwap", (evt) => {
|
||||||
// Only reattach if the swap target is our cleanup wrapper
|
// Only reattach if the swap target is our cleanup wrapper
|
||||||
if (evt.detail.target.id === 'tmp-cleanup-stats-wrapper') {
|
if (evt.detail.target.id === "tmp-cleanup-stats-wrapper") {
|
||||||
reattachListeners();
|
reattachListeners();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Export to global scope for onclick handlers in HTML
|
// Export to global scope for onclick handlers in HTML
|
||||||
window.cleanupToggleAll = cleanupToggleAll;
|
window.cleanupToggleAll = cleanupToggleAll;
|
||||||
window.cleanupUpdateBulk = cleanupUpdateBulk;
|
window.cleanupUpdateBulk = cleanupUpdateBulk;
|
||||||
window.cleanupBulkDelete = cleanupBulkDelete;
|
window.cleanupBulkDelete = cleanupBulkDelete;
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -5,87 +5,88 @@
|
|||||||
* Expects templates with ids `entry-template-f-{key}` and `group-template-f-{key}`.
|
* Expects templates with ids `entry-template-f-{key}` and `group-template-f-{key}`.
|
||||||
*/
|
*/
|
||||||
(() => {
|
(() => {
|
||||||
var form = document.querySelector('form[data-apropos-key]');
|
var form = document.querySelector("form[data-apropos-key]");
|
||||||
if (!form) return;
|
if (!form) return;
|
||||||
|
|
||||||
var key = form.dataset.aproposKey;
|
var key = form.dataset.aproposKey;
|
||||||
var groupCount = parseInt(form.dataset.aproposGroupCount, 10) || 0;
|
var groupCount = parseInt(form.dataset.aproposGroupCount, 10) || 0;
|
||||||
var entryTpl = document.getElementById('entry-template-f-' + key).innerHTML;
|
var entryTpl = document.getElementById(`entry-template-f-${key}`).innerHTML;
|
||||||
var groupTpl = document.getElementById('group-template-f-' + key).innerHTML;
|
var groupTpl = document.getElementById(`group-template-f-${key}`).innerHTML;
|
||||||
|
|
||||||
function reindexGroups() {
|
function reindexGroups() {
|
||||||
var fieldsets = form.querySelectorAll('fieldset.apropos-group');
|
var fieldsets = form.querySelectorAll("fieldset.apropos-group");
|
||||||
groupCount = fieldsets.length;
|
groupCount = fieldsets.length;
|
||||||
fieldsets.forEach((fs, i) => {
|
fieldsets.forEach((fs, i) => {
|
||||||
var newIdx = i;
|
var newIdx = i;
|
||||||
var legend = fs.querySelector('legend');
|
var legend = fs.querySelector("legend");
|
||||||
if (legend) legend.textContent = 'Contact ' + (newIdx + 1);
|
if (legend) legend.textContent = `Contact ${newIdx + 1}`;
|
||||||
|
|
||||||
fs.querySelectorAll('input').forEach((inp) => {
|
fs.querySelectorAll("input").forEach((inp) => {
|
||||||
if (inp.name) {
|
if (inp.name) {
|
||||||
inp.name = inp.name.replace(/groups\[\d+\]/, 'groups[' + newIdx + ']');
|
inp.name = inp.name.replace(/groups\[\d+\]/, `groups[${newIdx}]`);
|
||||||
}
|
}
|
||||||
if (inp.id) {
|
if (inp.id) {
|
||||||
inp.id = inp.id.replace(
|
inp.id = inp.id.replace(
|
||||||
/(group_f_contacts_|entry_f_contacts_)\d+/,
|
/(group_f_contacts_|entry_f_contacts_)\d+/,
|
||||||
'$1' + newIdx
|
`$1${newIdx}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
fs.querySelectorAll('label[for]').forEach((lbl) => {
|
fs.querySelectorAll("label[for]").forEach((lbl) => {
|
||||||
lbl.setAttribute(
|
lbl.setAttribute(
|
||||||
'for',
|
"for",
|
||||||
lbl.getAttribute('for').replace(
|
lbl
|
||||||
/(group_f_contacts_|entry_f_contacts_)\d+/,
|
.getAttribute("for")
|
||||||
'$1' + newIdx
|
.replace(/(group_f_contacts_|entry_f_contacts_)\d+/, `$1${newIdx}`),
|
||||||
)
|
);
|
||||||
);
|
});
|
||||||
});
|
|
||||||
|
|
||||||
var addBtn = fs.querySelector('.add-entry-btn-f');
|
var addBtn = fs.querySelector(".add-entry-btn-f");
|
||||||
if (addBtn) addBtn.dataset.group = newIdx;
|
if (addBtn) addBtn.dataset.group = newIdx;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function bindAddEntry(btn) {
|
function bindAddEntry(btn) {
|
||||||
btn.addEventListener('click', function () {
|
btn.addEventListener("click", function () {
|
||||||
var gi = parseInt(this.dataset.group);
|
var gi = parseInt(this.dataset.group, 10);
|
||||||
var fieldset = this.closest('fieldset');
|
var fieldset = this.closest("fieldset");
|
||||||
var entryCount = fieldset.querySelectorAll('.apropos-entry').length;
|
var entryCount = fieldset.querySelectorAll(".apropos-entry").length;
|
||||||
var html = entryTpl.replaceAll('{{gi}}', gi).replaceAll('{{ei}}', entryCount);
|
var html = entryTpl
|
||||||
this.insertAdjacentHTML('beforebegin', html);
|
.replaceAll("{{gi}}", gi)
|
||||||
});
|
.replaceAll("{{ei}}", entryCount);
|
||||||
}
|
this.insertAdjacentHTML("beforebegin", html);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function bindDeleteGroup(btn) {
|
function bindDeleteGroup(btn) {
|
||||||
btn.addEventListener('click', function () {
|
btn.addEventListener("click", function () {
|
||||||
var fieldset = this.closest('fieldset');
|
var fieldset = this.closest("fieldset");
|
||||||
if (fieldset) {
|
if (fieldset) {
|
||||||
fieldset.remove();
|
fieldset.remove();
|
||||||
reindexGroups();
|
reindexGroups();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind existing buttons
|
// Bind existing buttons
|
||||||
form.querySelectorAll('.add-entry-btn-f').forEach(bindAddEntry);
|
form.querySelectorAll(".add-entry-btn-f").forEach(bindAddEntry);
|
||||||
form.querySelectorAll('.delete-group-btn-f').forEach(bindDeleteGroup);
|
form.querySelectorAll(".delete-group-btn-f").forEach(bindDeleteGroup);
|
||||||
|
|
||||||
form.querySelector('.add-group-btn-f').addEventListener('click', function () {
|
form.querySelector(".add-group-btn-f").addEventListener("click", function () {
|
||||||
groupCount++;
|
groupCount++;
|
||||||
var html = groupTpl.replaceAll('{{gi}}', groupCount);
|
var html = groupTpl.replaceAll("{{gi}}", groupCount);
|
||||||
this.insertAdjacentHTML('beforebegin', html);
|
this.insertAdjacentHTML("beforebegin", html);
|
||||||
|
|
||||||
var newGroup = this.previousElementSibling;
|
var newGroup = this.previousElementSibling;
|
||||||
if (newGroup && newGroup.classList.contains('apropos-group')) {
|
if (newGroup?.classList.contains("apropos-group")) {
|
||||||
var addBtn = newGroup.querySelector('.add-entry-btn-f');
|
var addBtn = newGroup.querySelector(".add-entry-btn-f");
|
||||||
if (addBtn) {
|
if (addBtn) {
|
||||||
addBtn.dataset.group = groupCount;
|
addBtn.dataset.group = groupCount;
|
||||||
bindAddEntry(addBtn);
|
bindAddEntry(addBtn);
|
||||||
}
|
}
|
||||||
var delBtn = newGroup.querySelector('.delete-group-btn-f');
|
var delBtn = newGroup.querySelector(".delete-group-btn-f");
|
||||||
if (delBtn) bindDeleteGroup(delBtn);
|
if (delBtn) bindDeleteGroup(delBtn);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -7,111 +7,126 @@
|
|||||||
*/
|
*/
|
||||||
var _languesPendingForm = null;
|
var _languesPendingForm = null;
|
||||||
|
|
||||||
function languesConfirmDelete(btn, name) {
|
function _languesConfirmDelete(btn, name) {
|
||||||
_languesPendingForm = btn.closest('form');
|
_languesPendingForm = btn.closest("form");
|
||||||
document.getElementById('langues-delete-name').textContent = name;
|
document.getElementById("langues-delete-name").textContent = name;
|
||||||
document.getElementById('langues-delete-dialog').showModal();
|
document.getElementById("langues-delete-dialog").showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
function languesSubmitPending() {
|
function _languesSubmitPending() {
|
||||||
if (_languesPendingForm) _languesPendingForm.submit();
|
if (_languesPendingForm) _languesPendingForm.submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
function languesToggleAll(src) {
|
function _languesToggleAll(src) {
|
||||||
document.querySelectorAll('input[name="selected_langs[]"]').forEach((cb) => {
|
document.querySelectorAll('input[name="selected_langs[]"]').forEach((cb) => {
|
||||||
cb.checked = src.checked;
|
cb.checked = src.checked;
|
||||||
});
|
});
|
||||||
languesUpdateBulk();
|
languesUpdateBulk();
|
||||||
}
|
}
|
||||||
|
|
||||||
function languesUpdateBulk() {
|
function languesUpdateBulk() {
|
||||||
var n = document.querySelectorAll('input[name="selected_langs[]"]:checked').length;
|
var n = document.querySelectorAll(
|
||||||
document.getElementById('langues-selected-count').textContent = n;
|
'input[name="selected_langs[]"]:checked',
|
||||||
var bar = document.getElementById('langues-bulk-actions');
|
).length;
|
||||||
var wrap = document.getElementById('langues-table-wrap');
|
document.getElementById("langues-selected-count").textContent = n;
|
||||||
var visible = n > 1;
|
var bar = document.getElementById("langues-bulk-actions");
|
||||||
bar.style.display = visible ? 'flex' : 'none';
|
var wrap = document.getElementById("langues-table-wrap");
|
||||||
if (visible) {
|
var visible = n > 1;
|
||||||
requestAnimationFrame(() => {
|
bar.style.display = visible ? "flex" : "none";
|
||||||
wrap.style.setProperty('--sticky-top', bar.offsetHeight + 'px');
|
if (visible) {
|
||||||
});
|
requestAnimationFrame(() => {
|
||||||
} else {
|
wrap.style.setProperty("--sticky-top", `${bar.offsetHeight}px`);
|
||||||
wrap.style.setProperty('--sticky-top', '0px');
|
});
|
||||||
}
|
} else {
|
||||||
|
wrap.style.setProperty("--sticky-top", "0px");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function languesCancelSelection() {
|
function _languesCancelSelection() {
|
||||||
document.querySelectorAll('input[name="selected_langs[]"]').forEach((cb) => {
|
document.querySelectorAll('input[name="selected_langs[]"]').forEach((cb) => {
|
||||||
cb.checked = false;
|
cb.checked = false;
|
||||||
});
|
});
|
||||||
languesUpdateBulk();
|
languesUpdateBulk();
|
||||||
}
|
}
|
||||||
|
|
||||||
function languesConfirmBulkDelete() {
|
function _languesConfirmBulkDelete() {
|
||||||
var checked = document.querySelectorAll('input[name="selected_langs[]"]:checked');
|
var checked = document.querySelectorAll(
|
||||||
if (checked.length < 1) return;
|
'input[name="selected_langs[]"]:checked',
|
||||||
document.getElementById('langues-bulk-delete-count').textContent = checked.length;
|
);
|
||||||
document.getElementById('langues-bulk-delete-dialog').showModal();
|
if (checked.length < 1) return;
|
||||||
|
document.getElementById("langues-bulk-delete-count").textContent =
|
||||||
|
checked.length;
|
||||||
|
document.getElementById("langues-bulk-delete-dialog").showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
function languesExecBulkDelete() {
|
function _languesExecBulkDelete() {
|
||||||
var container = document.getElementById('langues-bulk-checkboxes');
|
var container = document.getElementById("langues-bulk-checkboxes");
|
||||||
container.innerHTML = '';
|
container.innerHTML = "";
|
||||||
document.querySelectorAll('input[name="selected_langs[]"]:checked').forEach((cb) => {
|
document
|
||||||
var inp = document.createElement('input');
|
.querySelectorAll('input[name="selected_langs[]"]:checked')
|
||||||
inp.type = 'hidden';
|
.forEach((cb) => {
|
||||||
inp.name = 'selected_langs[]';
|
var inp = document.createElement("input");
|
||||||
inp.value = cb.value;
|
inp.type = "hidden";
|
||||||
container.appendChild(inp);
|
inp.name = "selected_langs[]";
|
||||||
});
|
inp.value = cb.value;
|
||||||
document.getElementById('langues-bulk-form').querySelector('input[name="action"]').value =
|
container.appendChild(inp);
|
||||||
'delete_bulk';
|
});
|
||||||
document.getElementById('langues-bulk-delete-dialog').close();
|
document
|
||||||
document.getElementById('langues-bulk-form').submit();
|
.getElementById("langues-bulk-form")
|
||||||
|
.querySelector('input[name="action"]').value = "delete_bulk";
|
||||||
|
document.getElementById("langues-bulk-delete-dialog").close();
|
||||||
|
document.getElementById("langues-bulk-form").submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
function languesConfirmBulkMerge() {
|
function _languesConfirmBulkMerge() {
|
||||||
var checked = document.querySelectorAll('input[name="selected_langs[]"]:checked');
|
var checked = document.querySelectorAll(
|
||||||
if (checked.length < 2) return;
|
'input[name="selected_langs[]"]:checked',
|
||||||
document.getElementById('langues-bulk-merge-count').textContent = checked.length;
|
);
|
||||||
var sel = document.getElementById('langues-bulk-merge-target-select');
|
if (checked.length < 2) return;
|
||||||
sel.innerHTML = '<option value="">— Choisir la destination —</option>';
|
document.getElementById("langues-bulk-merge-count").textContent =
|
||||||
checked.forEach((cb) => {
|
checked.length;
|
||||||
var tr = cb.closest('tr');
|
var sel = document.getElementById("langues-bulk-merge-target-select");
|
||||||
sel.innerHTML +=
|
sel.innerHTML = '<option value="">— Choisir la destination —</option>';
|
||||||
'<option value="' +
|
checked.forEach((cb) => {
|
||||||
cb.value +
|
var tr = cb.closest("tr");
|
||||||
'">' +
|
sel.innerHTML +=
|
||||||
tr.querySelector('td:nth-child(2)').textContent.trim() +
|
'<option value="' +
|
||||||
'</option>';
|
cb.value +
|
||||||
});
|
'">' +
|
||||||
document.getElementById('langues-bulk-merge-dialog').showModal();
|
tr.querySelector("td:nth-child(2)").textContent.trim() +
|
||||||
|
"</option>";
|
||||||
|
});
|
||||||
|
document.getElementById("langues-bulk-merge-dialog").showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
function languesExecBulkMerge() {
|
function _languesExecBulkMerge() {
|
||||||
var targetId = document.getElementById('langues-bulk-merge-target-select').value;
|
var targetId = document.getElementById(
|
||||||
if (!targetId) return;
|
"langues-bulk-merge-target-select",
|
||||||
document.getElementById('langues-bulk-target').value = targetId;
|
).value;
|
||||||
var container = document.getElementById('langues-bulk-checkboxes');
|
if (!targetId) return;
|
||||||
container.innerHTML = '';
|
document.getElementById("langues-bulk-target").value = targetId;
|
||||||
document.querySelectorAll('input[name="selected_langs[]"]:checked').forEach((cb) => {
|
var container = document.getElementById("langues-bulk-checkboxes");
|
||||||
var inp = document.createElement('input');
|
container.innerHTML = "";
|
||||||
inp.type = 'hidden';
|
document
|
||||||
inp.name = 'selected_langs[]';
|
.querySelectorAll('input[name="selected_langs[]"]:checked')
|
||||||
inp.value = cb.value;
|
.forEach((cb) => {
|
||||||
container.appendChild(inp);
|
var inp = document.createElement("input");
|
||||||
});
|
inp.type = "hidden";
|
||||||
document.getElementById('langues-bulk-merge-dialog').close();
|
inp.name = "selected_langs[]";
|
||||||
document.getElementById('langues-bulk-form').submit();
|
inp.value = cb.value;
|
||||||
|
container.appendChild(inp);
|
||||||
|
});
|
||||||
|
document.getElementById("langues-bulk-merge-dialog").close();
|
||||||
|
document.getElementById("langues-bulk-form").submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('htmx:afterSwap', (evt) => {
|
document.addEventListener("htmx:afterSwap", (evt) => {
|
||||||
if (evt.target.id === 'langues-table-wrap') {
|
if (evt.target.id === "langues-table-wrap") {
|
||||||
document
|
document
|
||||||
.querySelectorAll('input[name="selected_langs[]"]')
|
.querySelectorAll('input[name="selected_langs[]"]')
|
||||||
.forEach((cb) => {
|
.forEach((cb) => {
|
||||||
cb.addEventListener('change', languesUpdateBulk);
|
cb.addEventListener("change", languesUpdateBulk);
|
||||||
});
|
});
|
||||||
languesUpdateBulk();
|
languesUpdateBulk();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,111 +7,124 @@
|
|||||||
*/
|
*/
|
||||||
var _motsclesPendingForm = null;
|
var _motsclesPendingForm = null;
|
||||||
|
|
||||||
function motsclesConfirmDelete(btn, name) {
|
function _motsclesConfirmDelete(btn, name) {
|
||||||
_motsclesPendingForm = btn.closest('form');
|
_motsclesPendingForm = btn.closest("form");
|
||||||
document.getElementById('motscles-delete-name').textContent = name;
|
document.getElementById("motscles-delete-name").textContent = name;
|
||||||
document.getElementById('motscles-delete-dialog').showModal();
|
document.getElementById("motscles-delete-dialog").showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
function motsclesSubmitPending() {
|
function _motsclesSubmitPending() {
|
||||||
if (_motsclesPendingForm) _motsclesPendingForm.submit();
|
if (_motsclesPendingForm) _motsclesPendingForm.submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
function motsclesToggleAll(src) {
|
function _motsclesToggleAll(src) {
|
||||||
document.querySelectorAll('input[name="selected_tags[]"]').forEach((cb) => {
|
document.querySelectorAll('input[name="selected_tags[]"]').forEach((cb) => {
|
||||||
cb.checked = src.checked;
|
cb.checked = src.checked;
|
||||||
});
|
});
|
||||||
motsclesUpdateBulk();
|
motsclesUpdateBulk();
|
||||||
}
|
}
|
||||||
|
|
||||||
function motsclesUpdateBulk() {
|
function motsclesUpdateBulk() {
|
||||||
var n = document.querySelectorAll('input[name="selected_tags[]"]:checked').length;
|
var n = document.querySelectorAll(
|
||||||
document.getElementById('motscles-selected-count').textContent = n;
|
'input[name="selected_tags[]"]:checked',
|
||||||
var bar = document.getElementById('motscles-bulk-actions');
|
).length;
|
||||||
var wrap = document.getElementById('motscles-table-wrap');
|
document.getElementById("motscles-selected-count").textContent = n;
|
||||||
var visible = n > 1;
|
var bar = document.getElementById("motscles-bulk-actions");
|
||||||
bar.style.display = visible ? 'flex' : 'none';
|
var wrap = document.getElementById("motscles-table-wrap");
|
||||||
if (visible) {
|
var visible = n > 1;
|
||||||
requestAnimationFrame(() => {
|
bar.style.display = visible ? "flex" : "none";
|
||||||
wrap.style.setProperty('--sticky-top', bar.offsetHeight + 'px');
|
if (visible) {
|
||||||
});
|
requestAnimationFrame(() => {
|
||||||
} else {
|
wrap.style.setProperty("--sticky-top", `${bar.offsetHeight}px`);
|
||||||
wrap.style.setProperty('--sticky-top', '0px');
|
});
|
||||||
}
|
} else {
|
||||||
|
wrap.style.setProperty("--sticky-top", "0px");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function motsclesConfirmBulkMerge() {
|
function _motsclesConfirmBulkMerge() {
|
||||||
var checked = document.querySelectorAll('input[name="selected_tags[]"]:checked');
|
var checked = document.querySelectorAll(
|
||||||
if (checked.length < 2) return;
|
'input[name="selected_tags[]"]:checked',
|
||||||
document.getElementById('motscles-bulk-merge-count').textContent = checked.length;
|
);
|
||||||
var sel = document.getElementById('motscles-bulk-merge-target-select');
|
if (checked.length < 2) return;
|
||||||
sel.innerHTML = '<option value="">— Choisir la destination —</option>';
|
document.getElementById("motscles-bulk-merge-count").textContent =
|
||||||
checked.forEach((cb) => {
|
checked.length;
|
||||||
var tr = cb.closest('tr');
|
var sel = document.getElementById("motscles-bulk-merge-target-select");
|
||||||
sel.innerHTML +=
|
sel.innerHTML = '<option value="">— Choisir la destination —</option>';
|
||||||
'<option value="' +
|
checked.forEach((cb) => {
|
||||||
cb.value +
|
var tr = cb.closest("tr");
|
||||||
'">' +
|
sel.innerHTML +=
|
||||||
tr.querySelector('td:nth-child(2)').textContent.trim() +
|
'<option value="' +
|
||||||
'</option>';
|
cb.value +
|
||||||
});
|
'">' +
|
||||||
document.getElementById('motscles-bulk-merge-dialog').showModal();
|
tr.querySelector("td:nth-child(2)").textContent.trim() +
|
||||||
|
"</option>";
|
||||||
|
});
|
||||||
|
document.getElementById("motscles-bulk-merge-dialog").showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
function motsclesExecBulkMerge() {
|
function _motsclesExecBulkMerge() {
|
||||||
var targetId = document.getElementById('motscles-bulk-merge-target-select').value;
|
var targetId = document.getElementById(
|
||||||
if (!targetId) return;
|
"motscles-bulk-merge-target-select",
|
||||||
document.getElementById('motscles-bulk-target').value = targetId;
|
).value;
|
||||||
var container = document.getElementById('motscles-bulk-checkboxes');
|
if (!targetId) return;
|
||||||
container.innerHTML = '';
|
document.getElementById("motscles-bulk-target").value = targetId;
|
||||||
document.querySelectorAll('input[name="selected_tags[]"]:checked').forEach((cb) => {
|
var container = document.getElementById("motscles-bulk-checkboxes");
|
||||||
var inp = document.createElement('input');
|
container.innerHTML = "";
|
||||||
inp.type = 'hidden';
|
document
|
||||||
inp.name = 'selected_tags[]';
|
.querySelectorAll('input[name="selected_tags[]"]:checked')
|
||||||
inp.value = cb.value;
|
.forEach((cb) => {
|
||||||
container.appendChild(inp);
|
var inp = document.createElement("input");
|
||||||
});
|
inp.type = "hidden";
|
||||||
document.getElementById('motscles-bulk-merge-dialog').close();
|
inp.name = "selected_tags[]";
|
||||||
document.getElementById('motscles-bulk-form').submit();
|
inp.value = cb.value;
|
||||||
|
container.appendChild(inp);
|
||||||
|
});
|
||||||
|
document.getElementById("motscles-bulk-merge-dialog").close();
|
||||||
|
document.getElementById("motscles-bulk-form").submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
function motsclesCancelSelection() {
|
function _motsclesCancelSelection() {
|
||||||
document.querySelectorAll('input[name="selected_tags[]"]').forEach((cb) => {
|
document.querySelectorAll('input[name="selected_tags[]"]').forEach((cb) => {
|
||||||
cb.checked = false;
|
cb.checked = false;
|
||||||
});
|
});
|
||||||
motsclesUpdateBulk();
|
motsclesUpdateBulk();
|
||||||
}
|
}
|
||||||
|
|
||||||
function motsclesConfirmBulkDelete() {
|
function _motsclesConfirmBulkDelete() {
|
||||||
var checked = document.querySelectorAll('input[name="selected_tags[]"]:checked');
|
var checked = document.querySelectorAll(
|
||||||
if (checked.length < 1) return;
|
'input[name="selected_tags[]"]:checked',
|
||||||
document.getElementById('motscles-bulk-delete-count').textContent = checked.length;
|
);
|
||||||
document.getElementById('motscles-bulk-delete-dialog').showModal();
|
if (checked.length < 1) return;
|
||||||
|
document.getElementById("motscles-bulk-delete-count").textContent =
|
||||||
|
checked.length;
|
||||||
|
document.getElementById("motscles-bulk-delete-dialog").showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
function motsclesExecBulkDelete() {
|
function _motsclesExecBulkDelete() {
|
||||||
var container = document.getElementById('motscles-bulk-checkboxes');
|
var container = document.getElementById("motscles-bulk-checkboxes");
|
||||||
container.innerHTML = '';
|
container.innerHTML = "";
|
||||||
document.querySelectorAll('input[name="selected_tags[]"]:checked').forEach((cb) => {
|
document
|
||||||
var inp = document.createElement('input');
|
.querySelectorAll('input[name="selected_tags[]"]:checked')
|
||||||
inp.type = 'hidden';
|
.forEach((cb) => {
|
||||||
inp.name = 'selected_tags[]';
|
var inp = document.createElement("input");
|
||||||
inp.value = cb.value;
|
inp.type = "hidden";
|
||||||
container.appendChild(inp);
|
inp.name = "selected_tags[]";
|
||||||
});
|
inp.value = cb.value;
|
||||||
document.getElementById('motscles-bulk-form').querySelector('input[name="action"]').value =
|
container.appendChild(inp);
|
||||||
'delete_bulk';
|
});
|
||||||
document.getElementById('motscles-bulk-delete-dialog').close();
|
document
|
||||||
document.getElementById('motscles-bulk-form').submit();
|
.getElementById("motscles-bulk-form")
|
||||||
|
.querySelector('input[name="action"]').value = "delete_bulk";
|
||||||
|
document.getElementById("motscles-bulk-delete-dialog").close();
|
||||||
|
document.getElementById("motscles-bulk-form").submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('htmx:afterSwap', (evt) => {
|
document.addEventListener("htmx:afterSwap", (evt) => {
|
||||||
if (evt.target.id === 'motscles-table-wrap') {
|
if (evt.target.id === "motscles-table-wrap") {
|
||||||
document
|
document.querySelectorAll('input[name="selected_tags[]"]').forEach((cb) => {
|
||||||
.querySelectorAll('input[name="selected_tags[]"]')
|
cb.addEventListener("change", motsclesUpdateBulk);
|
||||||
.forEach((cb) => {
|
});
|
||||||
cb.addEventListener('change', motsclesUpdateBulk);
|
motsclesUpdateBulk();
|
||||||
});
|
}
|
||||||
motsclesUpdateBulk();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
*
|
*
|
||||||
* Provides: openApproveDialog, openRejectDialog.
|
* Provides: openApproveDialog, openRejectDialog.
|
||||||
*/
|
*/
|
||||||
function openApproveDialog(requestId) {
|
function _openApproveDialog(requestId) {
|
||||||
document.getElementById('approve-request-id').value = requestId;
|
document.getElementById("approve-request-id").value = requestId;
|
||||||
document.getElementById('approve-dialog').showModal();
|
document.getElementById("approve-dialog").showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
function openRejectDialog(requestId) {
|
function _openRejectDialog(requestId) {
|
||||||
document.getElementById('reject-request-id').value = requestId;
|
document.getElementById("reject-request-id").value = requestId;
|
||||||
document.getElementById('reject-dialog').showModal();
|
document.getElementById("reject-dialog").showModal();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,113 +5,118 @@
|
|||||||
* confirmExport, confirmExportFiles, confirmDelete.
|
* confirmExport, confirmExportFiles, confirmDelete.
|
||||||
*/
|
*/
|
||||||
(() => {
|
(() => {
|
||||||
function toggleAll(src) {
|
function toggleAll(src) {
|
||||||
document.querySelectorAll('input[name="selected_theses[]"]').forEach((cb) => {
|
document
|
||||||
cb.checked = src.checked;
|
.querySelectorAll('input[name="selected_theses[]"]')
|
||||||
});
|
.forEach((cb) => {
|
||||||
updateBulk();
|
cb.checked = src.checked;
|
||||||
}
|
});
|
||||||
|
updateBulk();
|
||||||
|
}
|
||||||
|
|
||||||
function updateBulk() {
|
function updateBulk() {
|
||||||
var b = document.getElementById('bulk-actions');
|
var b = document.getElementById("bulk-actions");
|
||||||
var c = document.getElementById('selected-count');
|
var c = document.getElementById("selected-count");
|
||||||
if (!b || !c) return; // only on thesis index page
|
if (!b || !c) return; // only on thesis index page
|
||||||
var n = document.querySelectorAll('input[name="selected_theses[]"]:checked').length;
|
var n = document.querySelectorAll(
|
||||||
c.textContent = n;
|
'input[name="selected_theses[]"]:checked',
|
||||||
b.style.display = n > 0 ? 'flex' : 'none';
|
).length;
|
||||||
document.getElementById('admin-table-wrap').style.setProperty(
|
c.textContent = n;
|
||||||
'--sticky-top',
|
b.style.display = n > 0 ? "flex" : "none";
|
||||||
n > 0 ? b.offsetHeight + 'px' : '0px'
|
document
|
||||||
);
|
.getElementById("admin-table-wrap")
|
||||||
}
|
.style.setProperty("--sticky-top", n > 0 ? `${b.offsetHeight}px` : "0px");
|
||||||
|
}
|
||||||
|
|
||||||
function getSelectedIds() {
|
function getSelectedIds() {
|
||||||
return Array.from(
|
return Array.from(
|
||||||
document.querySelectorAll('input[name="selected_theses[]"]:checked')
|
document.querySelectorAll('input[name="selected_theses[]"]:checked'),
|
||||||
).map((cb) => cb.value);
|
).map((cb) => cb.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function confirmBulk(act) {
|
function confirmBulk(act) {
|
||||||
var noSel = document.getElementById('no-selection-dialog');
|
var noSel = document.getElementById("no-selection-dialog");
|
||||||
if (!noSel) return; // only on thesis index page
|
if (!noSel) return; // only on thesis index page
|
||||||
var ids = getSelectedIds();
|
var ids = getSelectedIds();
|
||||||
if (!ids.length) {
|
if (!ids.length) {
|
||||||
noSel.showModal();
|
noSel.showModal();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var n = ids.length;
|
var n = ids.length;
|
||||||
document.getElementById('bulk-action-input').value = act;
|
document.getElementById("bulk-action-input").value = act;
|
||||||
if (act === 'delete') {
|
if (act === "delete") {
|
||||||
document.getElementById('bulk-delete-count').textContent = n;
|
document.getElementById("bulk-delete-count").textContent = n;
|
||||||
document.getElementById('bulk-delete-dialog').showModal();
|
document.getElementById("bulk-delete-dialog").showModal();
|
||||||
} else {
|
} else {
|
||||||
document.getElementById('bulk-confirm-word').textContent =
|
document.getElementById("bulk-confirm-word").textContent =
|
||||||
act === 'publish' ? 'Publier' : 'Dépublier';
|
act === "publish" ? "Publier" : "Dépublier";
|
||||||
document.getElementById('bulk-confirm-count').textContent = n;
|
document.getElementById("bulk-confirm-count").textContent = n;
|
||||||
document.getElementById('bulk-confirm-dialog').showModal();
|
document.getElementById("bulk-confirm-dialog").showModal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function execBulk() {
|
function execBulk() {
|
||||||
var a = document.getElementById('bulk-action-input').value;
|
var a = document.getElementById("bulk-action-input").value;
|
||||||
var f = document.getElementById('bulk-form');
|
var f = document.getElementById("bulk-form");
|
||||||
f.action = a === 'delete' ? 'actions/delete.php' : 'actions/publish.php';
|
f.action = a === "delete" ? "actions/delete.php" : "actions/publish.php";
|
||||||
var c = document.getElementById('bulk-checkboxes');
|
var c = document.getElementById("bulk-checkboxes");
|
||||||
c.innerHTML = '';
|
c.innerHTML = "";
|
||||||
getSelectedIds().forEach((id) => {
|
getSelectedIds().forEach((id) => {
|
||||||
var inp = document.createElement('input');
|
var inp = document.createElement("input");
|
||||||
inp.type = 'hidden';
|
inp.type = "hidden";
|
||||||
inp.name = 'selected_theses[]';
|
inp.name = "selected_theses[]";
|
||||||
inp.value = id;
|
inp.value = id;
|
||||||
c.appendChild(inp);
|
c.appendChild(inp);
|
||||||
});
|
});
|
||||||
f.submit();
|
f.submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
function confirmExport() {
|
function confirmExport() {
|
||||||
var ids = getSelectedIds();
|
var ids = getSelectedIds();
|
||||||
if (!ids.length) {
|
if (!ids.length) {
|
||||||
document.getElementById('no-selection-dialog').showModal();
|
document.getElementById("no-selection-dialog").showModal();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
window.location.href = '/admin/actions/export.php?csv=1&ids=' + ids.join(',');
|
window.location.href = `/admin/actions/export.php?csv=1&ids=${ids.join(",")}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function confirmExportFiles() {
|
function confirmExportFiles() {
|
||||||
var ids = getSelectedIds();
|
var ids = getSelectedIds();
|
||||||
if (!ids.length) {
|
if (!ids.length) {
|
||||||
document.getElementById('no-selection-dialog').showModal();
|
document.getElementById("no-selection-dialog").showModal();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
window.location.href = '/admin/actions/export.php?files=1&ids=' + ids.join(',');
|
window.location.href = `/admin/actions/export.php?files=1&ids=${ids.join(",")}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function confirmDelete(id, title) {
|
function confirmDelete(id, title) {
|
||||||
var dialog = document.getElementById('delete-thesis-dialog');
|
var dialog = document.getElementById("delete-thesis-dialog");
|
||||||
if (!dialog) return; // only on thesis index page
|
if (!dialog) return; // only on thesis index page
|
||||||
document.getElementById('delete-thesis-title').textContent = title;
|
document.getElementById("delete-thesis-title").textContent = title;
|
||||||
dialog.showModal();
|
dialog.showModal();
|
||||||
document.getElementById('delete-dialog-confirm').onclick = () => {
|
document.getElementById("delete-dialog-confirm").onclick = () => {
|
||||||
document.getElementById('delete-form-' + id).submit();
|
document.getElementById(`delete-form-${id}`).submit();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function reattachListeners() {
|
function reattachListeners() {
|
||||||
document.querySelectorAll('input[name="selected_theses[]"]').forEach((cb) => {
|
document
|
||||||
cb.addEventListener('change', updateBulk);
|
.querySelectorAll('input[name="selected_theses[]"]')
|
||||||
});
|
.forEach((cb) => {
|
||||||
updateBulk();
|
cb.addEventListener("change", updateBulk);
|
||||||
}
|
});
|
||||||
|
updateBulk();
|
||||||
|
}
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', reattachListeners);
|
document.addEventListener("DOMContentLoaded", reattachListeners);
|
||||||
document.addEventListener('htmx:afterSwap', reattachListeners);
|
document.addEventListener("htmx:afterSwap", reattachListeners);
|
||||||
|
|
||||||
// Export to global scope for onclick handlers in HTML
|
// Export to global scope for onclick handlers in HTML
|
||||||
window.toggleAll = toggleAll;
|
window.toggleAll = toggleAll;
|
||||||
window.updateBulk = updateBulk;
|
window.updateBulk = updateBulk;
|
||||||
window.confirmBulk = confirmBulk;
|
window.confirmBulk = confirmBulk;
|
||||||
window.execBulk = execBulk;
|
window.execBulk = execBulk;
|
||||||
window.confirmExport = confirmExport;
|
window.confirmExport = confirmExport;
|
||||||
window.confirmExportFiles = confirmExportFiles;
|
window.confirmExportFiles = confirmExportFiles;
|
||||||
window.confirmDelete = confirmDelete;
|
window.confirmDelete = confirmDelete;
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -10,71 +10,76 @@
|
|||||||
*/
|
*/
|
||||||
var _pendingTagForm = null;
|
var _pendingTagForm = null;
|
||||||
|
|
||||||
function tagsToggleAll(src) {
|
function _tagsToggleAll(src) {
|
||||||
document.querySelectorAll('input[name="selected_tags[]"]').forEach((cb) => {
|
document.querySelectorAll('input[name="selected_tags[]"]').forEach((cb) => {
|
||||||
cb.checked = src.checked;
|
cb.checked = src.checked;
|
||||||
});
|
});
|
||||||
tagsUpdateBulk();
|
tagsUpdateBulk();
|
||||||
}
|
}
|
||||||
|
|
||||||
function tagsUpdateBulk() {
|
function tagsUpdateBulk() {
|
||||||
var n = document.querySelectorAll('input[name="selected_tags[]"]:checked').length;
|
var n = document.querySelectorAll(
|
||||||
document.getElementById('tags-selected-count').textContent = n;
|
'input[name="selected_tags[]"]:checked',
|
||||||
document.getElementById('tags-bulk-actions').style.display = n > 1 ? 'flex' : 'none';
|
).length;
|
||||||
|
document.getElementById("tags-selected-count").textContent = n;
|
||||||
|
document.getElementById("tags-bulk-actions").style.display =
|
||||||
|
n > 1 ? "flex" : "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
function tagsConfirmBulkMerge() {
|
function _tagsConfirmBulkMerge() {
|
||||||
var checked = document.querySelectorAll('input[name="selected_tags[]"]:checked');
|
var checked = document.querySelectorAll(
|
||||||
if (checked.length < 2) return;
|
'input[name="selected_tags[]"]:checked',
|
||||||
document.getElementById('bulk-merge-count').textContent = checked.length;
|
);
|
||||||
var sel = document.getElementById('bulk-merge-target-select');
|
if (checked.length < 2) return;
|
||||||
sel.innerHTML = '<option value="">— Choisir la destination —</option>';
|
document.getElementById("bulk-merge-count").textContent = checked.length;
|
||||||
checked.forEach((cb) => {
|
var sel = document.getElementById("bulk-merge-target-select");
|
||||||
var tr = cb.closest('tr');
|
sel.innerHTML = '<option value="">— Choisir la destination —</option>';
|
||||||
sel.innerHTML +=
|
checked.forEach((cb) => {
|
||||||
'<option value="' +
|
var tr = cb.closest("tr");
|
||||||
cb.value +
|
sel.innerHTML +=
|
||||||
'">' +
|
'<option value="' +
|
||||||
tr.querySelector('.tag-name-cell').textContent.trim() +
|
cb.value +
|
||||||
'</option>';
|
'">' +
|
||||||
});
|
tr.querySelector(".tag-name-cell").textContent.trim() +
|
||||||
document.getElementById('bulk-merge-dialog').showModal();
|
"</option>";
|
||||||
|
});
|
||||||
|
document.getElementById("bulk-merge-dialog").showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
function tagsExecBulkMerge() {
|
function _tagsExecBulkMerge() {
|
||||||
var targetId = document.getElementById('bulk-merge-target-select').value;
|
var targetId = document.getElementById("bulk-merge-target-select").value;
|
||||||
if (!targetId) return;
|
if (!targetId) return;
|
||||||
document.getElementById('tags-bulk-target').value = targetId;
|
document.getElementById("tags-bulk-target").value = targetId;
|
||||||
var container = document.getElementById('tags-bulk-checkboxes');
|
var container = document.getElementById("tags-bulk-checkboxes");
|
||||||
container.innerHTML = '';
|
container.innerHTML = "";
|
||||||
document.querySelectorAll('input[name="selected_tags[]"]:checked').forEach((cb) => {
|
document
|
||||||
var inp = document.createElement('input');
|
.querySelectorAll('input[name="selected_tags[]"]:checked')
|
||||||
inp.type = 'hidden';
|
.forEach((cb) => {
|
||||||
inp.name = 'selected_tags[]';
|
var inp = document.createElement("input");
|
||||||
inp.value = cb.value;
|
inp.type = "hidden";
|
||||||
container.appendChild(inp);
|
inp.name = "selected_tags[]";
|
||||||
});
|
inp.value = cb.value;
|
||||||
document.getElementById('bulk-merge-dialog').close();
|
container.appendChild(inp);
|
||||||
document.getElementById('tags-bulk-form').submit();
|
});
|
||||||
|
document.getElementById("bulk-merge-dialog").close();
|
||||||
|
document.getElementById("tags-bulk-form").submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
function tagsConfirmDelete(btn, name) {
|
function _tagsConfirmDelete(btn, name) {
|
||||||
_pendingTagForm = btn.closest('form');
|
_pendingTagForm = btn.closest("form");
|
||||||
document.getElementById('delete-tag-name').textContent = name;
|
document.getElementById("delete-tag-name").textContent = name;
|
||||||
document.getElementById('delete-tag-dialog').showModal();
|
document.getElementById("delete-tag-dialog").showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
function _submitPendingTagForm() {
|
function _submitPendingTagForm() {
|
||||||
if (_pendingTagForm) _pendingTagForm.submit();
|
if (_pendingTagForm) _pendingTagForm.submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('htmx:afterSwap', (evt) => {
|
document.addEventListener("htmx:afterSwap", (evt) => {
|
||||||
if (evt.target.id === 'tags-table-wrap') {
|
if (evt.target.id === "tags-table-wrap") {
|
||||||
document
|
document.querySelectorAll('input[name="selected_tags[]"]').forEach((cb) => {
|
||||||
.querySelectorAll('input[name="selected_tags[]"]')
|
cb.addEventListener("change", tagsUpdateBulk);
|
||||||
.forEach((cb) => {
|
});
|
||||||
cb.addEventListener('change', tagsUpdateBulk);
|
tagsUpdateBulk();
|
||||||
});
|
}
|
||||||
tagsUpdateBulk();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,108 +10,109 @@
|
|||||||
* Guarded: only runs once.
|
* Guarded: only runs once.
|
||||||
*/
|
*/
|
||||||
(() => {
|
(() => {
|
||||||
if (window.__adminTocBuilt) return;
|
if (window.__adminTocBuilt) return;
|
||||||
window.__adminTocBuilt = true;
|
window.__adminTocBuilt = true;
|
||||||
|
|
||||||
function build() {
|
function build() {
|
||||||
var main = document.getElementById('main-content');
|
var main = document.getElementById("main-content");
|
||||||
var toc = document.getElementById('admin-toc');
|
var toc = document.getElementById("admin-toc");
|
||||||
var list = document.getElementById('admin-toc-list');
|
var list = document.getElementById("admin-toc-list");
|
||||||
if (!main || !toc || !list) return;
|
if (!main || !toc || !list) return;
|
||||||
|
|
||||||
// Guard against double population
|
// Guard against double population
|
||||||
if (list.children.length > 0) return;
|
if (list.children.length > 0) return;
|
||||||
|
|
||||||
var sections = main.querySelectorAll('section[aria-labelledby]');
|
var sections = main.querySelectorAll("section[aria-labelledby]");
|
||||||
if (sections.length < 2) {
|
if (sections.length < 2) {
|
||||||
toc.hidden = true;
|
toc.hidden = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var items = [];
|
var items = [];
|
||||||
sections.forEach((sec) => {
|
sections.forEach((sec) => {
|
||||||
var headingId = sec.getAttribute('aria-labelledby');
|
var headingId = sec.getAttribute("aria-labelledby");
|
||||||
var heading = document.getElementById(headingId);
|
var heading = document.getElementById(headingId);
|
||||||
if (!heading) return;
|
if (!heading) return;
|
||||||
if (!sec.id) sec.id = headingId;
|
if (!sec.id) sec.id = headingId;
|
||||||
|
|
||||||
var a = document.createElement('a');
|
var a = document.createElement("a");
|
||||||
a.href = '#' + sec.id;
|
a.href = `#${sec.id}`;
|
||||||
a.textContent = heading.textContent.trim();
|
a.textContent = heading.textContent.trim();
|
||||||
|
|
||||||
var li = document.createElement('li');
|
var li = document.createElement("li");
|
||||||
li.appendChild(a);
|
li.appendChild(a);
|
||||||
list.appendChild(li);
|
list.appendChild(li);
|
||||||
items.push({ section: sec, link: a });
|
items.push({ section: sec, link: a });
|
||||||
});
|
});
|
||||||
|
|
||||||
// Generate a spread of thresholds for smooth IntersectionObserver firing.
|
// Generate a spread of thresholds for smooth IntersectionObserver firing.
|
||||||
function buildThresholds() {
|
function buildThresholds() {
|
||||||
var t = [];
|
var t = [];
|
||||||
for (var i = 0; i <= 20; i++) t.push(i / 20);
|
for (var i = 0; i <= 20; i++) t.push(i / 20);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
var observer = new IntersectionObserver(
|
var observer = new IntersectionObserver(
|
||||||
() => {
|
() => {
|
||||||
// Active section = whose top is closest to the midpoint of the
|
// Active section = whose top is closest to the midpoint of the
|
||||||
// viewport from above. At page bottom, the last section wins
|
// viewport from above. At page bottom, the last section wins
|
||||||
// even if its heading can't reach 50%.
|
// even if its heading can't reach 50%.
|
||||||
var line = window.innerHeight * 0.5;
|
var line = window.innerHeight * 0.5;
|
||||||
var best = null;
|
var best = null;
|
||||||
var bestDist = Infinity;
|
var bestDist = Infinity;
|
||||||
|
|
||||||
// Pass 1: sections whose top is above/at the line
|
// Pass 1: sections whose top is above/at the line
|
||||||
items.forEach((item) => {
|
items.forEach((item) => {
|
||||||
var top = item.section.getBoundingClientRect().top;
|
var top = item.section.getBoundingClientRect().top;
|
||||||
if (top <= line && (line - top) < bestDist) {
|
if (top <= line && line - top < bestDist) {
|
||||||
bestDist = line - top;
|
bestDist = line - top;
|
||||||
best = item;
|
best = item;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Pass 2: no section above the line — pick closest from below
|
// Pass 2: no section above the line — pick closest from below
|
||||||
if (!best) {
|
if (!best) {
|
||||||
items.forEach((item) => {
|
items.forEach((item) => {
|
||||||
var top = item.section.getBoundingClientRect().top;
|
var top = item.section.getBoundingClientRect().top;
|
||||||
var dist = top - line;
|
var dist = top - line;
|
||||||
if (dist >= 0 && dist < bestDist) {
|
if (dist >= 0 && dist < bestDist) {
|
||||||
bestDist = dist;
|
bestDist = dist;
|
||||||
best = item;
|
best = item;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass 3: at page bottom, if the last section is visible but
|
// Pass 3: at page bottom, if the last section is visible but
|
||||||
// its heading never crossed 50%, promote it anyway.
|
// its heading never crossed 50%, promote it anyway.
|
||||||
if (best) {
|
if (best) {
|
||||||
var lastItem = items[items.length - 1];
|
var lastItem = items[items.length - 1];
|
||||||
if (lastItem !== best) {
|
if (lastItem !== best) {
|
||||||
var lastTop = lastItem.section.getBoundingClientRect().top;
|
var lastTop = lastItem.section.getBoundingClientRect().top;
|
||||||
var atBottom = (window.innerHeight + window.scrollY + 5)
|
var atBottom =
|
||||||
>= document.documentElement.scrollHeight;
|
window.innerHeight + window.scrollY + 5 >=
|
||||||
if (atBottom && lastTop > line && lastTop < window.innerHeight) {
|
document.documentElement.scrollHeight;
|
||||||
best = lastItem;
|
if (atBottom && lastTop > line && lastTop < window.innerHeight) {
|
||||||
}
|
best = lastItem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!best && items.length > 0) best = items[0];
|
if (!best && items.length > 0) best = items[0];
|
||||||
items.forEach((item) => {
|
items.forEach((item) => {
|
||||||
item.link.classList.toggle('toc-active', item === best);
|
item.link.classList.toggle("toc-active", item === best);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
{ threshold: buildThresholds() }
|
{ threshold: buildThresholds() },
|
||||||
);
|
);
|
||||||
|
|
||||||
items.forEach((item) => {
|
items.forEach((item) => {
|
||||||
observer.observe(item.section);
|
observer.observe(item.section);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.readyState === 'loading') {
|
if (document.readyState === "loading") {
|
||||||
document.addEventListener('DOMContentLoaded', build);
|
document.addEventListener("DOMContentLoaded", build);
|
||||||
} else {
|
} else {
|
||||||
build();
|
build();
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -78,5 +78,3 @@ document.body.addEventListener("htmx:beforeRequest", (e) => {
|
|||||||
status.className = "autosave-status autosave-status--saving";
|
status.className = "autosave-status autosave-status--saving";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -172,7 +172,7 @@
|
|||||||
* Name: queue_order[<queueType>] for the pipe-separated order.
|
* Name: queue_order[<queueType>] for the pipe-separated order.
|
||||||
*/
|
*/
|
||||||
function syncOrderInput(queueType, pond) {
|
function syncOrderInput(queueType, pond) {
|
||||||
if (!pond || !pond.element) return;
|
if (!pond?.element) return;
|
||||||
var form = pond.element.closest("form");
|
var form = pond.element.closest("form");
|
||||||
if (!form) return;
|
if (!form) return;
|
||||||
|
|
||||||
@@ -724,7 +724,9 @@
|
|||||||
|
|
||||||
// Find the label for the TFE input (its parent group's <label>)
|
// Find the label for the TFE input (its parent group's <label>)
|
||||||
var fieldGroup = tfeInput.closest(".admin-files-fieldgroup");
|
var fieldGroup = tfeInput.closest(".admin-files-fieldgroup");
|
||||||
var label = fieldGroup ? fieldGroup.querySelector("label[for='tfe-files-input']") : null;
|
var label = fieldGroup
|
||||||
|
? fieldGroup.querySelector("label[for='tfe-files-input']")
|
||||||
|
: null;
|
||||||
|
|
||||||
if (checkedAny) {
|
if (checkedAny) {
|
||||||
tfeInput.removeAttribute("required");
|
tfeInput.removeAttribute("required");
|
||||||
@@ -992,12 +994,12 @@
|
|||||||
? data.error
|
? data.error
|
||||||
: typeof data === "string"
|
: typeof data === "string"
|
||||||
? data
|
? data
|
||||||
: "Erreur " + status;
|
: `Erreur ${status}`;
|
||||||
if (bodyEl)
|
if (bodyEl)
|
||||||
bodyEl.innerHTML = '<p class="file-browser-error">Erreur : ' + msg + '</p>';
|
bodyEl.innerHTML = `<p class="file-browser-error">Erreur : ${msg}</p>`;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log("[pt-relink] success | new_id=" + data.id);
|
console.log(`[pt-relink] success | new_id=${data.id}`);
|
||||||
|
|
||||||
var input = document.querySelector(
|
var input = document.querySelector(
|
||||||
'.tfe-file-picker[data-queue-type="tfe"]',
|
'.tfe-file-picker[data-queue-type="tfe"]',
|
||||||
@@ -1008,8 +1010,7 @@
|
|||||||
var block = document.getElementById("format-fichiers-block");
|
var block = document.getElementById("format-fichiers-block");
|
||||||
if (block && window.htmx) {
|
if (block && window.htmx) {
|
||||||
var url = "/admin/fragments/fichiers.php";
|
var url = "/admin/fragments/fichiers.php";
|
||||||
if (thesisId)
|
if (thesisId) url += `?_thesis_id=${encodeURIComponent(thesisId)}`;
|
||||||
url += "?_thesis_id=" + encodeURIComponent(thesisId);
|
|
||||||
htmx.ajax("GET", url, {
|
htmx.ajax("GET", url, {
|
||||||
target: "#format-fichiers-block",
|
target: "#format-fichiers-block",
|
||||||
swap: "outerHTML",
|
swap: "outerHTML",
|
||||||
@@ -1050,8 +1051,7 @@
|
|||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error("[pt-relink] fetch error", err);
|
console.error("[pt-relink] fetch error", err);
|
||||||
if (bodyEl)
|
if (bodyEl)
|
||||||
bodyEl.innerHTML =
|
bodyEl.innerHTML = '<p class="file-browser-error">Erreur réseau.</p>';
|
||||||
'<p class="file-browser-error">Erreur réseau.</p>';
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -5,22 +5,22 @@
|
|||||||
* receives a single integer (total minutes).
|
* receives a single integer (total minutes).
|
||||||
*/
|
*/
|
||||||
(() => {
|
(() => {
|
||||||
var form = document.querySelector('form.admin-form');
|
var form = document.querySelector("form.admin-form");
|
||||||
if (!form) return;
|
if (!form) return;
|
||||||
|
|
||||||
form.addEventListener('submit', function() {
|
form.addEventListener("submit", () => {
|
||||||
var h = parseInt(document.getElementById('duration_h')?.value, 10) || 0;
|
var h = parseInt(document.getElementById("duration_h")?.value, 10) || 0;
|
||||||
var m = parseInt(document.getElementById('duration_m')?.value, 10) || 0;
|
var m = parseInt(document.getElementById("duration_m")?.value, 10) || 0;
|
||||||
var total = h * 60 + m;
|
var total = h * 60 + m;
|
||||||
|
|
||||||
var hidden = document.getElementById('duration_minutes_hidden');
|
var hidden = document.getElementById("duration_minutes_hidden");
|
||||||
if (!hidden) {
|
if (!hidden) {
|
||||||
hidden = document.createElement('input');
|
hidden = document.createElement("input");
|
||||||
hidden.type = 'hidden';
|
hidden.type = "hidden";
|
||||||
hidden.name = 'duration_minutes';
|
hidden.name = "duration_minutes";
|
||||||
hidden.id = 'duration_minutes_hidden';
|
hidden.id = "duration_minutes_hidden";
|
||||||
form.appendChild(hidden);
|
form.appendChild(hidden);
|
||||||
}
|
}
|
||||||
hidden.value = total > 0 ? String(total) : '';
|
hidden.value = total > 0 ? String(total) : "";
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -5,62 +5,68 @@
|
|||||||
* Reads `data-admin-mode` (0/1) from the jury <fieldset>.
|
* Reads `data-admin-mode` (0/1) from the jury <fieldset>.
|
||||||
*/
|
*/
|
||||||
(() => {
|
(() => {
|
||||||
// ── Dynamic row add/remove ──────────────────────────────────────────────
|
// ── Dynamic row add/remove ──────────────────────────────────────────────
|
||||||
window.addJuryRow = (listId, inputName, roleLabel) => {
|
window.addJuryRow = (listId, inputName, roleLabel) => {
|
||||||
var list = document.getElementById(listId);
|
var list = document.getElementById(listId);
|
||||||
if (!list) return;
|
if (!list) return;
|
||||||
var n = list.querySelectorAll('.admin-jury-entry').length + 1;
|
var n = list.querySelectorAll(".admin-jury-entry").length + 1;
|
||||||
var div = document.createElement('div');
|
var div = document.createElement("div");
|
||||||
div.className = 'admin-jury-entry';
|
div.className = "admin-jury-entry";
|
||||||
div.innerHTML =
|
div.innerHTML =
|
||||||
'<input type="text" name="' +
|
'<input type="text" name="' +
|
||||||
inputName +
|
inputName +
|
||||||
'" placeholder="Nom" autocomplete="off" aria-label="' +
|
'" placeholder="Nom" autocomplete="off" aria-label="' +
|
||||||
roleLabel +
|
roleLabel +
|
||||||
' ' +
|
" " +
|
||||||
n +
|
n +
|
||||||
' \u2014 nom">' +
|
' \u2014 nom">' +
|
||||||
'<button type="button" class="btn btn--sm btn--ghost admin-btn-remove" onclick="removeJuryRow(this)" aria-label="Supprimer">' +
|
'<button type="button" class="btn btn--sm btn--ghost admin-btn-remove" onclick="removeJuryRow(this)" aria-label="Supprimer">' +
|
||||||
'<span aria-hidden="true">\u2715</span></button>';
|
'<span aria-hidden="true">\u2715</span></button>';
|
||||||
list.appendChild(div);
|
list.appendChild(div);
|
||||||
};
|
};
|
||||||
|
|
||||||
window.removeJuryRow = (btn) => {
|
window.removeJuryRow = (btn) => {
|
||||||
var entry = btn.closest('.admin-jury-entry');
|
var entry = btn.closest(".admin-jury-entry");
|
||||||
if (entry) entry.remove();
|
if (entry) entry.remove();
|
||||||
};
|
};
|
||||||
|
|
||||||
// ── ULB toggle ─────────────────────────────────────────────────────────
|
// ── ULB toggle ─────────────────────────────────────────────────────────
|
||||||
var juryFieldset = document.querySelector('fieldset[data-admin-mode]');
|
var juryFieldset = document.querySelector("fieldset[data-admin-mode]");
|
||||||
var adminMode = juryFieldset ? juryFieldset.getAttribute('data-admin-mode') === '1' : false;
|
var adminMode = juryFieldset
|
||||||
|
? juryFieldset.getAttribute("data-admin-mode") === "1"
|
||||||
|
: false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var finalitySelect = document.querySelector('select[name="finality"]');
|
var finalitySelect = document.querySelector('select[name="finality"]');
|
||||||
var ulbRow = document.getElementById('jury-promoteur-ulb-row');
|
var ulbRow = document.getElementById("jury-promoteur-ulb-row");
|
||||||
if (!finalitySelect || !ulbRow) return;
|
if (!finalitySelect || !ulbRow) return;
|
||||||
var ulbAsterisk = document.getElementById('jury-ulb-asterisk');
|
var ulbAsterisk = document.getElementById("jury-ulb-asterisk");
|
||||||
|
|
||||||
function isApprofondiSelected() {
|
function isApprofondiSelected() {
|
||||||
var opt = finalitySelect.options[finalitySelect.selectedIndex];
|
var opt = finalitySelect.options[finalitySelect.selectedIndex];
|
||||||
if (!opt) return false;
|
if (!opt) return false;
|
||||||
return (opt.textContent || opt.text || '').toLowerCase().includes('approfondi');
|
return (opt.textContent || opt.text || "")
|
||||||
}
|
.toLowerCase()
|
||||||
|
.includes("approfondi");
|
||||||
|
}
|
||||||
|
|
||||||
function toggleUlb() {
|
function toggleUlb() {
|
||||||
var show = isApprofondiSelected();
|
var show = isApprofondiSelected();
|
||||||
ulbRow.style.display = show ? '' : 'none';
|
ulbRow.style.display = show ? "" : "none";
|
||||||
if (ulbAsterisk) ulbAsterisk.style.display = show ? '' : 'none';
|
if (ulbAsterisk) ulbAsterisk.style.display = show ? "" : "none";
|
||||||
var inputs = ulbRow.querySelectorAll('input[name="jury_promoteur_ulb_name[]"]');
|
var inputs = ulbRow.querySelectorAll(
|
||||||
inputs.forEach((inp, idx) => {
|
'input[name="jury_promoteur_ulb_name[]"]',
|
||||||
inp.required = adminMode ? false : show && idx === 0;
|
);
|
||||||
inp.disabled = !show;
|
inputs.forEach((inp, idx) => {
|
||||||
if (!show) inp.value = '';
|
inp.required = adminMode ? false : show && idx === 0;
|
||||||
});
|
inp.disabled = !show;
|
||||||
}
|
if (!show) inp.value = "";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
finalitySelect.addEventListener('change', toggleUlb);
|
finalitySelect.addEventListener("change", toggleUlb);
|
||||||
toggleUlb();
|
toggleUlb();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('jury ULB toggle:', e);
|
console.error("jury ULB toggle:", e);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -5,28 +5,28 @@
|
|||||||
* Reads the container id from data-search-container-id on the pill-search div.
|
* Reads the container id from data-search-container-id on the pill-search div.
|
||||||
*/
|
*/
|
||||||
(() => {
|
(() => {
|
||||||
var pillDiv = document.querySelector('[data-search-container-id]');
|
var pillDiv = document.querySelector("[data-search-container-id]");
|
||||||
if (!pillDiv) return;
|
if (!pillDiv) return;
|
||||||
var containerId = pillDiv.getAttribute('data-search-container-id');
|
var containerId = pillDiv.getAttribute("data-search-container-id");
|
||||||
var container = document.getElementById(containerId);
|
var container = document.getElementById(containerId);
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
var pills = container.querySelector('.tag-search-pills');
|
var pills = container.querySelector(".tag-search-pills");
|
||||||
if (!pills) return;
|
if (!pills) return;
|
||||||
|
|
||||||
function check() {
|
function check() {
|
||||||
var asteriskEl = document.getElementById('languages-required-asterisk');
|
var asteriskEl = document.getElementById("languages-required-asterisk");
|
||||||
if (!asteriskEl) return;
|
if (!asteriskEl) return;
|
||||||
var n = pills.querySelectorAll('.tag-pill').length;
|
var n = pills.querySelectorAll(".tag-pill").length;
|
||||||
var checkboxes = document.querySelectorAll(
|
var checkboxes = document.querySelectorAll(
|
||||||
'#languages-fieldset input[type="checkbox"]:checked'
|
'#languages-fieldset input[type="checkbox"]:checked',
|
||||||
);
|
);
|
||||||
asteriskEl.innerHTML =
|
asteriskEl.innerHTML =
|
||||||
n === 0 && checkboxes.length === 0
|
n === 0 && checkboxes.length === 0
|
||||||
? ' <span class="asterisk">*</span>'
|
? ' <span class="asterisk">*</span>'
|
||||||
: '';
|
: "";
|
||||||
}
|
}
|
||||||
|
|
||||||
var observer = new MutationObserver(check);
|
var observer = new MutationObserver(check);
|
||||||
observer.observe(pills, { childList: true });
|
observer.observe(pills, { childList: true });
|
||||||
check();
|
check();
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -8,32 +8,35 @@
|
|||||||
* Loaded on all admin pages via footer.php.
|
* Loaded on all admin pages via footer.php.
|
||||||
*/
|
*/
|
||||||
(() => {
|
(() => {
|
||||||
// Toast accessibility — auto-focus warning toasts
|
// Toast accessibility — auto-focus warning toasts
|
||||||
document.body.addEventListener('htmx:afterSettle', (e) => {
|
document.body.addEventListener("htmx:afterSettle", (e) => {
|
||||||
if (e.target && e.target.id === 'toast-region') {
|
if (e.target && e.target.id === "toast-region") {
|
||||||
var warn = e.target.querySelector('.toast--warning');
|
var warn = e.target.querySelector(".toast--warning");
|
||||||
if (warn) {
|
if (warn) {
|
||||||
warn.setAttribute('tabindex', '-1');
|
warn.setAttribute("tabindex", "-1");
|
||||||
warn.focus();
|
warn.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Markdown cheatsheet: remove stale dialogs before a new one arrives
|
// Markdown cheatsheet: remove stale dialogs before a new one arrives
|
||||||
document.body.addEventListener('htmx:beforeRequest', (e) => {
|
document.body.addEventListener("htmx:beforeRequest", (e) => {
|
||||||
if (
|
if (
|
||||||
e.detail.requestConfig &&
|
e.detail.requestConfig &&
|
||||||
e.detail.requestConfig.path === '/admin/markdown-cheatsheet-fragment.php'
|
e.detail.requestConfig.path === "/admin/markdown-cheatsheet-fragment.php"
|
||||||
) {
|
) {
|
||||||
var old = document.getElementById('md-cheatsheet-dialog');
|
var old = document.getElementById("md-cheatsheet-dialog");
|
||||||
if (old) old.remove();
|
if (old) old.remove();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Markdown cheatsheet: close on backdrop (dialog element) click
|
// Markdown cheatsheet: close on backdrop (dialog element) click
|
||||||
document.body.addEventListener('click', (e) => {
|
document.body.addEventListener("click", (e) => {
|
||||||
if (e.target.tagName === 'DIALOG' && e.target.id === 'md-cheatsheet-dialog') {
|
if (
|
||||||
e.target.close();
|
e.target.tagName === "DIALOG" &&
|
||||||
}
|
e.target.id === "md-cheatsheet-dialog"
|
||||||
});
|
) {
|
||||||
|
e.target.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -5,85 +5,79 @@
|
|||||||
* On desktop, all panels close when crossing the breakpoint.
|
* On desktop, all panels close when crossing the breakpoint.
|
||||||
*/
|
*/
|
||||||
(() => {
|
(() => {
|
||||||
var INDEX_SEL = '#repertoire-index';
|
var INDEX_SEL = "#repertoire-index";
|
||||||
var ACCORDION_SEL = '.rep-accordion';
|
var ACCORDION_SEL = ".rep-accordion";
|
||||||
var TOGGLE_SEL = '.rep-accordion__toggle';
|
var TOGGLE_SEL = ".rep-accordion__toggle";
|
||||||
var PANEL_SEL = '.rep-accordion__panel';
|
var PANEL_SEL = ".rep-accordion__panel";
|
||||||
|
|
||||||
function isMobile() {
|
function isMobile() {
|
||||||
return window.matchMedia('(max-width: 1025px)').matches;
|
return window.matchMedia("(max-width: 1025px)").matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
function initAccordions(root) {
|
function initAccordions(root) {
|
||||||
if (!isMobile()) return;
|
if (!isMobile()) return;
|
||||||
var toggles = root.querySelectorAll(TOGGLE_SEL);
|
var toggles = root.querySelectorAll(TOGGLE_SEL);
|
||||||
toggles.forEach((btn) => {
|
toggles.forEach((btn) => {
|
||||||
// Skip students column — always visible, not an accordion
|
// Skip students column — always visible, not an accordion
|
||||||
if (btn.closest('[data-col="students"]')) return;
|
if (btn.closest('[data-col="students"]')) return;
|
||||||
if (btn._accordionBound) return;
|
if (btn._accordionBound) return;
|
||||||
btn._accordionBound = true;
|
btn._accordionBound = true;
|
||||||
btn.addEventListener('click', () => {
|
btn.addEventListener("click", () => {
|
||||||
var section = btn.closest(ACCORDION_SEL);
|
var section = btn.closest(ACCORDION_SEL);
|
||||||
var panel = section.querySelector(PANEL_SEL);
|
var panel = section.querySelector(PANEL_SEL);
|
||||||
var isOpen = btn.getAttribute('aria-expanded') === 'true';
|
var isOpen = btn.getAttribute("aria-expanded") === "true";
|
||||||
|
|
||||||
// Close all others (except students column)
|
// Close all others (except students column)
|
||||||
root.querySelectorAll(ACCORDION_SEL).forEach((s) => {
|
root.querySelectorAll(ACCORDION_SEL).forEach((s) => {
|
||||||
if (s.dataset.col === 'students') return;
|
if (s.dataset.col === "students") return;
|
||||||
var p = s.querySelector(PANEL_SEL);
|
var p = s.querySelector(PANEL_SEL);
|
||||||
var t = s.querySelector(TOGGLE_SEL);
|
var t = s.querySelector(TOGGLE_SEL);
|
||||||
if (s !== section) {
|
if (s !== section) {
|
||||||
t.setAttribute('aria-expanded', 'false');
|
t.setAttribute("aria-expanded", "false");
|
||||||
p.classList.remove('is-open');
|
p.classList.remove("is-open");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Toggle this one
|
// Toggle this one
|
||||||
var nowOpen = !isOpen;
|
var nowOpen = !isOpen;
|
||||||
btn.setAttribute('aria-expanded', nowOpen ? 'true' : 'false');
|
btn.setAttribute("aria-expanded", nowOpen ? "true" : "false");
|
||||||
if (nowOpen) {
|
if (nowOpen) {
|
||||||
panel.classList.add('is-open');
|
panel.classList.add("is-open");
|
||||||
} else {
|
} else {
|
||||||
panel.classList.remove('is-open');
|
panel.classList.remove("is-open");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initial bind
|
// Initial bind
|
||||||
initAccordions(document);
|
initAccordions(document);
|
||||||
|
|
||||||
// Re-bind after HTMX swaps (use live DOM since e.detail.target may be detached)
|
// Re-bind after HTMX swaps (use live DOM since e.detail.target may be detached)
|
||||||
document.body.addEventListener('htmx:afterSwap', (e) => {
|
document.body.addEventListener("htmx:afterSwap", (e) => {
|
||||||
if (
|
if (e.detail.target?.matches?.(INDEX_SEL)) {
|
||||||
e.detail.target &&
|
var liveIndex = document.querySelector(INDEX_SEL);
|
||||||
e.detail.target.matches &&
|
if (liveIndex) initAccordions(liveIndex);
|
||||||
e.detail.target.matches(INDEX_SEL)
|
}
|
||||||
) {
|
});
|
||||||
var liveIndex = document.querySelector(INDEX_SEL);
|
|
||||||
if (liveIndex) initAccordions(liveIndex);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Re-bind on resize crossing the breakpoint
|
// Re-bind on resize crossing the breakpoint
|
||||||
var wasMobile = isMobile();
|
var wasMobile = isMobile();
|
||||||
window.addEventListener('resize', () => {
|
window.addEventListener("resize", () => {
|
||||||
var nowMobile = isMobile();
|
var nowMobile = isMobile();
|
||||||
if (nowMobile !== wasMobile) {
|
if (nowMobile !== wasMobile) {
|
||||||
wasMobile = nowMobile;
|
wasMobile = nowMobile;
|
||||||
if (!nowMobile) {
|
if (!nowMobile) {
|
||||||
// Switching to desktop — close all panels
|
// Switching to desktop — close all panels
|
||||||
document
|
document
|
||||||
.querySelectorAll(INDEX_SEL + ' ' + TOGGLE_SEL)
|
.querySelectorAll(`${INDEX_SEL} ${TOGGLE_SEL}`)
|
||||||
.forEach((btn) => {
|
.forEach((btn) => {
|
||||||
btn.setAttribute('aria-expanded', 'false');
|
btn.setAttribute("aria-expanded", "false");
|
||||||
});
|
});
|
||||||
document
|
document.querySelectorAll(`${INDEX_SEL} ${PANEL_SEL}`).forEach((p) => {
|
||||||
.querySelectorAll(INDEX_SEL + ' ' + PANEL_SEL)
|
p.classList.remove("is-open");
|
||||||
.forEach((p) => {
|
});
|
||||||
p.classList.remove('is-open');
|
}
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -8,63 +8,55 @@
|
|||||||
* DOM replacement.
|
* DOM replacement.
|
||||||
*/
|
*/
|
||||||
(() => {
|
(() => {
|
||||||
var INDEX_SEL = '#repertoire-index';
|
var INDEX_SEL = "#repertoire-index";
|
||||||
var scrollSnapshots = {};
|
var scrollSnapshots = {};
|
||||||
|
|
||||||
function snapshot() {
|
function snapshot() {
|
||||||
var index = document.querySelector(INDEX_SEL);
|
var index = document.querySelector(INDEX_SEL);
|
||||||
if (!index) return;
|
if (!index) return;
|
||||||
scrollSnapshots = {};
|
scrollSnapshots = {};
|
||||||
index.querySelectorAll('.repertoire-col[data-col] > ul').forEach((ul) => {
|
index.querySelectorAll(".repertoire-col[data-col] > ul").forEach((ul) => {
|
||||||
var col = ul.closest('.repertoire-col');
|
var col = ul.closest(".repertoire-col");
|
||||||
if (!col) return;
|
if (!col) return;
|
||||||
var key = col.getAttribute('data-col');
|
var key = col.getAttribute("data-col");
|
||||||
scrollSnapshots[key] = ul.scrollTop;
|
scrollSnapshots[key] = ul.scrollTop;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function restore() {
|
function restore() {
|
||||||
var index = document.querySelector(INDEX_SEL);
|
var index = document.querySelector(INDEX_SEL);
|
||||||
if (!index) return;
|
if (!index) return;
|
||||||
index.querySelectorAll('.repertoire-col[data-col] > ul').forEach((ul) => {
|
index.querySelectorAll(".repertoire-col[data-col] > ul").forEach((ul) => {
|
||||||
var col = ul.closest('.repertoire-col');
|
var col = ul.closest(".repertoire-col");
|
||||||
if (!col) return;
|
if (!col) return;
|
||||||
var key = col.getAttribute('data-col');
|
var key = col.getAttribute("data-col");
|
||||||
if (scrollSnapshots[key] !== undefined) {
|
if (scrollSnapshots[key] !== undefined) {
|
||||||
ul.scrollTop = scrollSnapshots[key];
|
ul.scrollTop = scrollSnapshots[key];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Capture scroll positions before the outgoing element is replaced
|
// Capture scroll positions before the outgoing element is replaced
|
||||||
document.body.addEventListener('htmx:beforeSwap', (e) => {
|
document.body.addEventListener("htmx:beforeSwap", (e) => {
|
||||||
if (
|
if (e.detail.target?.matches?.(INDEX_SEL)) {
|
||||||
e.detail.target &&
|
snapshot();
|
||||||
e.detail.target.matches &&
|
}
|
||||||
e.detail.target.matches(INDEX_SEL)
|
});
|
||||||
) {
|
|
||||||
snapshot();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Restore after the new content is in the DOM
|
// Restore after the new content is in the DOM
|
||||||
document.body.addEventListener('htmx:afterSwap', (e) => {
|
document.body.addEventListener("htmx:afterSwap", (e) => {
|
||||||
if (
|
if (e.detail.target?.matches?.(INDEX_SEL)) {
|
||||||
e.detail.target &&
|
// Use requestAnimationFrame to ensure layout has settled
|
||||||
e.detail.target.matches &&
|
requestAnimationFrame(() => {
|
||||||
e.detail.target.matches(INDEX_SEL)
|
restore();
|
||||||
) {
|
});
|
||||||
// Use requestAnimationFrame to ensure layout has settled
|
}
|
||||||
requestAnimationFrame(() => {
|
});
|
||||||
restore();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Also restore on history navigation (browser back/forward)
|
// Also restore on history navigation (browser back/forward)
|
||||||
document.body.addEventListener('htmx:historyRestore', () => {
|
document.body.addEventListener("htmx:historyRestore", () => {
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
restore();
|
restore();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -5,53 +5,53 @@
|
|||||||
* with `data-student-name` attribute.
|
* with `data-student-name` attribute.
|
||||||
*/
|
*/
|
||||||
(() => {
|
(() => {
|
||||||
var popover = document.getElementById('student-popover');
|
var popover = document.getElementById("student-popover");
|
||||||
var currentAnchor = null;
|
var currentAnchor = null;
|
||||||
|
|
||||||
function position(anchor) {
|
function position(anchor) {
|
||||||
var r = anchor.getBoundingClientRect();
|
var r = anchor.getBoundingClientRect();
|
||||||
var left = r.right + window.scrollX + 12;
|
var left = r.right + window.scrollX + 12;
|
||||||
var top = r.top + window.scrollY;
|
var top = r.top + window.scrollY;
|
||||||
if (left + 300 > window.innerWidth + window.scrollX) {
|
if (left + 300 > window.innerWidth + window.scrollX) {
|
||||||
left = r.left + window.scrollX - 312;
|
left = r.left + window.scrollX - 312;
|
||||||
}
|
}
|
||||||
popover.style.left = left + 'px';
|
popover.style.left = `${left}px`;
|
||||||
popover.style.top = top + 'px';
|
popover.style.top = `${top}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.body.addEventListener(
|
document.body.addEventListener(
|
||||||
'mouseenter',
|
"mouseenter",
|
||||||
(e) => {
|
(e) => {
|
||||||
var a = e.target.closest('[data-student-name]');
|
var a = e.target.closest("[data-student-name]");
|
||||||
if (!a) return;
|
if (!a) return;
|
||||||
currentAnchor = a;
|
currentAnchor = a;
|
||||||
},
|
},
|
||||||
true
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
document.body.addEventListener('htmx:afterSwap', (e) => {
|
document.body.addEventListener("htmx:afterSwap", (e) => {
|
||||||
if (e.detail.target !== popover) return;
|
if (e.detail.target !== popover) return;
|
||||||
if (currentAnchor) position(currentAnchor);
|
if (currentAnchor) position(currentAnchor);
|
||||||
popover.hidden = false;
|
popover.hidden = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
document.body.addEventListener(
|
document.body.addEventListener(
|
||||||
'mouseleave',
|
"mouseleave",
|
||||||
(e) => {
|
(e) => {
|
||||||
if (
|
if (
|
||||||
!e.target.closest('[data-student-name]') &&
|
!e.target.closest("[data-student-name]") &&
|
||||||
!e.target.closest('#student-popover')
|
!e.target.closest("#student-popover")
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (
|
if (
|
||||||
!document.querySelector('[data-student-name]:hover') &&
|
!document.querySelector("[data-student-name]:hover") &&
|
||||||
!document.querySelector('#student-popover:hover')
|
!document.querySelector("#student-popover:hover")
|
||||||
) {
|
) {
|
||||||
popover.hidden = true;
|
popover.hidden = true;
|
||||||
}
|
}
|
||||||
}, 120);
|
}, 120);
|
||||||
},
|
},
|
||||||
true
|
true,
|
||||||
);
|
);
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -4,42 +4,45 @@
|
|||||||
* Operates on #sidebar-links-form and #sidebar-link-tpl.
|
* Operates on #sidebar-links-form and #sidebar-link-tpl.
|
||||||
*/
|
*/
|
||||||
(() => {
|
(() => {
|
||||||
var form = document.getElementById('sidebar-links-form');
|
var form = document.getElementById("sidebar-links-form");
|
||||||
var tpl = document.getElementById('sidebar-link-tpl');
|
var tpl = document.getElementById("sidebar-link-tpl");
|
||||||
if (!form || !tpl) return;
|
if (!form || !tpl) return;
|
||||||
var tplHtml = tpl.innerHTML;
|
var tplHtml = tpl.innerHTML;
|
||||||
|
|
||||||
function reindexLinks() {
|
function reindexLinks() {
|
||||||
var rows = form.querySelectorAll('.sidebar-link-row');
|
var rows = form.querySelectorAll(".sidebar-link-row");
|
||||||
rows.forEach((row, i) => {
|
rows.forEach((row, i) => {
|
||||||
row.querySelectorAll('input').forEach((inp) => {
|
row.querySelectorAll("input").forEach((inp) => {
|
||||||
if (inp.name) {
|
if (inp.name) {
|
||||||
inp.name = inp.name.replace(/links\[\d+\]/, 'links[' + i + ']');
|
inp.name = inp.name.replace(/links\[\d+\]/, `links[${i}]`);
|
||||||
}
|
}
|
||||||
if (inp.id) {
|
if (inp.id) {
|
||||||
inp.id = inp.id.replace(/sl_\d+/, 'sl_' + i);
|
inp.id = inp.id.replace(/sl_\d+/, `sl_${i}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
row.querySelectorAll('label[for]').forEach((lbl) => {
|
row.querySelectorAll("label[for]").forEach((lbl) => {
|
||||||
lbl.setAttribute('for', lbl.getAttribute('for').replace(/sl_\d+/, 'sl_' + i));
|
lbl.setAttribute(
|
||||||
});
|
"for",
|
||||||
});
|
lbl.getAttribute("for").replace(/sl_\d+/, `sl_${i}`),
|
||||||
}
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Event delegation for remove buttons
|
// Event delegation for remove buttons
|
||||||
form.addEventListener('click', (e) => {
|
form.addEventListener("click", (e) => {
|
||||||
if (!e.target.closest('.remove-sidebar-link-btn')) return;
|
if (!e.target.closest(".remove-sidebar-link-btn")) return;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.target.closest('.sidebar-link-row').remove();
|
e.target.closest(".sidebar-link-row").remove();
|
||||||
reindexLinks();
|
reindexLinks();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add button
|
// Add button
|
||||||
var addBtn = document.getElementById('add-sidebar-link-btn');
|
var addBtn = document.getElementById("add-sidebar-link-btn");
|
||||||
addBtn.addEventListener('click', function () {
|
addBtn.addEventListener("click", function () {
|
||||||
var rows = form.querySelectorAll('.sidebar-link-row');
|
var rows = form.querySelectorAll(".sidebar-link-row");
|
||||||
var idx = rows.length;
|
var idx = rows.length;
|
||||||
var html = tplHtml.split('{{li}}').join(idx);
|
var html = tplHtml.split("{{li}}").join(idx);
|
||||||
this.insertAdjacentHTML('beforebegin', html);
|
this.insertAdjacentHTML("beforebegin", html);
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -3,11 +3,11 @@
|
|||||||
* error. Reads the field id from data-smtp-error-field on the SMTP form.
|
* error. Reads the field id from data-smtp-error-field on the SMTP form.
|
||||||
*/
|
*/
|
||||||
(() => {
|
(() => {
|
||||||
var form = document.querySelector('form[data-smtp-error-field]');
|
var form = document.querySelector("form[data-smtp-error-field]");
|
||||||
if (!form) return;
|
if (!form) return;
|
||||||
var fieldId = form.getAttribute('data-smtp-error-field');
|
var fieldId = form.getAttribute("data-smtp-error-field");
|
||||||
var el = fieldId ? document.getElementById(fieldId) : null;
|
var el = fieldId ? document.getElementById(fieldId) : null;
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
el.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
el.scrollIntoView({ behavior: "smooth", block: "center" });
|
||||||
el.focus();
|
el.focus();
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -47,9 +47,6 @@ class FormBootstrap
|
|||||||
if (is_array($formData[$key])) {
|
if (is_array($formData[$key])) {
|
||||||
return $formData[$key];
|
return $formData[$key];
|
||||||
}
|
}
|
||||||
if ($formData[$key] === null) {
|
|
||||||
return $default;
|
|
||||||
}
|
|
||||||
return htmlspecialchars((string)$formData[$key]);
|
return htmlspecialchars((string)$formData[$key]);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -24,7 +24,13 @@
|
|||||||
"linter": {
|
"linter": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"rules": {
|
"rules": {
|
||||||
"recommended": true
|
"recommended": true,
|
||||||
|
"style": {
|
||||||
|
"noDescendingSpecificity": "off"
|
||||||
|
},
|
||||||
|
"correctness": {
|
||||||
|
"noInnerDeclarations": "off"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"formatter": {
|
"formatter": {
|
||||||
|
|||||||
@@ -470,7 +470,7 @@ lint:
|
|||||||
[group('test')]
|
[group('test')]
|
||||||
fix:
|
fix:
|
||||||
# Auto-fix: biome (JS/CSS formatting + lint) + php-cs-fixer (PHP coding standards)
|
# Auto-fix: biome (JS/CSS formatting + lint) + php-cs-fixer (PHP coding standards)
|
||||||
@npx biome check --write app/public/assets/css/ app/public/assets/js/app/ scripts/
|
@npx biome check --write --unsafe app/public/assets/css/ app/public/assets/js/app/ scripts/
|
||||||
@vendor/bin/php-cs-fixer fix --no-interaction
|
@vendor/bin/php-cs-fixer fix --no-interaction
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|||||||
@@ -6,6 +6,18 @@ parameters:
|
|||||||
count: 1
|
count: 1
|
||||||
path: app/src/Controllers/SearchController.php
|
path: app/src/Controllers/SearchController.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: '#^Offset ''duration_minutes'' on array\{\}\|array\{license_id\: int\|null, access_type_id\: int\|null, context_note\: string, contact_visible\: int\|null\} on left side of \?\? does not exist\.$#'
|
||||||
|
identifier: nullCoalesce.offset
|
||||||
|
count: 1
|
||||||
|
path: app/src/Controllers/ThesisEditController.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: '#^Offset ''duration_pages'' on array\{\}\|array\{license_id\: int\|null, access_type_id\: int\|null, context_note\: string, contact_visible\: int\|null\} on left side of \?\? does not exist\.$#'
|
||||||
|
identifier: nullCoalesce.offset
|
||||||
|
count: 1
|
||||||
|
path: app/src/Controllers/ThesisEditController.php
|
||||||
|
|
||||||
-
|
-
|
||||||
message: '#^Property Dispatcher\:\:\$queryParams is never read, only written\.$#'
|
message: '#^Property Dispatcher\:\:\$queryParams is never read, only written\.$#'
|
||||||
identifier: property.onlyWritten
|
identifier: property.onlyWritten
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build CSS bundles with Lightning CSS.
|
* Build CSS bundles with Lightning CSS.
|
||||||
*
|
*
|
||||||
@@ -13,10 +14,10 @@
|
|||||||
* Output: app/public/assets/dist/
|
* Output: app/public/assets/dist/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { bundleAsync } from "lightningcss";
|
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
||||||
import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
import { dirname, resolve } from "node:path";
|
||||||
import { resolve, dirname, basename } from "node:path";
|
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
|
import { bundleAsync } from "lightningcss";
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
const root = resolve(__dirname, "..");
|
const root = resolve(__dirname, "..");
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build JS bundles: one self-contained file per entry point.
|
* Build JS bundles: one self-contained file per entry point.
|
||||||
*
|
*
|
||||||
@@ -6,10 +7,10 @@
|
|||||||
* Output: app/public/assets/dist/{admin,public,form,partage}.min.js
|
* Output: app/public/assets/dist/{admin,public,form,partage}.min.js
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { rolldown } from "rolldown";
|
import { mkdirSync, writeFileSync } from "node:fs";
|
||||||
import { resolve, dirname } from "node:path";
|
import { dirname, resolve } from "node:path";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
import { writeFileSync, mkdirSync } from "node:fs";
|
import { rolldown } from "rolldown";
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
const root = resolve(__dirname, "..");
|
const root = resolve(__dirname, "..");
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
import { execSync } from "node:child_process";
|
import { execSync } from "node:child_process";
|
||||||
import { existsSync } from "node:fs";
|
import { existsSync } from "node:fs";
|
||||||
import { resolve, dirname } from "node:path";
|
import { dirname, resolve } from "node:path";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
* Staleness: any source file newer than the oldest dist file.
|
* Staleness: any source file newer than the oldest dist file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { statSync, existsSync, readdirSync } from "node:fs";
|
import { existsSync, readdirSync, statSync } from "node:fs";
|
||||||
import { resolve, dirname } from "node:path";
|
import { dirname, resolve } from "node:path";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
|
|||||||
Reference in New Issue
Block a user