mohsin-devs commited on
Commit
8b653e0
·
1 Parent(s): 508fdfd

Improve Links UI and hide storage folder

Browse files
Files changed (5) hide show
  1. index.html +57 -13
  2. js/main.js +38 -25
  3. js/ui/uiRenderer.js +4 -2
  4. server/storage/hf.py +3 -1
  5. styles.css +514 -173
index.html CHANGED
@@ -124,11 +124,22 @@
124
 
125
  <div id="linksView" class="links-view" style="display:none;">
126
  <section class="links-hero">
127
- <div>
128
  <span class="links-eyebrow">Interactive Link Storage</span>
129
  <h2>Save important websites alongside your documents</h2>
130
  <p>Collect references, dashboards, and research links in one searchable place.</p>
131
  </div>
 
 
 
 
 
 
 
 
 
 
 
132
  <button class="btn-primary" id="heroAddLinkBtn">
133
  <i class="ph-fill ph-link-plus"></i> Add Link
134
  </button>
@@ -136,31 +147,64 @@
136
 
137
  <section class="links-toolbar">
138
  <div class="links-stat-card">
139
- <span class="links-stat-label">Stored Links</span>
140
- <strong id="linksCount">0</strong>
 
 
 
 
 
 
141
  </div>
142
  <div class="links-stat-card">
143
- <span class="links-stat-label">Latest Update</span>
144
- <strong id="linksUpdatedAt">Just now</strong>
 
 
 
 
 
 
145
  </div>
146
  <div class="links-search">
147
- <i class="ph-bold ph-magnifying-glass"></i>
148
- <input type="text" id="linksSearchInput" placeholder="Search title, URL, or notes...">
 
 
 
 
 
 
149
  </div>
150
  </section>
151
 
152
  <section class="links-insights">
153
  <div class="links-note-chip">
154
- <i class="ph-fill ph-globe-hemisphere-west"></i>
155
- <span>Save articles, dashboards, and internal tools</span>
 
 
 
 
 
156
  </div>
157
  <div class="links-note-chip">
158
- <i class="ph-fill ph-lightning"></i>
159
- <span>Open, copy, edit, and clean up links quickly</span>
 
 
 
 
 
160
  </div>
161
  <div class="links-note-chip">
162
- <i class="ph-fill ph-note-pencil"></i>
163
- <span>Keep notes next to each saved website</span>
 
 
 
 
 
164
  </div>
165
  </section>
166
 
 
124
 
125
  <div id="linksView" class="links-view" style="display:none;">
126
  <section class="links-hero">
127
+ <div class="links-hero-copy">
128
  <span class="links-eyebrow">Interactive Link Storage</span>
129
  <h2>Save important websites alongside your documents</h2>
130
  <p>Collect references, dashboards, and research links in one searchable place.</p>
131
  </div>
132
+ <div class="links-hero-art" aria-hidden="true">
133
+ <div class="hero-orb hero-orb-one"></div>
134
+ <div class="hero-orb hero-orb-two"></div>
135
+ <div class="hero-card hero-card-back"></div>
136
+ <div class="hero-card hero-card-front">
137
+ <div class="hero-link-glyph">
138
+ <i class="ph-bold ph-link"></i>
139
+ </div>
140
+ </div>
141
+ <i class="ph-thin ph-globe hero-globe"></i>
142
+ </div>
143
  <button class="btn-primary" id="heroAddLinkBtn">
144
  <i class="ph-fill ph-link-plus"></i> Add Link
145
  </button>
 
147
 
148
  <section class="links-toolbar">
149
  <div class="links-stat-card">
150
+ <div class="links-stat-icon tint-green">
151
+ <i class="ph-bold ph-link"></i>
152
+ </div>
153
+ <div class="links-stat-copy">
154
+ <span class="links-stat-label">Stored Links</span>
155
+ <strong id="linksCount">0</strong>
156
+ <span class="links-stat-subtitle">Total saved links</span>
157
+ </div>
158
  </div>
159
  <div class="links-stat-card">
160
+ <div class="links-stat-icon tint-blue">
161
+ <i class="ph-bold ph-calendar-blank"></i>
162
+ </div>
163
+ <div class="links-stat-copy">
164
+ <span class="links-stat-label">Latest Update</span>
165
+ <strong id="linksUpdatedAt">Just now</strong>
166
+ <span class="links-stat-subtitle">Most recent activity</span>
167
+ </div>
168
  </div>
169
  <div class="links-search">
170
+ <div class="links-search-input">
171
+ <i class="ph-bold ph-magnifying-glass"></i>
172
+ <input type="text" id="linksSearchInput" placeholder="Search title, URL, or notes...">
173
+ </div>
174
+ <button class="links-filter-btn" type="button">
175
+ <i class="ph-bold ph-funnel-simple"></i>
176
+ <span>Filters</span>
177
+ </button>
178
  </div>
179
  </section>
180
 
181
  <section class="links-insights">
182
  <div class="links-note-chip">
183
+ <div class="links-note-icon tint-green-soft">
184
+ <i class="ph-fill ph-file-doc"></i>
185
+ </div>
186
+ <div class="links-note-copy">
187
+ <strong>Save everything</strong>
188
+ <span>Articles, dashboards, and internal tools</span>
189
+ </div>
190
  </div>
191
  <div class="links-note-chip">
192
+ <div class="links-note-icon tint-blue-soft">
193
+ <i class="ph-fill ph-lightning"></i>
194
+ </div>
195
+ <div class="links-note-copy">
196
+ <strong>Work smarter</strong>
197
+ <span>Open, copy, edit, and clean up links quickly</span>
198
+ </div>
199
  </div>
200
  <div class="links-note-chip">
201
+ <div class="links-note-icon tint-purple-soft">
202
+ <i class="ph-fill ph-note-pencil"></i>
203
+ </div>
204
+ <div class="links-note-copy">
205
+ <strong>Stay organized</strong>
206
+ <span>Keep notes next to each saved website</span>
207
+ </div>
208
  </div>
