gh-here 1.0.5 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,7 +19,8 @@
19
19
  "Bash(git push:*)",
20
20
  "Bash(git pull:*)",
21
21
  "Bash(npm publish:*)",
22
- "Bash(timeout:*)"
22
+ "Bash(timeout:*)",
23
+ "Bash(npm version:*)"
23
24
  ],
24
25
  "deny": [],
25
26
  "ask": []
package/README.md CHANGED
@@ -29,11 +29,12 @@ Navigate to any directory and run:
29
29
  ```bash
30
30
  gh-here # Start server on available port
31
31
  gh-here --open # Start server and open browser
32
+ gh-here --port=8080 # Start server on port 8080
32
33
  gh-here --open --browser=safari # Start server and open in Safari
33
34
  gh-here --open --browser=arc # Start server and open in Arc
34
35
  ```
35
36
 
36
- The app will automatically find an available port starting from 3000 and serve your current directory with a GitHub-like interface.
37
+ The app will automatically find an available port starting from 5555 and serve your current directory with a GitHub-like interface.
37
38
 
38
39
  ## Features
39
40
 
@@ -46,12 +47,13 @@ The app will automatically find an available port starting from 3000 and serve y
46
47
  - File and folder creation, editing, renaming, and deletion
47
48
 
48
49
  ### 🎨 Code Viewing & Editing
49
- - GitHub-accurate syntax highlighting for 25+ languages
50
- - Line numbers with GitHub-style selection (click, shift-click, ctrl-click)
51
- - In-browser file editing with auto-save to localStorage
50
+ - VS Code-quality Monaco Editor with advanced syntax highlighting for 30+ languages
51
+ - GitHub-style line numbers with selection (click, shift-click, ctrl-click)
52
+ - Professional in-browser file editing with auto-save to localStorage
53
+ - Draft management with persistence across sessions
52
54
  - Raw and rendered markdown views
53
55
  - Shareable URLs with line selections (`#L10-L20`)
54
- - Syntax highlighting and line numbers in editor
56
+ - Monaco Editor features: IntelliSense, bracket matching, folding
55
57
 
56
58
  ### 🔀 Git Integration
57
59
  - Automatic git repository detection
@@ -86,44 +88,9 @@ The app will automatically find an available port starting from 3000 and serve y
86
88
  - Error handling and loading states
87
89
  - Notification system for user feedback
88
90
 
89
- ## Supported File Types
90
-
91
- ### Programming Languages
92
- - JavaScript (.js, .mjs, .jsx) - React, Node.js
93
- - TypeScript (.ts, .tsx)
94
- - Python (.py)
95
- - Java (.java)
96
- - Go (.go)
97
- - Rust (.rs)
98
- - PHP (.php)
99
- - Ruby (.rb)
100
- - Swift (.swift)
101
- - Kotlin (.kt)
102
- - Dart (.dart)
103
-
104
- ### Web Technologies
105
- - HTML (.html)
106
- - CSS (.css, .scss, .sass, .less)
107
- - JSON (.json)
108
- - XML (.xml)
109
- - YAML (.yml, .yaml)
110
-
111
- ### Documentation & Config
112
- - Markdown (.md) - with beautiful rendering
113
- - Text files (.txt)
114
- - Configuration files (ESLint, Prettier, Webpack, etc.)
115
- - Docker files (Dockerfile, docker-compose.yml)
116
- - Environment files (.env)
117
-
118
- ### Media & Archives
119
- - Images (.png, .jpg, .gif, .svg, .webp)
120
- - Videos (.mp4, .mov, .avi)
121
- - Audio (.mp3, .wav, .flac)
122
- - Archives (.zip, .tar, .gz, .rar)
123
-
124
- ### Shell & Database
125
- - Shell scripts (.sh, .bash, .zsh)
126
- - SQL (.sql)
91
+ ## Language Support
92
+
93
+ Supports syntax highlighting for 30+ languages including JavaScript, TypeScript, Python, Go, Rust, Java, C/C++, and many more through Monaco Editor integration.
127
94
 
