diff --git a/app/helpers/theme.php b/app/helpers/theme.php
index 81a7f8e..55a420a 100644
--- a/app/helpers/theme.php
+++ b/app/helpers/theme.php
@@ -284,6 +284,115 @@ EOT;
}
+ /**
+ * Get descriptive metadata for a theme.
+ *
+ * @param string $themeId
+ * @return array{name:string,description:string,version:string,author:string,tags:array}
+ */
+ public static function getThemeMetadata(string $themeId): array
+ {
+ static $cache = [];
+ if (isset($cache[$themeId])) {
+ return $cache[$themeId];
+ }
+
+ $config = self::getConfig();
+ $defaults = $config['default_config'] ?? [];
+ $availableEntry = $config['available_themes'][$themeId] ?? null;
+
+ $metadata = [
+ 'name' => is_array($availableEntry) ? ($availableEntry['name'] ?? ucfirst($themeId)) : ($availableEntry ?? ucfirst($themeId)),
+ 'description' => $defaults['description'] ?? '',
+ 'version' => $defaults['version'] ?? '',
+ 'author' => $defaults['author'] ?? '',
+ 'tags' => [],
+ 'type' => $themeId === 'default' ? 'Core built-in' : 'Custom',
+ 'path' => $themeId === 'default' ? 'app/templates' : ('themes/' . $themeId),
+ 'last_modified' => null,
+ 'file_count' => null
+ ];
+
+ if (is_array($availableEntry)) {
+ $metadata = array_merge($metadata, array_intersect_key($availableEntry, array_flip(['name', 'description', 'version', 'author', 'tags'])));
+ }
+
+ if ($themeId !== 'default') {
+ $themesDir = rtrim($config['paths']['themes'] ?? (__DIR__ . '/../../themes'), '/');
+ $themeConfigPath = $themesDir . '/' . $themeId . '/config.php';
+ if (file_exists($themeConfigPath)) {
+ $themeConfig = require $themeConfigPath;
+ if (is_array($themeConfig)) {
+ $metadata = array_merge($metadata, array_intersect_key($themeConfig, array_flip(['name', 'description', 'version', 'author', 'tags'])));
+ }
+ }
+ }
+
+ if (empty($metadata['description'])) {
+ $metadata['description'] = $defaults['description'] ?? 'A Jilo Web theme';
+ }
+ if (empty($metadata['version'])) {
+ $metadata['version'] = $defaults['version'] ?? '1.0.0';
+ }
+ if (empty($metadata['author'])) {
+ $metadata['author'] = $defaults['author'] ?? 'Lindeas';
+ }
+
+ if (empty($metadata['tags']) || !is_array($metadata['tags'])) {
+ $metadata['tags'] = [];
+ }
+
+ $paths = $config['paths'] ?? [];
+ if ($themeId === 'default') {
+ $absolutePath = realpath($paths['templates'] ?? (__DIR__ . '/../templates')) ?: null;
+ } else {
+ $absolutePath = self::getThemePath($themeId);
+ }
+
+ if ($absolutePath && is_dir($absolutePath)) {
+ [$lastModified, $fileCount] = self::getDirectoryStats($absolutePath);
+ if ($lastModified !== null) {
+ $metadata['last_modified'] = $lastModified;
+ }
+ if ($fileCount > 0) {
+ $metadata['file_count'] = $fileCount;
+ }
+ }
+
+ return $cache[$themeId] = $metadata;
+ }
+
+
+ /**
+ * Calculate directory statistics for a theme folder.
+ */
+ private static function getDirectoryStats(string $path): array
+ {
+ $latest = null;
+ $count = 0;
+
+ try {
+ $iterator = new \RecursiveIteratorIterator(
+ new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS)
+ );
+ foreach ($iterator as $fileInfo) {
+ if (!$fileInfo->isFile()) {
+ continue;
+ }
+ $count++;
+ $mtime = $fileInfo->getMTime();
+ if ($latest === null || $mtime > $latest) {
+ $latest = $mtime;
+ }
+ }
+ } catch (\Throwable $e) {
+ return [null, 0];
+ }
+
+ return [$latest, $count];
+ }
+
+
/**
* Get the URL for a theme asset
*
diff --git a/app/pages/theme.php b/app/pages/theme.php
index 7c35794..4b741d1 100644
--- a/app/pages/theme.php
+++ b/app/pages/theme.php
@@ -51,11 +51,20 @@ if (isset($_GET['switch_to'])) {
$themes = \App\Helpers\Theme::getAvailableThemes();
$currentTheme = \App\Helpers\Theme::getCurrentThemeName();
-// Prepare theme data with screenshot URLs for the view
+// Prepare theme data with screenshot URLs and metadata for the view
$themeData = [];
foreach ($themes as $id => $name) {
+ $meta = \App\Helpers\Theme::getThemeMetadata($id);
$themeData[$id] = [
- 'name' => $name,
+ 'name' => $meta['name'] ?? $name,
+ 'description' => $meta['description'] ?? '',
+ 'version' => $meta['version'] ?? '',
+ 'author' => $meta['author'] ?? '',
+ 'tags' => $meta['tags'] ?? [],
+ 'type' => $meta['type'] ?? '',
+ 'path' => $meta['path'] ?? '',
+ 'last_modified' => $meta['last_modified'] ?? null,
+ 'file_count' => $meta['file_count'] ?? null,
'screenshotUrl' => \App\Helpers\Theme::getAssetUrl($id, 'screenshot.png'),
'isActive' => $id === $currentTheme
];
diff --git a/app/templates/theme.php b/app/templates/theme.php
index 068f584..39825d2 100644
--- a/app/templates/theme.php
+++ b/app/templates/theme.php
@@ -10,35 +10,124 @@
* - isActive: Whether this is the current theme
*/
?>
-
-
Theme switcher
-
Select a theme to change the appearance of the application.
-
- $theme): ?>
-
-
-
-
-
-
No preview available
-
-
-
-
-
-
-
= htmlspecialchars($theme['name']) ?>
-
Theme ID: = htmlspecialchars($themeId) ?>
-
-
-
-
-
-
+
+
+
+
+
+
+
+
Themes
+
Personalize = htmlspecialchars($config['site_name']); ?> with custom visual styles.
+
+
+
+ = $totalThemes ?> available
+
+
+
+ Active: = htmlspecialchars($activeThemeName) ?>
+
+
+
+
+
+
+
+
+ $theme):
+ $isActive = !empty($theme['isActive']);
+ $screenshot = $theme['screenshotUrl'];
+?>
+
+
+
+ No preview available
+
+
+
+
+
ID: = htmlspecialchars($themeId) ?>
+
= htmlspecialchars($theme['name']) ?>
+
+
+
+ = htmlspecialchars($theme['description']) ?>
+
+
+
+
+
+
- Version
+ - = htmlspecialchars($theme['version']) ?>
+
+
+
+
+
- Author
+ - = htmlspecialchars($theme['author']) ?>
+
+
+
+
+
+
+
+
+
+
- Type
+ - = htmlspecialchars($theme['type']) ?>
+
+
+
+
+
- Files
+ - = number_format((int)$theme['file_count']) ?>
+
+
+
+
+
- Location
+ = htmlspecialchars($theme['path']) ?>
+
+
+
+
+
- Last edit
+ - = htmlspecialchars($lastEdited) ?>
+
+
+
+
+
+
+
+
+
+
diff --git a/public_html/static/css/main.css b/public_html/static/css/main.css
index 6575b13..ff15454 100644
--- a/public_html/static/css/main.css
+++ b/public_html/static/css/main.css
@@ -1,3 +1,210 @@
+.tm-theme-gallery {
+ padding: 2rem 0;
+}
+
+.tm-theme-header {
+ display: flex;
+ align-items: flex-end;
+ justify-content: space-between;
+ gap: 1.5rem;
+ margin-bottom: 2rem;
+ flex-wrap: wrap;
+}
+
+.tm-theme-eyebrow {
+ text-transform: uppercase;
+ letter-spacing: 0.2em;
+ font-size: 0.75rem;
+ color: #94a3b8;
+ margin-bottom: 0.4rem;
+}
+
+.tm-theme-title {
+ margin: 0;
+ font-size: 2rem;
+ font-weight: 600;
+ color: #0f172a;
+}
+
+.tm-theme-subtitle {
+ margin: 0.5rem 0 0;
+ color: #475569;
+ max-width: 520px;
+}
+
+.tm-theme-current {
+ background: rgba(15, 23, 42, 0.03);
+ border: 1px solid rgba(148, 163, 184, 0.3);
+ border-radius: 1rem;
+ padding: 1rem 1.5rem;
+ display: inline-flex;
+ flex-direction: column;
+ min-width: 220px;
+}
+
+.tm-theme-current-label {
+ text-transform: uppercase;
+ letter-spacing: 0.21em;
+ font-size: 0.7rem;
+ color: #94a3b8;
+ margin-bottom: 0.35rem;
+}
+
+.tm-theme-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
+ gap: 1.5rem;
+}
+
+.tm-theme-card {
+ background: rgba(255, 255, 255, 0.98);
+ border-radius: 0.5rem;
+ border: 1px solid rgba(148, 163, 184, 0.2);
+ box-shadow: 0 25px 45px rgba(15, 23, 42, 0.06);
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+}
+
+.tm-theme-card.is-active {
+ border-color: rgba(37, 99, 235, 0.5);
+ box-shadow: 0 35px 60px rgba(37, 99, 235, 0.15);
+}
+
+.tm-theme-preview {
+ position: relative;
+ padding-top: 58%;
+ background-color: rgba(148, 163, 184, 0.15);
+ background-size: cover;
+ background-position: center;
+}
+
+.tm-theme-preview span {
+ position: absolute;
+ inset: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: #64748b;
+ font-size: 0.95rem;
+}
+
+.tm-theme-body {
+ padding: 1.5rem;
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+}
+
+.tm-theme-heading {
+ display: flex;
+ flex-direction: column;
+ gap: 0.25rem;
+}
+
+.tm-theme-id {
+ margin: 0 0 0.25rem;
+ font-size: 0.85rem;
+ color: #94a3b8;
+}
+
+.tm-theme-name {
+ margin: 0;
+ font-size: 1.25rem;
+ color: #0f172a;
+}
+
+.tm-theme-description {
+ margin: 0;
+ color: #475569;
+ font-size: 0.95rem;
+ line-height: 1.5;
+}
+
+.tm-theme-meta {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 1rem;
+ margin: 0;
+ padding: 0;
+}
+
+.tm-theme-meta-item {
+ display: flex;
+ flex-direction: column;
+ gap: 0.2rem;
+}
+
+.tm-theme-meta-item dt {
+ margin: 0;
+ font-size: 0.75rem;
+ text-transform: uppercase;
+ letter-spacing: 0.2em;
+ color: #94a3b8;
+}
+
+.tm-theme-meta-item dd {
+ margin: 0;
+ font-weight: 600;
+ color: #0f172a;
+}
+
+.tm-theme-tags {
+ list-style: none;
+ padding: 0;
+ margin: -0.25rem 0 0.25rem;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.5rem;
+}
+
+.tm-theme-tags li {
+ background: rgba(37, 99, 235, 0.08);
+ color: #1d4ed8;
+ font-size: 0.8rem;
+ padding: 0.25rem 0.65rem;
+ border-radius: 999px;
+}
+
+.tm-theme-stats {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
+ gap: 0.25rem;
+/* margin: 0.25rem 0 0;*/
+ margin: 0;
+ padding: 0;
+}
+
+.tm-theme-stat {
+ background: rgba(15, 23, 42, 0.03);
+ border: 1px solid rgba(148, 163, 184, 0.25);
+ border-radius: 0.5rem;
+/* padding: 0.75rem 1rem;*/
+ padding: 0.3rem;
+ display: flex;
+ flex-direction: column;
+/* gap: 0.2rem;*/
+}
+
+.tm-theme-stat dt {
+ margin: 0;
+ font-size: 0.7rem;
+ letter-spacing: 0.2em;
+ text-transform: uppercase;
+ color: #94a3b8;
+}
+
+.tm-theme-stat dd {
+ margin: 0;
+ font-weight: 600;
+ color: #0f172a;
+ font-size: 0.7rem;
+ text-transform: uppercase;
+}
+
+.tm-theme-actions .btn {
+ width: 100%;
+}
html, body {
width: 100%;
min-height: 100%;
@@ -86,6 +293,46 @@ html, body {
margin-top: 0.75rem;
}
+.tm-hero-controls {
+ display: inline-flex;
+ gap: 0.5rem;
+ margin-top: 0.85rem;
+ background: rgba(148, 163, 184, 0.15);
+ padding: 0.25rem;
+ border-radius: 999px;
+ align-self: flex-start;
+}
+
+.tm-toggle-pill {
+ border: none;
+ background: transparent;
+ color: #475569;
+ font-size: 0.9rem;
+ font-weight: 500;
+ padding: 0.4rem 1.05rem;
+ border-radius: 999px;
+ display: inline-flex;
+ align-items: center;
+ gap: 0.35rem;
+ cursor: pointer;
+ transition: background 0.2s ease, color 0.2s ease, box-shadow 0.2s ease;
+}
+
+.tm-toggle-pill i {
+ font-size: 0.85rem;
+}
+
+.tm-toggle-pill:is(:hover, :focus-visible) {
+ background: rgba(255, 255, 255, 0.7);
+ color: #0f172a;
+}
+
+.tm-toggle-pill.is-active {
+ background: #1d4ed8;
+ color: #fff;
+ box-shadow: 0 10px 25px rgba(30, 64, 175, 0.25);
+}
+
.tm-hero-pill {
display: inline-flex;
align-items: center;
@@ -504,18 +751,40 @@ html, body {
/* Dashboard widgets */
.tm-widget-card {
background: rgba(255, 255, 255, 0.97);
- border-radius: 1.25rem;
+ border-radius: 1rem;
box-shadow: 0 20px 45px rgba(15, 23, 42, 0.08);
- padding: 1.75rem;
+/* padding: 1.75rem;*/
margin-bottom: 1.75rem;
+ overflow: hidden;
}
.tm-widget-header {
display: flex;
- justify-content: space-between;
- align-items: flex-start;
- gap: 1rem;
- margin-bottom: 1rem;
+ align-items: center;
+/* gap: 0.85rem;*/
+ background: linear-gradient(135deg, #eef2ff 0%, #e0f2fe 100%);
+/* border-radius: 1rem;*/
+ padding: 0.25rem;
+/* margin: -0.25rem -0.25rem 1.25rem;*/
+ margin: -0.25rem -0.25rem 0rem;
+}
+
+.tm-widget-heading {
+ display: flex;
+ align-items: center;
+/* gap: 0.75rem;*/
+}
+
+.tm-widget-title-icon {
+ width: 48px;
+ height: 48px;
+ border-radius: 16px;
+/* background: rgba(15, 23, 42, 0.08);*/
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ color: #0f172a;
+ font-size: 1.25rem;
}
.tm-widget-eyebrow {
@@ -531,13 +800,18 @@ html, body {
border: none;
padding: 0;
margin: 0;
- font-size: 1.35rem;
+/* font-size: 1.35rem;*/
+ font-size: 1rem;
font-weight: 600;
color: #0f172a;
- display: flex;
- align-items: center;
- gap: 0.5rem;
- cursor: pointer;
+ display: inline-flex;
+ align-items: baseline;
+/* gap: 0.4rem;*/
+ cursor: default;
+}
+
+.tm-widget-title a {
+ text-decoration: none;
}
.tm-widget-title:focus {
@@ -583,7 +857,9 @@ html, body {
.tm-widget-body {
border-top: 1px solid rgba(148, 163, 184, 0.2);
- padding-top: 1rem;
+/* padding-top: 1rem;*/
+ padding: 1rem;
+/* margin-top: 0.75rem;*/
}
.tm-widget-table thead {
@@ -848,6 +1124,7 @@ html, body {
border: 1px solid rgba(148, 163, 184, 0.5);
border-radius: 0.85rem;
padding: 0.55rem 0.85rem;
+ height: 100%;
}
.tm-filter-input input {
@@ -872,9 +1149,51 @@ html, body {
gap: 1rem;
flex-wrap: nowrap;
width: 100%;
+ height: 2.25rem;
/* margin-bottom: 1rem;*/
}
+/*.tm-call-filter-row--compact {*/
+/* align-items: center;*/
+/* gap: 0.65rem;*/
+/* height: auto;*/
+/*}*/
+
+.tm-call-filter-row--compact .tm-filter-field {
+ flex: 0 0 auto;
+}
+
+.tm-call-filter-row--compact .tm-filter-input {
+ width: auto;
+ padding: 0.4rem 0.85rem;
+ white-space: nowrap;
+}
+
+.tm-call-filter-row--compact .tm-filter-input select,
+.tm-call-filter-row--compact .tm-filter-input input[type="date"] {
+ width: auto;
+ min-width: 0;
+ flex: 0 0 auto;
+}
+
+.tm-call-filter-row--compact .tm-filter-input--tagged {
+ padding: 0.35rem 0.6rem;
+}
+
+.tm-call-filter-row--compact .tm-filter-input--tagged input[type="date"] {
+ width: auto;
+ text-transform: uppercase;
+ font-weight: lighter;
+ font-variant: all-small-caps;
+}
+
+.tm-call-filter-actions--compact {
+ margin-left: auto;
+ display: inline-flex;
+ gap: 0.6rem;
+ align-items: center;
+}
+
.tm-call-filter-row:last-of-type {
margin-bottom: 0;
}
@@ -884,6 +1203,11 @@ html, body {
min-width: 0;
}
+.tm-call-filter-row.tm-call-filter-row--compact .tm-filter-field {
+ flex: 0 0 auto;
+ min-width: auto;
+}
+
@media (max-width: 768px) {
.tm-call-filter-row {
flex-wrap: wrap;
@@ -902,7 +1226,8 @@ html, body {
display: inline-flex;
align-items: center;
padding: 0.2rem 0.6rem;
- border-radius: 999px;
+/* border-radius: 999px;*/
+ border-radius: 10px;
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.08em;
@@ -913,18 +1238,52 @@ html, body {
.tm-directory-filter-form .form-select,
.tm-directory-filter-form select {
width: 100%;
+ background: transparent;
+ border: none;
}
.tm-directory-filter-form .select2-container {
width: 100% !important;
}
+.tm-directory-filter-form .form-select:focus,
+.tm-directory-filter-form select:focus,
+.tm-directory-filter-form .select2-selection:focus,
+.tm-directory-filter-form .select2-selection--single:focus,
+.tm-directory-filter-form .select2-selection--multiple:focus {
+ outline: none;
+ box-shadow: none;
+}
+
+.tm-directory-filter-form .select2-selection,
+.tm-directory-filter-form .select2-container--default .select2-selection--single,
+.tm-directory-filter-form .select2-container--default .select2-selection--multiple {
+ background-color: transparent !important;
+ border: none !important;
+ min-height: auto;
+ padding-left: 0;
+ box-shadow: none;
+}
+
+.tm-directory-filter-form .select2-selection__rendered {
+ padding-left: 0;
+ color: inherit;
+}
+
+.tm-directory-filter-form .select2-selection__choice {
+ background: rgba(37, 99, 235, 0.08);
+ border: none;
+ color: #1d4ed8;
+}
+
.tm-filter-actions {
display: flex;
gap: 0.75rem;
flex-wrap: wrap;
}
+
+
.tm-directory-meta {
display: flex;
align-items: center;
@@ -1036,6 +1395,7 @@ html, body {
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 0.3rem 0.65rem;
align-items: center;
+ position: relative;
}
.tm-directory-field {
@@ -1057,6 +1417,227 @@ html, body {
color: #94a3b8;
}
+.tm-directory-match-flag {
+ position: absolute;
+ top: 0.4rem;
+ right: 0.4rem;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 28px;
+ height: 28px;
+ border-radius: 50%;
+ background: rgba(37, 99, 235, 0.12);
+ color: #1d4ed8;
+ font-size: 0.75rem;
+}
+
+.tm-notification-list {
+ display: flex;
+ flex-direction: column;
+ gap: 0.3rem;
+/* margin-top: 1.5rem;*/
+}
+
+.tm-notification-card {
+ background: #fff;
+ border: 1px solid rgba(148, 163, 184, 0.25);
+ border-radius: 0.5rem;
+ padding: 1.25rem;
+ box-shadow: 0 20px 45px rgba(15, 23, 42, 0.08);
+ display: flex;
+ flex-direction: column;
+ gap: 0.85rem;
+ position: relative;
+ width: 100%;
+}
+
+.tm-notification-card.is-unread {
+ border-color: rgba(37, 99, 235, 0.35);
+}
+
+.tm-notification-card-head {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 1rem;
+}
+
+.tm-notification-card-info {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 0.55rem;
+ flex: 1 1 auto;
+ min-width: 0;
+}
+
+.tm-notification-subject {
+ margin: 0;
+ font-size: 1rem;
+ color: #0f172a;
+}
+
+.tm-notification-status-dot {
+ width: 10px;
+ height: 10px;
+ border-radius: 50%;
+ background: rgba(148, 163, 184, 0.6);
+ display: inline-block;
+ margin-right: 0.45rem;
+}
+
+.tm-notification-card.is-unread .tm-notification-status-dot {
+ background: #1d4ed8;
+}
+
+.tm-notification-badge {
+ border-radius: 999px;
+ padding: 0.4rem 0.75rem;
+ font-size: 0.75rem;
+ text-transform: uppercase;
+ letter-spacing: 0.08em;
+}
+
+.tm-notification-badge.badge-unread {
+ background: rgba(37, 99, 235, 0.12);
+ color: #1d4ed8;
+}
+
+.tm-notification-badge.badge-read {
+ background: rgba(148, 163, 184, 0.15);
+ color: #475569;
+}
+
+.tm-notification-meta {
+ display: inline-flex;
+ flex-wrap: wrap;
+ gap: 0.75rem;
+ font-size: 0.85rem;
+ color: #64748b;
+}
+
+.tm-notification-meta i {
+ margin-right: 0.3rem;
+ color: #94a3b8;
+}
+
+.tm-notification-card-actions {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.75rem;
+}
+
+.tm-notification-pill {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.35rem;
+ padding: 0.15rem 0.7rem;
+ border-radius: 999px;
+ font-size: 0.75rem;
+ text-transform: uppercase;
+ letter-spacing: 0.06em;
+}
+
+.tm-notification-pill.is-read {
+ background: rgba(148, 163, 184, 0.25);
+ color: #475569;
+}
+
+.tm-notification-pill.is-unread {
+ background: rgba(248, 113, 113, 0.25);
+ color: #b91c1c;
+}
+
+/*.tm-notification-view {*/
+/* margin-top: 1.5rem;*/
+/*}*/
+
+.tm-notification-view-card {
+ background: #fff;
+ border: 1px solid rgba(148, 163, 184, 0.25);
+ border-radius: 1rem;
+ box-shadow: 0 30px 60px rgba(15, 23, 42, 0.12);
+ padding: 1.75rem;
+ margin-top: 1.5rem;
+}
+
+.tm-notification-view-head {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+ gap: 1rem;
+ margin-bottom: 1rem;
+}
+
+.tm-notification-view-label {
+ text-transform: uppercase;
+ letter-spacing: 0.18em;
+ font-size: 0.75rem;
+ color: #94a3b8;
+ margin: 0 0 0.35rem;
+}
+
+.tm-notification-view-title {
+ margin: 0;
+ color: #0f172a;
+}
+
+.tm-notification-view-body {
+ font-size: 0.95rem;
+ line-height: 1.7;
+ color: #1e293b;
+ white-space: pre-wrap;
+}
+
+.tm-notification-view-body p {
+ margin-bottom: 1rem;
+}
+
+.tm-empty-state,
+.tm-notification-empty {
+ padding: 3rem 1.5rem;
+ text-align: center;
+ border: 2px dashed rgba(148, 163, 184, 0.45);
+ border-radius: 1.25rem;
+ background: rgba(248, 250, 252, 0.9);
+/* margin: 1.5rem auto 0;*/
+ margin: 0 auto 0;
+ max-width: 640px;
+ box-shadow: 0 18px 40px rgba(15, 23, 42, 0.08);
+}
+
+.tm-empty-state > i,
+.tm-notification-empty > i {
+ font-size: 3rem;
+ color: #94a3b8;
+ margin-bottom: 0.9rem;
+}
+
+.tm-empty-state h3,
+.tm-notification-empty h3 {
+ margin-bottom: 0.5rem;
+ font-size: 1.5rem;
+ color: #0f172a;
+ font-weight: 600;
+}
+
+.tm-empty-state p,
+.tm-notification-empty p {
+ margin: 0 auto;
+ max-width: 460px;
+ color: #475569;
+ line-height: 1.6;
+}
+
+.tm-empty-state-actions {
+ margin-top: 1.25rem;
+ display: inline-flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ gap: 0.75rem;
+}
+
.tm-directory-tags {
display: flex;
flex-wrap: wrap;
@@ -1176,6 +1757,7 @@ html, body {
display: flex;
align-items: center;
justify-content: flex-end;
+ gap: 0.5rem;
}
.tm-call-card-actions .btn {
@@ -1183,6 +1765,17 @@ html, body {
font-size: 0.85rem;
}
+@media (max-width: 1200px) {
+ .tm-call-card {
+ grid-template-columns: minmax(220px, 1fr) minmax(0, 1fr);
+ }
+
+ .tm-call-card-actions {
+ grid-column: 1 / -1;
+ justify-content: flex-start;
+ }
+}
+
@media (max-width: 992px) {
.tm-call-card {
grid-template-columns: 1fr;
@@ -1656,7 +2249,7 @@ html, body {
.dashboard-stats-row {
margin-bottom: 1.5rem;
- justify-content: center;
+ justify-content: flex-start;
}
@media (min-width: 1200px) {