209
  </section>
210
 
js/main.js CHANGED
@@ -536,43 +536,56 @@ class App {
536
  }
537
 
538
  linksContainer.innerHTML = links
539
- .map((link) => `
540
- <article class="link-card">
 
 
 
 
541
  <div class="link-card-header">
542
- <div class="link-icon">
543
- <i class="ph-fill ph-link"></i>
 
 
 
544
  </div>
545
  <div class="link-card-content">
546
  <div class="link-card-topline">
547
- <div class="link-title">${this.escapeHtml(link.title || link.url)}</div>
548
- <span class="link-domain-badge">${this.escapeHtml(this.getLinkHostname(link.url))}</span>
549
  </div>
550
- <a href="${this.escapeHtml(link.url)}" target="_blank" rel="noopener noreferrer" class="link-url" title="${this.escapeHtml(link.url)}">
551
  ${this.escapeHtml(link.url)}
552
  </a>
553
  </div>
554
  </div>
555
- ${link.description ? `<p class="link-description">${this.escapeHtml(link.description)}</p>` : '<p class="link-description muted">No notes added yet.</p>'}
556
- <div class="link-meta">
557
- <span><i class="ph-fill ph-clock"></i> ${this.formatRelativeDate(link.updated_at || link.created_at)}</span>
558
- <span><i class="ph-fill ph-bookmark-simple"></i> Saved item</span>
559
  </div>
560
- <div class="link-actions">
561
- <a href="${this.escapeHtml(link.url)}" target="_blank" rel="noopener noreferrer" class="link-action-btn">
562
- <i class="ph-fill ph-arrow-up-right"></i> Open
563
- </a>
564
- <button class="link-action-btn" data-action="copy" data-link-url="${this.escapeHtml(link.url)}">
565
- <i class="ph-fill ph-copy"></i> Copy
566
- </button>
567
- <button class="link-action-btn" data-action="edit" data-link-id="${link.id}">
568
- <i class="ph-fill ph-pencil-simple"></i> Edit
569
- </button>
570
- <button class="link-action-btn delete" data-action="delete" data-link-id="${link.id}">
571
- <i class="ph-fill ph-trash"></i> Delete
572
- </button>
 
 
 
 
 
 
 
573
  </div>
574
  </article>
575
- `)
576
  .join('');
577
 