128
95
  ## Keyboard Shortcuts
129
96
 
@@ -161,7 +128,7 @@ npm install
161
128
  npm start
162
129
  ```
163
130
 
164
- Navigate to `http://localhost:3000` to view the interface.
131
+ Navigate to `http://localhost:5555` to view the interface.
165
132
 
166
133
  ## Dependencies
167
134
 
package/lib/renderers.js CHANGED
@@ -13,8 +13,9 @@ const { getGitStatusIcon, getGitStatusDescription } = require('./git');
13
13
  * Handles all HTML template generation for different views
14
14
  */
15
15
 
16
- function renderDirectory(currentPath, items, showGitignored = false, gitBranch = null, gitStatus = {}) {
17
- const breadcrumbs = generateBreadcrumbs(currentPath, gitBranch);
16
+ function renderDirectory(currentPath, items, showGitignored = false, gitBranch = null, gitStatus = {}, workingDir = null) {
17
+ const workingDirName = workingDir ? path.basename(workingDir) : null;
18
+ const breadcrumbs = generateBreadcrumbs(currentPath, gitBranch, workingDirName);
18
19
  const readmeFile = findReadmeFile(items);
19
20
  const readmePreview = readmeFile ? generateReadmePreview(currentPath, readmeFile) : '';
20
21
  const languageStats = generateLanguageStats(items);
@@ -22,7 +23,7 @@ function renderDirectory(currentPath, items, showGitignored = false, gitBranch =
22
23
  const itemsHtml = items.map(item => `
23
24
  <tr class="file-row" data-name="${item.name.toLowerCase()}" data-type="${item.isDirectory ? 'dir' : 'file'}" data-path="${item.path}">
24
25
  <td class="icon">
25
- ${item.isDirectory ? octicons['file-directory'].toSVG({ class: 'octicon-directory' }) : getFileIcon(item.name)}
26
+ ${item.isDirectory ? octicons['file-directory-fill'].toSVG({ class: 'octicon-directory' }) : getFileIcon(item.name)}
26
27
  </td>
27
28
  <td class="git-status-col">
28
29
  ${item.gitStatus ? (item.gitStatus.status === '??' ? `<span class="git-status git-status-untracked" title="Untracked file">${require('./git').getGitStatusIcon('??')}</span>` : `<span class="git-status git-status-${item.gitStatus.status.replace(' ', '')}" title="Git Status: ${getGitStatusDescription(item.gitStatus.status)}">${getGitStatusIcon(item.gitStatus.status)}</span>`) : ''}
@@ -78,13 +79,9 @@ function renderDirectory(currentPath, items, showGitignored = false, gitBranch =
78
79
  <header>
79
80
  <div class="header-content">
80
81
  <div class="header-left">
81
- <h1 class="header-path">${breadcrumbs}</h1>
82
+ <h1>gh-here</h1>
82
83
  </div>
83
84
  <div class="header-right">
84
- <div class="search-container">
85
- ${octicons.search.toSVG({ class: 'search-icon' })}
86
- <input type="text" id="file-search" placeholder="Find files..." class="search-input">
87
- </div>
88
85
  ${Object.keys(gitStatus).length > 0 ? `
89
86
  <button id="commit-btn" class="commit-btn" title="Commit changes">
90
87
  ${octicons['git-commit'].toSVG({ class: 'commit-icon' })}
@@ -100,15 +97,42 @@ function renderDirectory(currentPath, items, showGitignored = false, gitBranch =
100
97
  </div>
101
98
  </div>
102
99
  </header>
103
- <main>
104
- ${languageStats}
105
- <div class="directory-actions">
106
- <button id="new-file-btn" class="btn btn-secondary">
107
- ${octicons['file-added'].toSVG({ class: 'btn-icon' })} New file
108
- </button>
100
+
101
+ <!-- White canvas section like GitHub -->
102
+ <div class="repo-canvas">
103
+ <div class="repo-canvas-content">
104
+ <div class="breadcrumb-section">${breadcrumbs}</div>
105
+ <hr class="repo-divider">
106
+
107
+ <div class="repo-controls">
108
+ <div class="repo-controls-left">
109
+ ${gitBranch ? `
110
+ <button class="branch-button">
111
+ ${octicons['git-branch'].toSVG({ class: 'octicon-branch' })}
112
+ <span class="branch-name">${gitBranch}</span>
113
+ ${octicons['chevron-down'].toSVG({ class: 'octicon-chevron' })}
114
+ </button>
115
+ ` : ''}
116
+ </div>
117
+ <div class="repo-controls-right">
118
+ <div class="search-container">
119
+ ${octicons.search.toSVG({ class: 'search-icon' })}
120
+ <input type="text" id="file-search" placeholder="Go to file" class="search-input">
121
+ <kbd class="search-hotkey">t</kbd>
122
+ </div>
123
+ <button id="new-file-btn" class="btn btn-outline">
124
+ <span class="btn-text">New file</span>
125
+ </button>
126
+ </div>
127
+ </div>
109
128
  </div>
110
- <div class="file-table-container">
111
- <table class="file-table" id="file-table">
129
+ </div>
130
+ <main>
131
+ <div class="repo-canvas">
132
+ <div class="repo-canvas-content">
133
+ ${languageStats}
134
+ <div class="file-table-container">
135
+ <table class="file-table" id="file-table">
112
136
  <thead>
113
137
  <tr>
114
138
  <th></th>
@@ -133,8 +157,10 @@ function renderDirectory(currentPath, items, showGitignored = false, gitBranch =
133
157
  ${itemsHtml}
134
158
  </tbody>
135
159
  </table>
160
+ </div>
161
+ ${readmePreview}
162
+ </div>
136
163
  </div>
137
- ${readmePreview}
138
164
  </main>
139
165
  </body>
140
166
  </html>
@@ -265,7 +291,7 @@ async function renderFileDiff(filePath, ext, gitInfo, gitRepoRoot) {
265
291
  <header>
266
292
  <div class="header-content">
267
293
  <div class="header-left">
268
- <h1 class="header-path">${breadcrumbs}</h1>
294
+ <h1>gh-here</h1>
269
295
  </div>
270
296
  <div class="header-right">
271
297
  ${viewToggle}
@@ -276,9 +302,12 @@ async function renderFileDiff(filePath, ext, gitInfo, gitRepoRoot) {
276
302
  </div>
277
303
  </header>
278
304
  <main>
279
- <div class="diff-container">
280
- <div class="diff-content">
281
- ${diffContent}
305
+ <div class="main-content">
306
+ <div class="breadcrumb-section">${breadcrumbs}</div>
307
+ <div class="diff-container">
308
+ <div class="diff-content">
309
+ ${diffContent}
310
+ </div>
282
311
  </div>
283
312
  </div>
284
313
  </main>
@@ -433,10 +462,7 @@ async function renderFile(filePath, content, ext, viewMode = 'rendered', gitStat
433
462
  <header>
434
463
  <div class="header-content">
435
464
  <div class="header-left">
436
- <h1 class="header-path">
437
- ${breadcrumbs}
438
- ${hasGitChanges ? (hasGitChanges.status === '??' ? `<span class="git-status git-status-untracked" title="Untracked file">${getGitStatusIcon('??')}</span>` : `<span class="git-status git-status-${hasGitChanges.status.replace(' ', '')}" title="Git Status: ${getGitStatusDescription(hasGitChanges.status)}">${getGitStatusIcon(hasGitChanges.status)}</span>`) : ''}
439
- </h1>
465
+ <h1>gh-here</h1>
440
466
  </div>
441
467
  <div class="header-right">
442
468
  <div id="filename-input-container" class="filename-input-container" style="display: none;">
@@ -453,9 +479,11 @@ async function renderFile(filePath, content, ext, viewMode = 'rendered', gitStat
453
479
  </div>
454
480
  </header>
455
481
  <main>
456
- <div class="file-content">
457
- ${displayContent}
458
- </div>
482
+ <div class="main-content">
483
+ <div class="breadcrumb-section">${breadcrumbs}</div>
484
+ <div class="file-content">
485
+ ${displayContent}
486
+ </div>
459
487
  <div id="editor-container" class="editor-container" style="display: none;">
460
488
  <div class="editor-header">
461
489
  <div class="editor-title">Edit ${path.basename(filePath)}</div>
@@ -469,6 +497,7 @@ async function renderFile(filePath, content, ext, viewMode = 'rendered', gitStat
469
497
  <div id="file-editor" class="monaco-editor"></div>
470
498
  </div>
471
499
  </div>
500
+ </div>
472
501
  </main>
473
502
  </body>
474
503
  </html>
@@ -492,7 +521,7 @@ function renderNewFile(currentPath) {
492
521
  <header>
493
522
  <div class="header-content">
494
523
  <div class="header-left">
495
- <h1 class="header-path">${breadcrumbs}</h1>
524
+ <h1>gh-here</h1>
496
525
  </div>
497
526
  <div class="header-right">
498
527
  <button id="theme-toggle" class="theme-toggle" aria-label="Toggle theme">
@@ -502,8 +531,10 @@ function renderNewFile(currentPath) {
502
531
  </div>
503
532
  </header>
504
533
  <main>
505
- <div class="new-file-container">
506
- <div class="new-file-header">
534
+ <div class="main-content">
535
+ <div class="breadcrumb-section">${breadcrumbs}</div>
536
+ <div class="new-file-container">
537
+ <div class="new-file-header">
507
538
  <div class="filename-section">
508
539
  <span class="filename-label">Name your file...</span>
509
540
  <input type="text" id="new-filename-input" class="new-filename-input" placeholder="README.md" autofocus>
@@ -519,24 +550,26 @@ function renderNewFile(currentPath) {
519
550
  </div>
520
551
  </div>
521
552
  </div>
553
+ </div>
522
554
  </main>
523
555
  </body>
524
556
  </html>
525
557
  `;
526
558
  }
527
559
 
528
- function generateBreadcrumbs(currentPath, gitBranch = null) {
529
- // At root, show gh-here branding with git branch if available
560
+ function generateBreadcrumbs(currentPath, gitBranch = null, workingDirName = null) {
561
+ const rootDisplayName = workingDirName || 'repository';
562
+
563
+ // At root, show working directory name
530
564
  if (!currentPath || currentPath === '.') {
531
- const gitBranchDisplay = gitBranch ? `<span class="git-branch">${octicons['git-branch'].toSVG({ class: 'octicon-branch' })} ${gitBranch}</span>` : '';
532
- return `${octicons.home.toSVG({ class: 'octicon-home' })} gh-here ${gitBranchDisplay}`;
565
+ return `${octicons.home.toSVG({ class: 'octicon-home' })} ${rootDisplayName}`;
533
566
  }
534
567
 
535
568
  // In subdirectories, show clickable path
536
569
  const parts = currentPath.split('/').filter(p => p && p !== '.');
537
570
  let breadcrumbs = `
538
571
  <div class="breadcrumb-item">
539
- <a href="/">${octicons.home.toSVG({ class: 'octicon-home' })}</a>
572
+ <a href="/">${octicons.home.toSVG({ class: 'octicon-home' })} ${rootDisplayName}</a>
540
573
  </div>
541
574
  `;
542
575
  let buildPath = '';
package/lib/server.js CHANGED
@@ -82,7 +82,7 @@ function setupRoutes(app, workingDir, isGitRepo, gitRepoRoot) {
82
82
  return a.name.localeCompare(b.name);
83
83
  });
84
84
 
85
- res.send(renderDirectory(currentPath, items, showGitignored, gitBranch, gitStatus));
85
+ res.send(renderDirectory(currentPath, items, showGitignored, gitBranch, gitStatus, workingDir));
86
86
  } else {
87
87
  const content = fs.readFileSync(fullPath, 'utf8');
88
88
  const ext = path.extname(fullPath).slice(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gh-here",
3
- "version": "1.0.5",
3
+ "version": "1.1.0",
4
4
  "description": "A local GitHub-like file browser for viewing code",
5
5
  "repository": "https://github.com/corywilkerson/gh-here",
6
6
  "main": "index.js",
package/public/styles.css CHANGED
@@ -52,15 +52,15 @@ body {
52
52
  header {
53
53
  background-color: var(--bg-secondary);
54
54
  border-bottom: 1px solid var(--border-primary);
55
- padding: 16px 24px;
56
55
  }
57
56
 
58
57
  .header-content {
59
58
  display: flex;
60
59
  justify-content: space-between;
61
60
  align-items: flex-start;
62
- max-width: 1200px;
61
+ max-width: 900px;
63
62
  margin: 0 auto;
63
+ padding: 16px 24px;
64
64
  }
65
65
 
66
66
  .header-left h1 {
@@ -82,6 +82,203 @@ header {
82
82
  gap: 12px;
83
83
  }
84
84
 
85
+ /* GitHub-style White Canvas Section */
86
+ .repo-canvas {
87
+ background-color: var(--bg-primary);
88
+ }
89
+
90
+ .repo-canvas-content {
91
+ max-width: 900px;
92
+ margin: 0 auto;
93
+ padding: 16px 24px;
94
+ }
95
+
96
+ .breadcrumb-section {
97
+ font-size: 20px;
98
+ font-weight: 600;
99
+ color: var(--text-primary);
100
+ margin: 0 0 12px 0;
101
+ display: flex;
102
+ align-items: center;
103
+ flex-wrap: wrap;
104
+ }
105
+
106
+ .repo-name {
107
+ font-size: 20px;
108
+ font-weight: 600;
109
+ color: var(--text-primary);
110
+ margin: 0 0 12px 0;
111
+ }
112
+
113
+ .repo-divider {
114
+ border: none;
115
+ border-top: 1px solid var(--border-primary);
116
+ margin: 0 0 12px 0;
117
+ }
118
+
119
+ .repo-controls {
120
+ display: flex;
121
+ align-items: center;
122
+ justify-content: space-between;
123
+ }
124
+
125
+ .repo-controls-left {
126
+ display: flex;
127
+ align-items: center;
128
+ }
129
+
130
+ .repo-controls-right {
131
+ display: flex;
132
+ align-items: center;
133
+ gap: 12px;
134
+ }
135
+
136
+ .branch-button {
137
+ display: flex;
138
+ align-items: center;
139
+ gap: 6px;
140
+ padding: 5px 12px;
141
+ background: var(--bg-primary);
142
+ border: 1px solid var(--border-primary);
143
+ border-radius: 6px;
144
+ color: var(--text-primary);
145
+ font-size: 14px;
146
+ font-weight: 500;
147
+ cursor: pointer;
148
+ transition: all 0.2s ease;
149
+ }
150
+
151
+ .branch-button:hover {
152
+ background: var(--bg-secondary);
153
+ border-color: var(--text-secondary);
154
+ }
155
+
156
+ .branch-count,
157
+ .tag-count {
158
+ color: var(--text-secondary);
159
+ font-size: 14px;
160
+ display: flex;
161
+ align-items: center;
162
+ gap: 6px;
163
+ }
164
+
165
+ .octicon-branch {
166
+ width: 16px;
167
+ height: 16px;
168
+ fill: var(--text-secondary);
169
+ }
170
+
171
+ .octicon-small {
172
+ width: 14px;
173
+ height: 14px;
174
+ fill: var(--text-secondary);
175
+ }
176
+
177
+ .branch-name {
178
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo, monospace;
179
+ font-weight: 600;
180
+ }
181
+
182
+ .octicon-chevron {
183
+ width: 12px;
184
+ height: 12px;
185
+ fill: var(--text-secondary);
186
+ }
187
+
188
+ .search-container {
189
+ position: relative;
190
+ display: flex;
191
+ align-items: center;
192
+ }
193
+
194
+ .search-input {
195
+ background: var(--bg-primary);
196
+ border: 1px solid var(--border-primary);
197
+ border-radius: 6px;
198
+ padding: 6px 40px 6px 32px;
199
+ color: var(--text-primary);
200
+ font-size: 14px;
201
+ width: 300px;
202
+ }
203
+
204
+ .search-input:focus {
205
+ outline: none;
206
+ border-color: #0969da;
207
+ box-shadow: 0 0 0 3px rgba(9, 105, 218, 0.3);
208
+ }
209
+
210
+ .search-icon {
211
+ position: absolute;
212
+ left: 8px;
213
+ width: 16px;
214
+ height: 16px;
215
+ fill: var(--text-secondary);
216
+ pointer-events: none;
217
+ }
218
+
219
+ .search-hotkey {
220
+ position: absolute;
221
+ right: 8px;
222
+ background: var(--bg-tertiary);
223
+ border: 1px solid var(--border-primary);
224
+ border-radius: 3px;
225
+ padding: 2px 6px;
226
+ font-size: 12px;
227
+ color: var(--text-secondary);
228
+ font-family: ui-monospace, SFMono-Regular, monospace;
229
+ }
230
+
231
+ /* GitHub-style Buttons */
232
+ .btn {
233
+ display: flex;
234
+ align-items: center;
235
+ gap: 6px;
236
+ padding: 6px 12px;
237
+ border-radius: 6px;
238
+ font-size: 14px;
239
+ font-weight: 500;
240
+ cursor: pointer;
241
+ transition: all 0.2s ease;
242
+ border: 1px solid;
243
+ }
244
+
245
+ .btn-primary {
246
+ background: var(--bg-primary);
247
+ border-color: var(--border-primary);
248
+ color: var(--text-primary);
249
+ }
250
+
251
+ .btn-primary:hover {
252
+ background: var(--bg-secondary);
253
+ }
254
+
255
+ .btn-outline {
256
+ background: var(--bg-primary);
257
+ border-color: var(--border-primary);
258
+ color: var(--text-primary);
259
+ }
260
+
261
+ .btn-outline:hover {
262
+ background: var(--bg-secondary);
263
+ }
264
+
265
+ .btn-success {
266
+ background: #238636;
267
+ border-color: rgba(240, 246, 252, 0.1);
268
+ color: #ffffff;
269
+ }
270
+
271
+ .btn-success:hover {
272
+ background: #2ea043;
273
+ }
274
+
275
+ .btn-icon,
276
+ .btn-chevron {
277
+ width: 16px;
278
+ height: 16px;
279
+ fill: currentColor;
280
+ }
281
+
85
282
  .theme-toggle,
86
283
  .gitignore-toggle,
87
284
  .edit-btn {
@@ -158,7 +355,7 @@ header {
158
355
  }
159
356
 
160
357
  .breadcrumb-item {
161
- display: flex;
358
+ display: inline-flex;
162
359
  align-items: center;
163
360
  }
164
361
 
@@ -184,9 +381,13 @@ header {
184
381
  }
185
382
 
186
383
  main {
187
- padding: 24px;
188
- max-width: 1200px;
384
+ padding: 0;
385
+ }
386
+
387
+ .main-content {
388
+ max-width: 900px;
189
389
  margin: 0 auto;
390
+ padding: 16px 24px;
190
391
  }
191
392
 
192
393
  .directory-actions {
@@ -261,13 +462,13 @@ main {
261
462
  vertical-align: text-bottom;
262
463
  }
263
464
 
264
- /* GitHub-style blue folder icons */
465
+ /* GitHub-style baby blue folder icons */
265
466
  .octicon-directory {
266
- fill: #58a6ff;
467
+ fill: #7dd3fc;
267
468
  }
268
469
 
269
470
  [data-theme="light"] .octicon-directory {
270
- fill: #0969da;
471
+ fill: #54adf5;
271
472
  }
272
473
 
273
474
  .octicon-home {
@@ -296,43 +497,7 @@ main {
296
497
  [data-theme="light"] .text-orange { color: #bc4c00; }
297
498
  [data-theme="light"] .text-purple { color: #6f42c1; }
298
499
 
299
- /* Search functionality */
300
- .search-container {
301
- position: relative;
302
- display: flex;
303
- align-items: center;
304
- background: var(--bg-primary);
305
- border: 1px solid var(--border-primary);
306
- border-radius: 6px;
307
- padding: 6px 8px;
308
- transition: all 0.2s ease;
309
- }
310
-
311
- .search-container:focus-within {
312
- border-color: var(--link-color);
313
- box-shadow: 0 0 0 2px rgba(88, 166, 255, 0.1);
314
- }
315
-
316
- .search-icon {
317
- width: 16px;
318
- height: 16px;
319
- fill: var(--text-secondary);
320
- margin-right: 6px;
321
- }
322
-
323
- .search-input {
324
- background: none;
325
- border: none;
326
- outline: none;
327
- color: var(--text-primary);
328
- font-size: 14px;
329
- width: 200px;
330
- transition: all 0.2s ease;
331
- }
332
-
333
- .search-input::placeholder {
334
- color: var(--text-secondary);
335
- }
500
+ /* Old search styles removed - using new GitHub-style search */
336
501
 
337
502
  /* Language stats */
338
503
  .language-stats {
@@ -451,9 +616,6 @@ main {
451
616
 
452
617
 
453
618
  /* Loading states */
454
- .search-input:focus {
455
- width: 250px;
456
- }
457
619
 
458
620
  /* Quick actions */
459
621
  .name {
@@ -1109,8 +1271,18 @@ main {
1109
1271
 
1110
1272
 
1111
1273
  @media (max-width: 768px) {
1112
- main {
1113
- padding: 16px;
1274
+ .main-content {
1275
+ padding: 12px 16px;
1276
+ }
1277
+
1278
+ .repo-canvas-content {
1279
+ padding: 12px 16px;
1280
+ }
1281
+
1282
+ .header-content {
1283
+ padding: 12px 16px;
1284
+ flex-direction: column;
1285
+ gap: 12px;
1114
1286
  }
1115
1287
 
1116
1288
  .file-table .size,
@@ -1118,13 +1290,15 @@ main {
1118
1290
  display: none;
1119
1291
  }
1120
1292
 
1121
- header {
1122
- padding: 12px 16px;
1293
+ .repo-controls {
1294
+ flex-direction: column;
1295
+ gap: 12px;
1296
+ align-items: stretch;
1123
1297
  }
1124
1298
 
1125
- .header-content {
1299
+ .repo-controls-right {
1126
1300
  flex-direction: column;
1127
- gap: 12px;
1301
+ gap: 8px;
1128
1302
  }
1129
1303
 
1130
1304
  .header-right {
@@ -1331,22 +1505,8 @@ main {
1331
1505
  transform: translateY(0);
1332
1506
  }
1333
1507
  }
1334
- }
1335
- /* Git Integration */
1336
- .git-branch {
1337
- display: inline-flex;
1338
- align-items: center;
1339
- margin-left: 12px;
1340
- color: var(--text-secondary);
1341
- font-size: 14px;
1342
- font-weight: 500;
1343
- gap: 6px;
1344
- }
1345
1508
 
1346
- .octicon-branch {
1347
- width: 16px;
1348
- height: 16px;
1349
- }
1509
+ /* Git Integration */
1350
1510
 
1351
1511
  .git-status {
1352
1512
  display: inline;