578
  linksContainer.querySelectorAll('[data-action="copy"]').forEach((btn) => {
 
536
  }
537
 
538
  linksContainer.innerHTML = links
539
+ .map((link) => {
540
+ const hostname = this.getLinkHostname(link.url);
541
+ const faviconUrl = `https://www.google.com/s2/favicons?domain=${hostname}&sz=128`;
542
+
543
+ return `
544
+ <article class="link-card" data-link-id="${link.id}">
545
  <div class="link-card-header">
546
+ <div class="link-icon-container">
547
+ <img src="${faviconUrl}" alt="" class="link-favicon" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex'">
548
+ <div class="link-icon-fallback" style="display:none">
549
+ <i class="ph-fill ph-link"></i>
550
+ </div>
551
  </div>
552
  <div class="link-card-content">
553
  <div class="link-card-topline">
554
+ <div class="link-title" title="${this.escapeHtml(link.title || link.url)}">${this.escapeHtml(link.title || link.url)}</div>
555
+ <span class="link-domain-badge">${this.escapeHtml(hostname)}</span>
556
  </div>
557
+ <a href="${this.escapeHtml(link.url)}" target="_blank" rel="noopener noreferrer" class="link-url">
558
  ${this.escapeHtml(link.url)}
559
  </a>
560
  </div>
561
  </div>
562
+
563
+ <div class="link-card-body">
564
+ ${link.description ? `<p class="link-description">${this.escapeHtml(link.description)}</p>` : '<p class="link-description empty">No additional notes.</p>'}
 
565
  </div>
566
+
567
+ <div class="link-card-footer">
568
+ <div class="link-meta">
569
+ <i class="ph-fill ph-clock"></i>
570
+ <span>${this.formatRelativeDate(link.updated_at || link.created_at)}</span>
571
+ </div>
572
+ <div class="link-actions">
573
+ <button class="link-action-btn copy-btn" data-action="copy" data-link-url="${this.escapeHtml(link.url)}" title="Copy Link">
574
+ <i class="ph-bold ph-copy"></i>
575
+ </button>
576
+ <button class="link-action-btn edit-btn" data-action="edit" data-link-id="${link.id}" title="Edit Link">
577
+ <i class="ph-bold ph-pencil-simple"></i>
578
+ </button>
579
+ <button class="link-action-btn delete-btn" data-action="delete" data-link-id="${link.id}" title="Delete Link">
580
+ <i class="ph-bold ph-trash"></i>
581
+ </button>
582
+ <a href="${this.escapeHtml(link.url)}" target="_blank" rel="noopener noreferrer" class="btn-visit">
583
+ Visit <i class="ph-bold ph-arrow-square-out"></i>
584
+ </a>
585
+ </div>
586
  </div>
587
  </article>
588
+ `;})
589
  .join('');
590
 
591
  linksContainer.querySelectorAll('[data-action="copy"]').forEach((btn) => {
js/ui/uiRenderer.js CHANGED
@@ -65,9 +65,11 @@ export class UIRenderer {
65
 
66
  renderFolders(folders, onFolderClick, onRename, onDelete) {
67
  this.containers.folders.innerHTML = '';
68
- if (!folders.length) return;
 
 
69
 
70
- folders.forEach(folder => {
71
  const card = document.createElement('div');
72
  card.className = 'folder-card';
73
  card.innerHTML = `
 
65
 
66
  renderFolders(folders, onFolderClick, onRename, onDelete) {
67
  this.containers.folders.innerHTML = '';
68
+ // Filter out hidden folders (starting with .)
69
+ const visibleFolders = folders.filter(f => !f.name.startsWith('.'));
70
+ if (!visibleFolders.length) return;
71
 
72
+ visibleFolders.forEach(folder => {
73
  const card = document.createElement('div');
74
  card.className = 'folder-card';
75
  card.innerHTML = `
server/storage/hf.py CHANGED
@@ -428,7 +428,9 @@ class HuggingFaceStorageManager(StorageInterface):
428
  )
429
  )
430
 
431
- folders = sorted(folders_map.values(), key=lambda item: item["name"].lower())
 
 
432
  files.sort(key=lambda item: item["name"].lower())
433
  return {
434
  "success": True,
 
428
  )
429
  )
430
 
431
+ # Filter out hidden folders (starting with .)
432
+ folders_list = [f for f in folders_map.values() if not f["name"].startswith(".")]
433
+ folders = sorted(folders_list, key=lambda item: item["name"].lower())
434
  files.sort(key=lambda item: item["name"].lower())
435
  return {
436
  "success": True,
styles.css CHANGED
@@ -464,63 +464,200 @@ body {
464
 
465
  .links-hero {
466
  background:
467
- radial-gradient(circle at top left, rgba(59, 130, 246, 0.12), transparent 30%),
468
- linear-gradient(135deg, #16233f, #21314b 56%, #1c5667);
 
469
  color: #f8fafc;
470
- border-radius: var(--radius-lg);
471
- padding: 22px 28px;
472
- min-height: 196px;
473
  display: flex;
474
  align-items: center;
475
  justify-content: space-between;
476
  gap: var(--space-3);
477
  box-shadow: var(--shadow-lg);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
  }
479
 
480
  .links-eyebrow {
481
  display: inline-flex;
482
- font-size: 11px;
483
- letter-spacing: 1px;
484
  text-transform: uppercase;
485
- color: rgba(255, 255, 255, 0.7);
486
  margin-bottom: var(--space-2);
 
487
  }
488
 
489
  .links-hero h2 {
490
- font-size: 28px;
491
- line-height: 1.12;
492
- letter-spacing: -0.6px;
493
- margin-bottom: 12px;
494
- max-width: 760px;
495
  }
496
 
497
  .links-hero p {
498
  max-width: 560px;
499
- color: rgba(241, 245, 249, 0.82);
500
- line-height: 1.7;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
501
  }
502
 
503
  .links-toolbar {
504
  display: grid;
505
- grid-template-columns: repeat(2, minmax(0, 180px)) minmax(240px, 1fr);
506
  gap: var(--space-2);
507
  align-items: stretch;
508
  }
509
 
510
  .links-insights {
511
- display: flex;
512
- flex-wrap: wrap;
513
- gap: 10px;
514
- margin-top: -6px;
515
  }
516
 
517
  .links-note-chip {
518
- display: inline-flex;
519
  align-items: center;
520
- gap: 8px;
521
- padding: 9px 14px;
522
- border-radius: 999px;
523
- background: rgba(255, 255, 255, 0.9);
524
  border: 1px solid var(--border-color);
525
  color: var(--text-muted);
526
  font-size: 12px;
@@ -528,16 +665,38 @@ body {
528
  box-shadow: var(--shadow-sm);
529
  }
530
 
531
- .links-note-chip i {
532
- color: var(--primary-color);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
533
  font-size: 16px;
 
 
 
 
 
 
534
  }
535
 
536
  .links-stat-card,
537
  .links-search {
538
- background: var(--card);
539
  border: 1px solid var(--border-color);
540
- border-radius: var(--radius-md);
541
  padding: 22px 24px;
542
  box-shadow: 0 2px 8px rgba(0,0,0,0.05);
543
  transition: all 0.2s ease;
@@ -545,10 +704,10 @@ body {
545
 
546
  .links-stat-card {
547
  display: flex;
548
- flex-direction: column;
549
- gap: 8px;
550
- min-height: 118px;
551
- justify-content: center;
552
  }
553
 
554
  .links-stat-card:hover,
@@ -557,31 +716,67 @@ body {
557
  box-shadow: var(--shadow-md);
558
  }
559
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
560
  .links-stat-label {
561
- font-size: 11px;
562
  text-transform: uppercase;
563
- letter-spacing: 0.8px;
564
- color: var(--text-muted);
565
  font-weight: 700;
566
  }
567
 
568
  .links-stat-card strong {
569
- font-size: 24px;
570
  line-height: 1.1;
571
- color: var(--text-main);
 
 
 
 
 
572
  }
573
 
574
  .links-search {
575
  display: flex;
576
  align-items: center;
577
- gap: 12px;
578
- min-height: 118px;
 
579
  border-color: #d7e2ee;
 
580
  }
581
 
582
- .links-search i {
583
- color: var(--text-muted);
584
- font-size: 22px;
 
 
 
 
 
 
 
 
 
 
 
 
585
  }
586
 
587
  .links-search input {
@@ -590,13 +785,60 @@ body {
590
  background: transparent;
591
  outline: none;
592
  font-family: inherit;
593
- font-size: 15px;
594
  color: var(--text-main);
595
  }
596
 
597
- .links-search:focus-within {
598
- border-color: #22c55e;
599
- box-shadow: 0 0 0 2px #22c55e;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
600
  }
601
 
602
  .link-preview-panel {
@@ -1736,10 +1978,18 @@ body {
1736
  .sidebar { width: 224px; }
1737
  .search-bar { width: 100%; max-width: 420px; }
1738
  .grid-container { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }
 
 
 
 
 
 
 
 
 
1739
  .links-toolbar { grid-template-columns: 1fr 1fr; }
1740
  .links-search { grid-column: 1 / -1; }
1741
- .links-hero h2 { font-size: 24px; }
1742
- .links-empty h3 { font-size: 28px; }
1743
  }
1744
 
1745
  @media (max-width: 768px) {
@@ -1778,26 +2028,49 @@ body {
1778
  .file-card { border-radius: 16px; }
1779
  .file-preview { height: 92px; }
1780
  .links-hero {
1781
- padding: 20px;
1782
- min-height: auto;
1783
  flex-direction: column;
1784
  align-items: flex-start;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1785
  }
1786
- .links-hero h2 { font-size: 22px; }
1787
  .links-toolbar { grid-template-columns: 1fr; }
1788
- .links-stat-card strong { font-size: 22px; }
1789
- .links-note-chip { width: 100%; justify-content: center; }
1790
- .link-card-topline { flex-direction: column; }
1791
- .shortcut-hint { width: 100%; margin-right: 0; }
1792
- .links-empty {
1793
- padding: 72px 20px 80px;
 
 
 
 
 
1794
  }
1795
- .links-empty h3 {
1796
- font-size: 26px;
 
1797
  }
1798
- .links-empty p {
1799
- font-size: 15px;
 
 
1800
  }
 
 
1801
 
1802
  /* Mobile Menu Toggle */
1803
  .menu-toggle {
@@ -1931,41 +2204,92 @@ body {
1931
  font-size: 13px;
1932
  }
1933
 
1934
- /* ── LINKS SECTION ── */
1935
  .links-container {
1936
  display: grid;
1937
- grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
1938
- gap: var(--space-2);
1939
  margin-top: var(--space-2);
 
 
 
 
 
 
1940
  }
1941
 
1942
  .link-card {
1943
- background: var(--card);
1944
- border: 1px solid var(--border-color);
1945
- border-radius: 14px;
1946
- padding: 18px;
1947
  position: relative;
1948
- cursor: pointer;
1949
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
1950
- box-shadow: var(--shadow-sm);
1951
  display: flex;
1952
  flex-direction: column;
1953
- gap: 12px;
1954
- animation: cardFadeIn 0.4s ease-out forwards;
 
 
1955
  opacity: 0;
1956
- transform: translateY(20px);
 
 
 
 
 
1957
  }
1958
 
1959
  .link-card:hover {
1960
- transform: translateY(-4px);
1961
- box-shadow: var(--shadow-lg);
1962
- border-color: var(--primary-color);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1963
  }
1964
 
1965
  .link-card-header {
1966
  display: flex;
1967
- align-items: flex-start;
1968
- gap: 12px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1969
  }
1970
 
1971
  .link-card-content {
@@ -1977,123 +2301,143 @@ body {
1977
  display: flex;
1978
  align-items: flex-start;
1979
  justify-content: space-between;
1980
- gap: 10px;
1981
- margin-bottom: 6px;
1982
- }
1983
-
1984
- .link-icon {
1985
- width: 40px;
1986
- height: 40px;
1987
- background: var(--primary-light);
1988
- border-radius: 10px;
1989
- display: flex;
1990
- align-items: center;
1991
- justify-content: center;
1992
- color: var(--primary-color);
1993
- font-size: 20px;
1994
- flex-shrink: 0;
1995
  }
1996
 
1997
  .link-title {
1998
- font-size: 15px;
1999
- font-weight: 600;
2000
- color: var(--text-main);
2001
- word-break: break-word;
2002
- line-height: 1.3;
 
 
2003
  }
2004
 
2005
  .link-domain-badge {
2006
- display: inline-flex;
2007
- align-items: center;
2008
- white-space: nowrap;
2009
- padding: 5px 10px;
2010
- border-radius: 999px;
2011
- background: var(--hover-bg);
2012
- color: var(--text-muted);
2013
- border: 1px solid var(--border-color);
2014
  font-size: 11px;
2015
  font-weight: 700;
2016
- letter-spacing: 0.3px;
 
 
 
 
 
 
2017
  }
2018
 
2019
  .link-url {
2020
- font-size: 12px;
2021
  color: var(--primary-color);
2022
- word-break: break-all;
2023
  text-decoration: none;
2024
- line-height: 1.4;
2025
  overflow: hidden;
2026
- display: -webkit-box;
2027
- -webkit-line-clamp: 1;
2028
- -webkit-box-orient: vertical;
 
 
 
 
 
 
 
 
 
 
2029
  }
2030
 
2031
  .link-description {
2032
- font-size: 13px;
2033
- color: var(--text-muted);
2034
- line-height: 1.5;
2035
  display: -webkit-box;
2036
  -webkit-line-clamp: 2;
2037
  -webkit-box-orient: vertical;
2038
  overflow: hidden;
 
2039
  }
2040
 
2041
- .link-description.muted {
2042
  color: #94a3b8;
2043
  font-style: italic;
 
2044
  }
2045
 
2046
- .link-meta {
2047
  display: flex;
2048
- flex-wrap: wrap;
2049
- gap: 10px 16px;
2050
- font-size: 12px;
2051
- color: var(--text-muted);
 
2052
  }
2053
 
2054
- .link-meta span {
2055
- display: inline-flex;
2056
  align-items: center;
2057
  gap: 6px;
 
 
 
 
 
 
 
2058
  }
2059
 
2060
  .link-actions {
2061
  display: flex;
 
2062
  gap: 8px;
2063
- justify-content: space-between;
2064
- flex-wrap: wrap;
2065
- padding-top: 8px;
2066
- border-top: 1px solid var(--border-color);
2067
  }
2068
 
2069
  .link-action-btn {
2070
- flex: 1 1 140px;
 
 
 
 
 
2071
  display: flex;
2072
  align-items: center;
2073
  justify-content: center;
2074
- gap: 6px;
2075
- padding: 8px 12px;
2076
- background: var(--hover-bg);
2077
- border: 1px solid var(--border-color);
2078
- border-radius: 8px;
2079
- color: var(--text-muted);
2080
- font-size: 13px;
2081
- font-weight: 600;
2082
  cursor: pointer;
2083
- transition: all 0.15s ease;
2084
- text-decoration: none;
2085
  }
2086
 
2087
  .link-action-btn:hover {
2088
- background: var(--primary-light);
2089
- color: var(--primary-color);
2090
- border-color: var(--primary-color);
2091
  }
2092
 
2093
- .link-action-btn.delete:hover {
2094
- background: rgba(239, 68, 68, 0.1);
2095
- color: var(--danger-color);
2096
- border-color: var(--danger-color);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2097
  }
2098
 
2099
  .links-empty {
@@ -2102,45 +2446,42 @@ body {
2102
  flex-direction: column;
2103
  align-items: center;
2104
  justify-content: center;
2105
- padding: 88px 24px 96px;
2106
  text-align: center;
2107
- color: var(--text-muted);
2108
- animation: fadeInUp 0.6s ease-out;
2109
  }
2110
 
2111
  .links-empty-illustration {
2112
- width: 92px;
2113
- height: 92px;
2114
- border-radius: 28px;
 
2115
  display: flex;
2116
  align-items: center;
2117
  justify-content: center;
2118
- margin-bottom: var(--space-3);
2119
- background: linear-gradient(180deg, #e2fdf1, #d8f7eb);
2120
- box-shadow: 0 12px 30px rgba(16, 185, 129, 0.12);
2121
- }
2122
-
2123
- .links-empty-illustration i {
2124
- font-size: 44px;
2125
- color: #12c989;
2126
- opacity: 1;
2127
- animation: bounceIn 0.8s ease-out;
2128
  }
2129
 
2130
  .links-empty h3 {
2131
- font-size: 34px;
2132
  font-weight: 700;
2133
- line-height: 1.1;
2134
- margin-bottom: 12px;
2135
- color: var(--text-main);
2136
  }
2137
 
2138
  .links-empty p {
2139
- font-size: 16px;
2140
- line-height: 1.7;
2141
- max-width: 420px;
2142
- margin-bottom: var(--space-3);
2143
- color: #7c8da5;
 
 
 
 
 
2144
  }
2145
 
2146
  .input-group textarea {
 
464
 
465
  .links-hero {
466
  background:
467
+ radial-gradient(circle at 28% 0%, rgba(73, 143, 255, 0.2), transparent 26%),
468
+ radial-gradient(circle at 72% 46%, rgba(21, 190, 175, 0.14), transparent 18%),
469
+ linear-gradient(90deg, #18315f 0%, #1c2e68 48%, #146d83 100%);
470
  color: #f8fafc;
471
+ border-radius: 24px;
472
+ padding: 42px 44px;
473
+ min-height: 256px;
474
  display: flex;
475
  align-items: center;
476
  justify-content: space-between;
477
  gap: var(--space-3);
478
  box-shadow: var(--shadow-lg);
479
+ position: relative;
480
+ overflow: hidden;
481
+ }
482
+
483
+ .links-hero::after {
484
+ content: '';
485
+ position: absolute;
486
+ width: 120px;
487
+ height: 120px;
488
+ top: 46px;
489
+ left: 58%;
490
+ opacity: 0.22;
491
+ pointer-events: none;
492
+ background:
493
+ radial-gradient(circle, rgba(255,255,255,0.14) 1.4px, transparent 1.5px);
494
+ background-size: 14px 14px;
495
+ }
496
+
497
+ .links-hero-copy {
498
+ position: relative;
499
+ z-index: 1;
500
  }
501
 
502
  .links-eyebrow {
503
  display: inline-flex;
504
+ font-size: 14px;
505
+ letter-spacing: 0.4px;
506
  text-transform: uppercase;
507
+ color: #8cf0d0;
508
  margin-bottom: var(--space-2);
509
+ font-weight: 700;
510
  }
511
 
512
  .links-hero h2 {
513
+ font-size: clamp(34px, 4vw, 58px);
514
+ line-height: 1.05;
515
+ letter-spacing: -1.4px;
516
+ margin-bottom: 16px;
517
+ max-width: 670px;
518
  }
519
 
520
  .links-hero p {
521
  max-width: 560px;
522
+ color: rgba(241, 245, 249, 0.86);
523
+ line-height: 1.6;
524
+ font-size: 16px;
525
+ }
526
+
527
+ .links-hero .btn-primary {
528
+ position: relative;
529
+ z-index: 1;
530
+ min-width: 164px;
531
+ min-height: 60px;
532
+ justify-content: center;
533
+ border-radius: 18px;
534
+ }
535
+
536
+ .links-hero-art {
537
+ flex: 0 0 360px;
538
+ height: 190px;
539
+ position: relative;
540
+ z-index: 1;
541
+ margin-left: auto;
542
+ }
543
+
544
+ .hero-orb {
545
+ position: absolute;
546
+ border-radius: 50%;
547
+ border: 1px solid rgba(255, 255, 255, 0.08);
548
+ }
549
+
550
+ .hero-orb-one {
551
+ width: 92px;
552
+ height: 92px;
553
+ right: 16px;
554
+ top: 18px;
555
+ }
556
+
557
+ .hero-orb-two {
558
+ width: 10px;
559
+ height: 10px;
560
+ left: 36px;
561
+ top: 52px;
562
+ background: rgba(140, 240, 208, 0.5);
563
+ border: none;
564
+ }
565
+
566
+ .hero-card {
567
+ position: absolute;
568
+ border: 3px solid rgba(136, 170, 214, 0.24);
569
+ border-radius: 18px;
570
+ background: linear-gradient(180deg, rgba(255,255,255,0.05), rgba(255,255,255,0.02));
571
+ }
572
+
573
+ .hero-card-back {
574
+ width: 172px;
575
+ height: 132px;
576
+ right: 136px;
577
+ top: 0;
578
+ transform: rotate(-4deg);
579
+ }
580
+
581
+ .hero-card-back::before,
582
+ .hero-card-back::after {
583
+ content: '';
584
+ position: absolute;
585
+ left: 18px;
586
+ height: 8px;
587
+ border-radius: 999px;
588
+ background: rgba(175, 202, 236, 0.34);
589
+ }
590
+
591
+ .hero-card-back::before {
592
+ width: 94px;
593
+ top: 24px;
594
+ }
595
+
596
+ .hero-card-back::after {
597
+ width: 62px;
598
+ top: 40px;
599
+ }
600
+
601
+ .hero-card-front {
602
+ width: 156px;
603
+ height: 110px;
604
+ right: 82px;
605
+ top: 54px;
606
+ transform: rotate(-4deg);
607
+ }
608
+
609
+ .hero-card-front::before {
610
+ content: '';
611
+ position: absolute;
612
+ top: -18px;
613
+ left: 22px;
614
+ width: 58px;
615
+ height: 26px;
616
+ border-radius: 10px 10px 0 0;
617
+ border: 3px solid rgba(136, 170, 214, 0.24);
618
+ border-bottom: none;
619
+ background: linear-gradient(180deg, rgba(255,255,255,0.05), rgba(255,255,255,0.01));
620
+ }
621
+
622
+ .hero-link-glyph {
623
+ position: absolute;
624
+ inset: 0;
625
+ display: flex;
626
+ align-items: center;
627
+ justify-content: center;
628
+ color: #2eb8d3;
629
+ font-size: 56px;
630
+ }
631
+
632
+ .hero-globe {
633
+ position: absolute;
634
+ right: 42px;
635
+ top: 18px;
636
+ font-size: 44px;
637
+ color: rgba(133, 171, 214, 0.3);
638
  }
639
 
640
  .links-toolbar {
641
  display: grid;
642
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(360px, 1.45fr);
643
  gap: var(--space-2);
644
  align-items: stretch;
645
  }
646
 
647
  .links-insights {
648
+ display: grid;
649
+ grid-template-columns: repeat(3, minmax(0, 1fr));
650
+ gap: 18px;
651
+ margin-top: -2px;
652
  }
653
 
654
  .links-note-chip {
655
+ display: flex;
656
  align-items: center;
657
+ gap: 16px;
658
+ padding: 18px 22px;
659
+ border-radius: 20px;
660
+ background: #ffffff;
661
  border: 1px solid var(--border-color);
662
  color: var(--text-muted);
663
  font-size: 12px;
 
665
  box-shadow: var(--shadow-sm);
666
  }
667
 
668
+ .links-note-icon {
669
+ width: 48px;
670
+ height: 48px;
671
+ border-radius: 16px;
672
+ display: flex;
673
+ align-items: center;
674
+ justify-content: center;
675
+ flex-shrink: 0;
676
+ font-size: 22px;
677
+ }
678
+
679
+ .links-note-copy {
680
+ display: flex;
681
+ flex-direction: column;
682
+ gap: 4px;
683
+ }
684
+
685
+ .links-note-copy strong {
686
  font-size: 16px;
687
+ color: #18315f;
688
+ }
689
+
690
+ .links-note-copy span {
691
+ font-size: 14px;
692
+ color: #62748e;
693
  }
694
 
695
  .links-stat-card,
696
  .links-search {
697
+ background: #ffffff;
698
  border: 1px solid var(--border-color);
699
+ border-radius: 22px;
700
  padding: 22px 24px;
701
  box-shadow: 0 2px 8px rgba(0,0,0,0.05);
702
  transition: all 0.2s ease;
 
704
 
705
  .links-stat-card {
706
  display: flex;
707
+ align-items: center;
708
+ gap: 18px;
709
+ min-height: 132px;
710
+ justify-content: flex-start;
711
  }
712
 
713
  .links-stat-card:hover,
 
716
  box-shadow: var(--shadow-md);
717
  }
718
 
719
+ .links-stat-icon {
720
+ width: 76px;
721
+ height: 76px;
722
+ border-radius: 50%;
723
+ display: flex;
724
+ align-items: center;
725
+ justify-content: center;
726
+ font-size: 34px;
727
+ flex-shrink: 0;
728
+ }
729
+
730
+ .links-stat-copy {
731
+ display: flex;
732
+ flex-direction: column;
733
+ gap: 6px;
734
+ }
735
+
736
  .links-stat-label {
737
+ font-size: 12px;
738
  text-transform: uppercase;
739
+ letter-spacing: 0.6px;
740
+ color: #71819b;
741
  font-weight: 700;
742
  }
743
 
744
  .links-stat-card strong {
745
+ font-size: 30px;
746
  line-height: 1.1;
747
+ color: #0f2b63;
748
+ }
749
+
750
+ .links-stat-subtitle {
751
+ font-size: 14px;
752
+ color: #62748e;
753
  }
754
 
755
  .links-search {
756
  display: flex;
757
  align-items: center;
758
+ justify-content: space-between;
759
+ gap: 18px;
760
+ min-height: 132px;
761
  border-color: #d7e2ee;
762
+ padding: 20px 22px;
763
  }
764
 
765
+ .links-search-input {
766
+ display: flex;
767
+ align-items: center;
768
+ gap: 16px;
769
+ min-height: 84px;
770
+ flex: 1;
771
+ border: 1px solid #e6edf5;
772
+ border-radius: 20px;
773
+ padding: 0 22px;
774
+ background: linear-gradient(180deg, #ffffff, #fbfdff);
775
+ }
776
+
777
+ .links-search-input i {
778
+ color: #6b778a;
779
+ font-size: 28px;
780
  }
781
 
782
  .links-search input {
 
785
  background: transparent;
786
  outline: none;
787
  font-family: inherit;
788
+ font-size: 16px;
789
  color: var(--text-main);
790
  }
791
 
792
+ .links-search-input:focus-within {
793
+ border-color: #c7d8eb;
794
+ box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.08);
795
+ }
796
+
797
+ .links-filter-btn {
798
+ min-height: 46px;
799
+ padding: 0 18px;
800
+ border-radius: 999px;
801
+ border: 1px solid #dce7f2;
802
+ background: #ffffff;
803
+ color: #4b5b72;
804
+ display: inline-flex;
805
+ align-items: center;
806
+ gap: 10px;
807
+ font-family: inherit;
808
+ font-size: 14px;
809
+ font-weight: 700;
810
+ cursor: pointer;
811
+ transition: all 0.2s ease;
812
+ }
813
+
814
+ .links-filter-btn:hover {
815
+ background: #f8fbff;
816
+ border-color: #c8d8e8;
817
+ }
818
+
819
+ .tint-green {
820
+ background: #dff8ec;
821
+ color: #10b981;
822
+ }
823
+
824
+ .tint-blue {
825
+ background: #e6f0ff;
826
+ color: #2f80ed;
827
+ }
828
+
829
+ .tint-green-soft {
830
+ background: #dff8ec;
831
+ color: #11b87f;
832
+ }
833
+
834
+ .tint-blue-soft {
835
+ background: #e8f1ff;
836
+ color: #2d7ef0;
837
+ }
838
+
839
+ .tint-purple-soft {
840
+ background: #efe8ff;
841
+ color: #7c57eb;
842
  }
843
 
844
  .link-preview-panel {
 
1978
  .sidebar { width: 224px; }
1979
  .search-bar { width: 100%; max-width: 420px; }
1980
  .grid-container { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }
1981
+ .links-hero {
1982
+ padding: 32px 28px;
1983
+ min-height: 220px;
1984
+ }
1985
+ .links-hero-art {
1986
+ flex-basis: 250px;
1987
+ transform: scale(0.82);
1988
+ transform-origin: right center;
1989
+ }
1990
  .links-toolbar { grid-template-columns: 1fr 1fr; }
1991
  .links-search { grid-column: 1 / -1; }
1992
+ .links-insights { grid-template-columns: 1fr; }
 
1993
  }
1994
 
1995
  @media (max-width: 768px) {
 
2028
  .file-card { border-radius: 16px; }
2029
  .file-preview { height: 92px; }
2030
  .links-hero {
2031
+ padding: 24px 20px;
 
2032
  flex-direction: column;
2033
  align-items: flex-start;
2034
+ min-height: auto;
2035
+ }
2036
+ .links-hero::after {
2037
+ left: auto;
2038
+ right: 18px;
2039
+ top: 120px;
2040
+ }
2041
+ .links-hero-art {
2042
+ width: 100%;
2043
+ height: 132px;
2044
+ flex: none;
2045
+ margin-left: 0;
2046
+ transform: scale(0.8);
2047
+ transform-origin: left center;
2048
  }
2049
+ .links-hero h2 { font-size: 24px; }
2050
  .links-toolbar { grid-template-columns: 1fr; }
2051
+ .links-stat-card {
2052
+ min-height: auto;
2053
+ padding: 20px;
2054
+ }
2055
+ .links-stat-card strong { font-size: 24px; }
2056
+ .links-search {
2057
+ flex-direction: column;
2058
+ align-items: stretch;
2059
+ }
2060
+ .links-search-input {
2061
+ min-height: 64px;
2062
  }
2063
+ .links-filter-btn {
2064
+ width: fit-content;
2065
+ align-self: flex-end;
2066
  }
2067
+ .links-note-chip { width: 100%; }
2068
+ .links-container {
2069
+ padding: 16px;
2070
+ border-radius: 20px;
2071
  }
2072
+ .link-card-topline { flex-direction: column; }
2073
+ .shortcut-hint { width: 100%; margin-right: 0; }
2074
 
2075
  /* Mobile Menu Toggle */
2076
  .menu-toggle {
 
2204
  font-size: 13px;
2205
  }
2206
 
2207
+ /* -- LINKS SECTION -- */
2208
  .links-container {
2209
  display: grid;
2210
+ grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
2211
+ gap: 24px;
2212
  margin-top: var(--space-2);
2213
+ background: #ffffff;
2214
+ border: 1px solid #e8edf4;
2215
+ border-radius: 28px;
2216
+ min-height: 300px;
2217
+ padding: 32px;
2218
+ box-shadow: var(--shadow-sm);
2219
  }
2220
 
2221
  .link-card {
2222
+ background: #ffffff;
2223
+ border: 1px solid #eef2f6;
2224
+ border-radius: 20px;
2225
+ padding: 24px;
2226
  position: relative;
 
 
 
2227
  display: flex;
2228
  flex-direction: column;
2229
+ gap: 18px;
2230
+ transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1);
2231
+ box-shadow: 0 4px 12px rgba(15, 23, 42, 0.02);
2232
+ animation: cardFadeIn 0.5s ease-out forwards;
2233
  opacity: 0;
2234
+ transform: translateY(15px);
2235
+ overflow: hidden;
2236
+ }
2237
+
2238
+ @keyframes cardFadeIn {
2239
+ to { opacity: 1; transform: translateY(0); }
2240
  }
2241
 
2242
  .link-card:hover {
2243
+ transform: translateY(-6px);
2244
+ box-shadow: 0 12px 32px rgba(15, 23, 42, 0.08);
2245
+ border-color: rgba(16, 185, 129, 0.2);
2246
+ }
2247
+
2248
+ .link-card::before {
2249
+ content: "";
2250
+ position: absolute;
2251
+ top: 0;
2252
+ left: 0;
2253
+ width: 100%;
2254
+ height: 4px;
2255
+ background: var(--primary-gradient);
2256
+ opacity: 0;
2257
+ transition: opacity 0.3s ease;
2258
+ }
2259
+
2260
+ .link-card:hover::before {
2261
+ opacity: 1;
2262
  }
2263
 
2264
  .link-card-header {
2265
  display: flex;
2266
+ align-items: center;
2267
+ gap: 16px;
2268
+ }
2269
+
2270
+ .link-icon-container {
2271
+ width: 52px;
2272
+ height: 52px;
2273
+ background: #f8fafc;
2274
+ border: 1px solid #f1f5f9;
2275
+ border-radius: 14px;
2276
+ display: flex;
2277
+ align-items: center;
2278
+ justify-content: center;
2279
+ flex-shrink: 0;
2280
+ overflow: hidden;
2281
+ box-shadow: inset 0 1px 3px rgba(0,0,0,0.02);
2282
+ }
2283
+
2284
+ .link-favicon {
2285
+ width: 32px;
2286
+ height: 32px;
2287
+ object-fit: contain;
2288
+ }
2289
+
2290
+ .link-icon-fallback {
2291
+ color: var(--primary-color);
2292
+ font-size: 24px;
2293
  }
2294
 
2295
  .link-card-content {
 
2301
  display: flex;
2302
  align-items: flex-start;
2303
  justify-content: space-between;
2304
+ gap: 12px;
2305
+ margin-bottom: 4px;
 
 
 
 
 
 
 
 
 
 
 
 
 
2306
  }
2307
 
2308
  .link-title {
2309
+ font-size: 16px;
2310
+ font-weight: 700;
2311
+ color: #1e293b;
2312
+ line-height: 1.4;
2313
+ white-space: nowrap;
2314
+ overflow: hidden;
2315
+ text-overflow: ellipsis;
2316
  }
2317
 
2318
  .link-domain-badge {
 
 
 
 
 
 
 
 
2319
  font-size: 11px;
2320
  font-weight: 700;
2321
+ text-transform: uppercase;
2322
+ letter-spacing: 0.5px;
2323
+ color: #64748b;
2324
+ background: #f1f5f9;
2325
+ padding: 4px 10px;
2326
+ border-radius: 8px;
2327
+ white-space: nowrap;
2328
  }
2329
 
2330
  .link-url {
2331
+ font-size: 13px;
2332
  color: var(--primary-color);
 
2333
  text-decoration: none;
2334
+ white-space: nowrap;
2335
  overflow: hidden;
2336
+ text-overflow: ellipsis;
2337
+ display: block;
2338
+ font-weight: 500;
2339
+ transition: color 0.2s ease;
2340
+ }
2341
+
2342
+ .link-url:hover {
2343
+ color: var(--primary-hover);
2344
+ text-decoration: underline;
2345
+ }
2346
+
2347
+ .link-card-body {
2348
+ flex: 1;
2349
  }
2350
 
2351
  .link-description {
2352
+ font-size: 14px;
2353
+ line-height: 1.6;
2354
+ color: #475569;
2355
  display: -webkit-box;
2356
  -webkit-line-clamp: 2;
2357
  -webkit-box-orient: vertical;
2358
  overflow: hidden;
2359
+ margin: 0;
2360
  }
2361
 
2362
+ .link-description.empty {
2363
  color: #94a3b8;
2364
  font-style: italic;
2365
+ font-size: 13px;
2366
  }
2367
 
2368
+ .link-card-footer {
2369
  display: flex;
2370
+ align-items: center;
2371
+ justify-content: space-between;
2372
+ padding-top: 16px;
2373
+ border-top: 1px solid #f1f5f9;
2374
+ margin-top: auto;
2375
  }
2376
 
2377
+ .link-meta {
2378
+ display: flex;
2379
  align-items: center;
2380
  gap: 6px;
2381
+ font-size: 12px;
2382
+ color: #94a3b8;
2383
+ font-weight: 500;
2384
+ }
2385
+
2386
+ .link-meta i {
2387
+ font-size: 14px;
2388
  }
2389
 
2390
  .link-actions {
2391
  display: flex;
2392
+ align-items: center;
2393
  gap: 8px;
 
 
 
 
2394
  }
2395
 
2396
  .link-action-btn {
2397
+ width: 32px;
2398
+ height: 32px;
2399
+ border-radius: 8px;
2400
+ border: 1px solid #e2e8f0;
2401
+ background: #ffffff;
2402
+ color: #64748b;
2403
  display: flex;
2404
  align-items: center;
2405
  justify-content: center;
 
 
 
 
 
 
 
 
2406
  cursor: pointer;
2407
+ transition: all 0.2s ease;
 
2408
  }
2409
 
2410
  .link-action-btn:hover {
2411
+ background: #f8fafc;
2412
+ color: #1e293b;
2413
+ border-color: #cbd5e1;
2414
  }
2415
 
2416
+ .link-action-btn.delete-btn:hover {
2417
+ background: #fef2f2;
2418
+ color: #ef4444;
2419
+ border-color: #fecaca;
2420
+ }
2421
+
2422
+ .btn-visit {
2423
+ display: inline-flex;
2424
+ align-items: center;
2425
+ gap: 6px;
2426
+ padding: 8px 16px;
2427
+ background: var(--primary-color);
2428
+ color: #ffffff;
2429
+ border-radius: 10px;
2430
+ font-size: 13px;
2431
+ font-weight: 600;
2432
+ text-decoration: none;
2433
+ transition: all 0.2s ease;
2434
+ box-shadow: 0 4px 12px rgba(16, 185, 129, 0.15);
2435
+ }
2436
+
2437
+ .btn-visit:hover {
2438
+ background: var(--primary-hover);
2439
+ transform: translateY(-1px);
2440
+ box-shadow: 0 6px 16px rgba(16, 185, 129, 0.25);
2441
  }
2442
 
2443
  .links-empty {
 
2446
  flex-direction: column;
2447
  align-items: center;
2448
  justify-content: center;
2449
+ padding: 60px 20px;
2450
  text-align: center;
2451
+ color: #64748b;
 
2452
  }
2453
 
2454
  .links-empty-illustration {
2455
+ width: 80px;
2456
+ height: 80px;
2457
+ background: #f1f5f9;
2458
+ border-radius: 24px;
2459
  display: flex;
2460
  align-items: center;
2461
  justify-content: center;
2462
+ font-size: 40px;
2463
+ color: #94a3b8;
2464
+ margin-bottom: 24px;
 
 
 
 
 
 
 
2465
  }
2466
 
2467
  .links-empty h3 {
2468
+ font-size: 20px;
2469
  font-weight: 700;
2470
+ color: #1e293b;
2471
+ margin-bottom: 8px;
 
2472
  }
2473
 
2474
  .links-empty p {
2475
+ font-size: 15px;
2476
+ max-width: 320px;
2477
+ margin-bottom: 24px;
2478
+ line-height: 1.6;
2479
+ }
2480
+
2481
+ .btn-link-secondary {
2482
+ padding: 12px 24px;
2483
+ border-radius: 12px;
2484
+ font-weight: 600;
2485
  }
2486
 
2487
  .input-group textarea {