-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbackup_data.json
More file actions
484 lines (484 loc) · 97 KB
/
backup_data.json
File metadata and controls
484 lines (484 loc) · 97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
{
"languages": [
{
"id": 1,
"name": "CSS"
},
{
"id": 2,
"name": "HTML"
},
{
"id": 3,
"name": "JavaScript"
},
{
"id": 4,
"name": "JSON"
},
{
"id": 5,
"name": "Python"
},
{
"id": 6,
"name": "React"
},
{
"id": 7,
"name": "Regex"
},
{
"id": 8,
"name": "SQL"
},
{
"id": 9,
"name": "Terminal"
},
{
"id": 10,
"name": "Xml"
}
],
"categories": [
{
"id": 1,
"name": "Arrays"
},
{
"id": 2,
"name": "Classes"
},
{
"id": 3,
"name": "Curl"
},
{
"id": 4,
"name": "Functions"
},
{
"id": 5,
"name": "Images"
},
{
"id": 6,
"name": "Loops"
},
{
"id": 7,
"name": "Manipulation"
},
{
"id": 8,
"name": "Methods"
},
{
"id": 9,
"name": "Startup"
},
{
"id": 10,
"name": "Filters"
},
{
"id": 11,
"name": "Components"
}
],
"cheats": [
{
"title": "New Vite React Project",
"code": "npm create vite@latest client -- --template react\ncd client\nnpm install\nnpm install react-router-dom lucide-react",
"notes": "Executed from existing client folder with router and lucide",
"language_id": 9,
"category_id": 9
},
{
"title": "Initial and Use Migration",
"code": "flask db init\nflask db migrate -m \"initial migration\"\nflask db upgrade",
"notes": "First time setup: init creates migrations folder. After changing models: migrate creates migration file. upgrade applies changes to database. Run from server directory.",
"language_id": 9,
"category_id": 9
},
{
"title": "Flask GET Route with jsonify",
"code": "@app.route('/cheats', methods=['GET'])\ndef get_cheats():\n cheats = Cheat.query.all()\n return jsonify([cheat.to_dict() for cheat in cheats]), 200",
"notes": "Standard Flask route decorator. Query all cheats from database. Use list comprehension with to_dict() to serialize. jsonify converts to JSON response. Returns 200 status. Use when not using Flask-RESTful.",
"language_id": 5,
"category_id": 8
},
{
"title": "React Router Setup in main.jsx",
"code": "import { createRoot } from 'react-dom/client'\nimport { createBrowserRouter, RouterProvider } from 'react-router-dom'\nimport { routes } from './routes.jsx'\nimport './index.css'\n\nconst router = createBrowserRouter(routes)\n\nconst root = createRoot(document.getElementById('root'))\nroot.render(<RouterProvider router={router} />)",
"notes": "Entry point for React app with React Router. Import routes from separate file. createBrowserRouter sets up routing. RouterProvider wraps app with router. Renders into root div.",
"language_id": 6,
"category_id": 9
},
{
"title": "Vite Proxy Configuration",
"code": "import { defineConfig } from \"vite\";\nimport react from \"@vitejs/plugin-react\";\n\nexport default defineConfig({\n plugins: [react()],\n server: {\n proxy: {\n \"/api\": {\n target: \"http://localhost:5555\",\n changeOrigin: true,\n },\n },\n },\n});\n",
"notes": "Proxies /api requests to Flask backend at port 5555. Change target port if Flask runs on different port (like 5000). rewrite strips /api prefix before sending to Flask. Good for all React + Flask projects. Avoids CORS issues in development.",
"language_id": 3,
"category_id": 9
},
{
"title": "Create React Context",
"code": "import { createContext } from \"react\";\n\nexport const AuthContext = createContext();",
"notes": "Creates context object for sharing state across components. Export to use in provider and custom hook. Holds no initial value - provider will supply values. Import in provider file and custom hook.",
"language_id": 6,
"category_id": 9
},
{
"title": "React Router Routes Setup",
"code": "import App from \"./App.jsx\";\nimport { ErrorPage } from \"./pages/ErrorPage.jsx\";\nimport { HomePage } from \"./pages/HomePage.jsx\";\nimport { ProtectedRoute } from \"./components/ProtectedRoute.jsx\";\n\nexport const routes = [\n {\n path: \"/\",\n element: (\n <ProtectedRoute>\n <App />\n </ProtectedRoute>\n ),\n errorElement: <ErrorPage />,\n children: [\n {\n index: true,\n element: <HomePage />,\n },\n ],\n },\n];\n",
"notes": "Exports routes array for React Router. Sets App as root with ErrorPage fallback. Children array holds nested routes. Wrap protected routes in ProtectedRoute component. Add more route objects for login, signup, etc.",
"language_id": 6,
"category_id": 9
},
{
"title": "Protected Route Component",
"code": "import { Navigate } from 'react-router-dom';\nimport { useAuth } from '../hooks/useAuth';\n\nexport function ProtectedRoute({ children }) {\n const { loggedIn, loading } = useAuth();\n \n if (loading) return <div>Loading...</div>;\n if (!loggedIn) return <Navigate to=\"/login\" replace />;\n \n return children;\n}",
"notes": "Wraps routes that require authentication. Checks loading state first to avoid flash redirects. Redirects to login if not logged in. Returns children if authenticated. Use in routes.jsx to protect pages.",
"language_id": 6,
"category_id": 11
},
{
"title": "Basic Error Page Component",
"code": "import { useRouteError, useNavigate } from \"react-router-dom\";\n\nexport function ErrorPage() {\n const error = useRouteError();\n const navigate = useNavigate();\n\n return (\n <div className=\"error-container\">\n <h1>Oops!</h1>\n <p>Sorry, an unexpected error has occurred.</p>\n <p><i>{error.statusText || error.message}</i></p>\n <button onClick={() => navigate('/')}>Go Home</button>\n </div>\n );\n}",
"notes": "Catches routing errors with useRouteError hook. Displays error message and Go Home button. Set as errorElement in routes. Logs error to console for debugging.",
"language_id": 6,
"category_id": 11
},
{
"title": "Flask Extensions File",
"code": "from flask_sqlalchemy import SQLAlchemy\nfrom flask_migrate import Migrate\nfrom flask_bcrypt import Bcrypt\nfrom flask_cors import CORS\n\ndb = SQLAlchemy()\nmigrate = Migrate()\nbcrypt = Bcrypt()\ncors = CORS()",
"notes": "Centralized file for Flask extensions. Import extensions here, initialize in create_app(). Avoids circular imports. Import db in models and routes. Import bcrypt for password hashing.",
"language_id": 5,
"category_id": 9
},
{
"title": "Flask Configuration File",
"code": "import os\n\nclass Config:\n SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URI', 'sqlite:///app.db')\n SQLALCHEMY_TRACK_MODIFICATIONS = False\n SECRET_KEY = os.getenv('SECRET_KEY', 'dev-secret-key-change-in-production')",
"notes": "Configuration class for Flask settings. Database URI defaults to SQLite. SECRET_KEY for sessions and security. SQLALCHEMY_TRACK_MODIFICATIONS False saves memory. Import in create_app with app.config.from_object(Config).",
"language_id": 5,
"category_id": 9
},
{
"title": "Flask Run File",
"code": "from app import create_app\n\napp = create_app()\n\nif __name__ == '__main__':\n app.run(port=5555, debug=True)",
"notes": "Entry point to run Flask app. Imports create_app factory function. Runs on port 5555 with debug mode. Execute with python run.py from server directory. Change port to match vite.config proxy.",
"language_id": 5,
"category_id": 9
},
{
"title": "Basic App Component with Auth Provider",
"code": "import { Outlet } from \"react-router-dom\";\nimport { AuthProvider } from \"./providers/AuthProvider\";\nimport { NavBar } from \"./components/NavBar\";\n\nfunction App() {\n return (\n <>\n <AuthProvider>\n <header>\n <NavBar />\n </header>\n <main>\n <Outlet />\n </main>\n </AuthProvider>\n </>\n );\n}\n\nexport default App;",
"notes": "Root App component wrapped in AuthProvider for global auth state. Outlet renders child routes from routes.jsx. Remove extra fragments - AuthProvider can be direct parent. Add more providers here if needed for global state.",
"language_id": 6,
"category_id": 9
},
{
"title": "Flask Requirements.txt Template",
"code": "annotated-doc==0.0.4\nannotated-types==0.7.0\nanyio==4.12.1\nasgiref==3.11.0\nbcrypt==5.0.0\nblinker==1.9.0\ncharset-normalizer==3.4.4\nclick==8.3.1\ndj-database-url==3.1.0\nDjango==6.0.1\ndnspython==2.8.0\nemail-validator==2.3.0\nFaker==40.1.2\nfastapi==0.128.0\nFlask==3.1.2\nh11==0.16.0\nidna==3.11\nitsdangerous==2.2.0\nJinja2==3.1.6\nMarkupSafe==3.0.3\npeewee==3.19.0\npillow==12.1.0\npsycopg2-binary==2.9.11\npydantic==2.12.5\npydantic-settings==2.6.1\npydantic_core==2.41.5\nPygments==2.19.2\nPyJWT==2.10.1\npython-dotenv==1.2.1\nreportlab==4.4.9\nSQLAlchemy==2.0.46\nsqlite-web==0.6.8\nsqlparse==0.5.5\nstarlette==0.50.0\ntyping-inspection==0.4.2\ntyping_extensions==4.15.0\nuvicorn==0.40.0\nWerkzeug==3.1.5",
"notes": "Standard Flask requirements for full-stack apps. Includes database (SQLAlchemy, Migrate), auth (Bcrypt, JWT), API tools (RESTful, CORS, Marshmallow), and production server (gunicorn). Install with pip install -r requirements.txt. Good starter for all Flask projects.",
"language_id": 9,
"category_id": 9
},
{
"title": "Sort List by Title in React",
"code": "const sortedCheats = [...cheats].sort((a, b) => \n a.title.localeCompare(b.title)\n);",
"notes": "Spread operator creates copy to avoid mutating original array. sort with localeCompare does alphabetical sorting. Use sortedCheats in map instead of cheats. For reverse order use b.title.localeCompare(a.title). Works with any object property.",
"language_id": 6,
"category_id": 1
},
{
"title": "Flask-RESTful GET List Resource",
"code": "class CategoryList(Resource):\n def get(self):\n categories = Category.query.all()\n return [{'id': c.id, 'name': c.name} for c in categories], 200",
"notes": "Flask-RESTful class-based resource. Inherits from Resource. get method returns list of dicts using list comprehension. No jsonify needed - auto converts. Returns tuple with data and status code. Register with api.add_resource(CategoryList, '/categories').",
"language_id": 5,
"category_id": 8
},
{
"title": "Replace Spaces with Underscores (JavaScript)",
"code": "string = 'cheat code app'\nstring.replaceAll(' ', '_')\n\n// Example\nconst title = \"cheat code app\"\nconst formatted = title.replaceAll(' ', '_')",
"notes": "replaceAll method replaces all occurrences. First argument is what to find, second is replacement. Works with any string characters. Can also use replace with regex: replace(/ /g, '_'). Returns new string, doesn't modify original.",
"language_id": 3,
"category_id": 7
},
{
"title": "Replace Spaces with Underscores (Python)",
"code": "string = 'cheat code app'\nstring.replace(' ', '_')\n\n# Example\ntitle = \"cheat code app\"\nformatted = title.replace(' ', '_')",
"notes": "replace method replaces all occurrences by default in Python. First argument is what to find, second is replacement. Works with any string characters. Returns new string, doesn't modify original. No need for replaceAll like JavaScript.",
"language_id": 5,
"category_id": 7
},
{
"title": "Count Spaces in String (JavaScript)",
"code": "// Count all spaces\nstring.split(' ').length - 1\n\n// Example\nconst title = \"cheat code app\"\nconst spaceCount = title.split(' ').length - 1\n// Result: 2",
"notes": "split divides string by spaces into array, subtract 1 from length. Cleaner than match with null check. matchAll with spread operator is modern but overkill for simple counting. split method is most readable and straightforward.",
"language_id": 3,
"category_id": 7
},
{
"title": "Count Spaces in String (Python)",
"code": "# Count all spaces\nstring.count(' ')\n\n# Example\ntitle = \"cheat code app\"\nspace_count = title.count(' ')\n# Result: 2",
"notes": "count method counts occurrences of substring. Pass space character as argument. Returns integer count. Works with any character or substring. Simpler than JavaScript - no regex needed.",
"language_id": 5,
"category_id": 7
},
{
"title": "Basic Email Validation (Python)",
"code": "# Check for @ and dot after @\n'@' in email and '.' in email.split('@')[-1]\n\n# Example\nemail = \"josh@josh.com\"\nis_valid = '@' in email and '.' in email.split('@')[-1]\n# Result: True\n\nbad_email = \"joshjosh.com\"\nis_valid = '@' in bad_email and '.' in bad_email.split('@')[-1]\n# Result: False",
"notes": "in operator checks for @ symbol. Split by @ and check last part has dot. Simple validation - not production-grade. For real validation use regex or email-validator library. Works for basic form checks.",
"language_id": 5,
"category_id": 4
},
{
"title": "Basic Email Validation (JavaScript)",
"code": "// Check for @ and dot after @\nemail.includes('@') && email.split('@')[1]?.includes('.')\n\n// Example with steps\nconst email = \"josh@josh.com\"\nconst parts = email.split('@') // ['josh', 'josh.com']\nconst domain = parts[1] // 'josh.com'\nconst isValid = email.includes('@') && domain?.includes('.')\n// Result: true\n\nconst badEmail = \"joshjosh.com\"\nconst badParts = badEmail.split('@') // ['joshjosh.com']\nconst badDomain = badParts[1] // undefined\nconst isValid = badEmail.includes('@') && badDomain?.includes('.')\n// Result: false",
"notes": "Includes checks for @ symbol. Split by @ creates array of parts. Index [1] gets domain part after @. Optional chaining ?. prevents error if no domain. Simple validation - not production-grade. For real validation use regex or validation library.",
"language_id": 3,
"category_id": 4
},
{
"title": "Email Validation with Regex (JavaScript)",
"code": "// Email regex pattern\nconst emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n\n// Test method\nemailRegex.test(email)\n\n// Example\nconst email = \"josh@josh.com\"\nconst isValid = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)\n// Result: true\n\nconst badEmail = \"josh@josh\"\nconst isValid = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(badEmail)\n// Result: false\n\n// More comprehensive (RFC 5322 compliant)\nconst strictRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/\nconst isValid = strictRegex.test(email)\n\n// Use\nfunction handleSubmit(e) {\n e.preventDefault()\n const email = e.target.email.value\n \n if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) {\n alert('Invalid email')\n return\n }\n}",
"notes": "Basic regex checks: characters before @, characters after @, dot in domain. test method returns true/false. Use in form validation before submit. Regex catches most invalid emails but not all edge cases. For production use validation library like validator.js or email-validator.",
"language_id": 3,
"category_id": 7
},
{
"title": "Email Validation with Regex (Python)",
"code": "import re\n\n# Email regex pattern\nemail_regex = r'^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$'\n\n# Match method\nre.match(email_regex, email)\n\n# Example\nemail = \"josh@josh.com\"\nis_valid = bool(re.match(r'^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$', email))\n# Result: True\n\nbad_email = \"josh@josh\"\nis_valid = bool(re.match(r'^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$', bad_email))\n# Result: False\n\n# More comprehensive\nstrict_regex = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$'\nis_valid = bool(re.match(strict_regex, email))\n\n# Use\n@app.route('/signup', methods=['POST'])\ndef signup():\n email = request.json.get('email')\n \n if not re.match(r'^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$', email):\n return {'error': 'Invalid email'}, 400",
"notes": "Basic regex checks: characters before @, characters after @, dot in domain. re.match returns match object or None. Use in form validation. Regex catches most invalid emails but not all edge cases. For production use validation library like email-validator.",
"language_id": 5,
"category_id": 7
},
{
"title": "Flask Login Resource",
"code": "class Login(Resource):\n def post(self):\n data = request.get_json()\n user = User.query.filter_by(email=data.get('email')).first()\n \n if user and user.authenticate(data.get('password')):\n session['user_id'] = user.id\n return {'id': user.id, 'name': user.name, 'email': user.email}\n \n return {'error': 'Invalid credentials'}, 401",
"notes": "Flask-RESTful login endpoint. Gets JSON data from request body. Queries user by email. Checks password with authenticate method. Stores user_id in session. Returns user data on success or 401 error. Register with api.add_resource(Login, '/login').",
"language_id": 5,
"category_id": 8
},
{
"title": "Flask Logout Resource",
"code": "class Logout(Resource):\n def post(self):\n session.pop('user_id', None)\n return {'message': 'Logged out'}, 200",
"notes": "Flask-RESTful logout endpoint. Removes user_id from session with pop. Second argument None prevents KeyError if not found. Returns success message with 200 status. Register with api.add_resource(Logout, '/logout').",
"language_id": 5,
"category_id": 8
},
{
"title": "Flask User Model with Bcrypt",
"code": "class User(db.Model):\n __tablename__ = 'users'\n \n id = db.Column(db.Integer, primary_key=True)\n name = db.Column(db.String(100), nullable=False)\n email = db.Column(db.String(120), unique=True, nullable=False)\n _password_hash = db.Column(db.String(128))\n created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc))\n updated_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))\n \n # Relationship to *pets*\n *pets* = db.relationship('*Pet*', back_populates='user', cascade='all, delete-orphan')\n \n # Association proxy to get through cheats\n *cats* = association_proxy('*pets*', '*cat*',\n creator=lambda *cat*_obj: *Pet*(category=category_obj))\n *dogs* = association_proxy('*pets*', '*dog*',\n creator=lambda language_obj: *Pet*(language=language_obj))\n \n @property\n def password(self):\n raise AttributeError('password is not readable')\n \n @password.setter\n def password(self, password):\n self._password_hash = bcrypt.generate_password_hash(password).decode('utf-8')\n \n def check_password(self, password):\n return bcrypt.check_password_hash(self._password_hash, password)",
"notes": "User model with secure password hashing. Underscore prefix _password_hash keeps it private. init auto-hashes password on creation with bcrypt. authenticate method checks password against hash. unique=True on email prevents duplicates. Change relationship name (cheats) for each project. cascade delete removes related records when user deleted.",
"language_id": 5,
"category_id": 2
},
{
"title": "Loading State for Auth Context",
"code": "function HomePage() {\n const { loading, loggedIn, user } = useAuth();\n const [cheats, setCheats] = useState([]);\n \n // Wait for auth to load\n if (loading) {\n return <div>Loading...</div>;\n }\n \n // Now safe to fetch data\n useEffect(() => {\n if (loggedIn) {\n fetch('/api/cheats')\n .then(r => r.json())\n .then(setCheats);\n }\n }, [loggedIn]);\n \n return (\n <div>\n {cheats.map(cheat => <div key={cheat.id}>{cheat.title}</div>)}\n </div>\n );\n}",
"notes": "Check loading state from auth context at top of component. Return loading message if still checking auth. Prevents render before data loads. Avoids flash of wrong content. Add after useAuth hook call before any other logic.",
"language_id": 6,
"category_id": 11
},
{
"title": "Curl POST Create User",
"code": "curl -X POST http://localhost:5555/api/users \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"name\": \"Josh\",\n \"email\": \"josh@josh.com\",\n \"password\": \"1111\"\n }' ",
"notes": "curl POST request to create user. -X POST specifies method. -H sets Content-Type header to JSON. -d sends JSON data in request body. Use password not _password_hash - model handles hashing. Change port and endpoint to match your setup. Response returns created user data. Send password in the request, NOT _password_hash.",
"language_id": 9,
"category_id": 3
},
{
"title": "Curl POST Login",
"code": "curl -X POST http://localhost:5555/api/login \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"email\": \"josh@josh.com\",\n \"password\": \"1111\"\n }' ",
"notes": "curl POST request to login. Sends email and password as JSON. Returns user data if credentials valid or 401 error if invalid. Creates session cookie but curl doesn't save it by default. Add -c cookies.txt to save session. Add -b cookies.txt to send saved cookies in next request.",
"language_id": 9,
"category_id": 3
},
{
"title": "Autocomplete Filter on Input",
"code": "const filteredCheats = cheats.filter(cheat =>\n cheat.title.toLowerCase().includes(searchTerm.toLowerCase())\n );",
"notes": "Controlled input with searchTerm state. onChange updates state on every keystroke. Filter array using includes for partial match. toLowerCase makes search case-insensitive. filteredCheats recalculates automatically on state change. Shows results instantly as user types.",
"language_id": 6,
"category_id": 11
},
{
"title": "Query All Records",
"code": "# Get all users\nusers = User.query.all()\n\n# Example\nusers = User.query.all()\n# Result: [<User Josh>, <User Sarah>, <User Mike>]",
"notes": "Returns list of all records from table. Use on Query object not model directly. Good for small tables under 1000 records. Bad for large tables - loads everything into memory. If need just one use .first(). If counting use .count(). If filtering first use .filter_by() then .all().",
"language_id": 5,
"category_id": 8
},
{
"title": "Query First Record",
"code": "# Get first user\nuser = User.query.first()\n\n# With filter\nuser = User.query.filter_by(email=\"josh@josh.com\").first()\n\n# Example\nuser = User.query.filter_by(name=\"Josh\").first()\n# Result: <User Josh> or None",
"notes": "Returns first matching record or None if not found. Safer than .one() which errors if zero or multiple results. Use after .filter_by() for single lookups. Good for getting one record safely. If must exist use .one(). If need all use .all().",
"language_id": 5,
"category_id": 8
},
{
"title": "Check Relationship with any()",
"code": "# Check if user has any cheats with \"python\" in title\nhas_python = user.cheats.any(Cheat.title.ilike('%python%'))\n\n# Example\njosh = User.query.first()\nhas_terminal_cheats = josh.cheats.any(Cheat.category_id == 4)\n# Result: True or False",
"notes": "Used on collection relationships to check if any match condition. Returns boolean. Good for filtering parent by child properties. Use .has() for parent relationships instead. Don't use on plain columns. Returns True/False not records.",
"language_id": 5,
"category_id": 8
},
{
"title": "Check Parent with has()",
"code": "# Check if cheat has user with specific email\nCheat.query.filter(Cheat.user.has(email=\"josh@josh.com\"))\n\n# Example\nterminal_cheats = Cheat.query.filter(\n Cheat.user.has(User.name == \"Josh\")\n).all()\n# Result: Query of cheats where user.name is Josh",
"notes": "Used on parent relationships to check if parent matches condition. Returns filtered query not boolean. Good for filtering children by parent properties. Use .any() for collection relationships instead. Chain with .all() or .first() to execute.",
"language_id": 5,
"category_id": 8
},
{
"title": "Count Query Results",
"code": "# Count all users\ntotal = User.query.count()\n\n# Count with filter\npython_cheats = Cheat.query.filter_by(language_id=5).count()\n\n# Example\ncheat_count = Cheat.query.filter_by(user_id=1).count()\n# Result: 42",
"notes": "Returns integer count without loading records into memory. Faster than len(query.all()) for large tables. Use on Query object. Good for quick counts and pagination. If need actual data use .all() instead. More efficient than counting list length.",
"language_id": 5,
"category_id": 8
},
{
"title": "Filter by Equality with filter_by()",
"code": "# Filter by single field\nusers = User.query.filter_by(name=\"Josh\").all()\n\n# Multiple fields\ncheats = Cheat.query.filter_by(language_id=5, category_id=2).all()\n\n# Example\nuser = User.query.filter_by(email=\"josh@josh.com\").first()\n# Result: <User Josh>",
"notes": "Simple equality filtering using keyword arguments. Only works with equals not >, <, OR, LIKE. Chain multiple fields with commas. Use .filter() for complex conditions. Chain with .all() or .first() to execute. Most readable for simple lookups.",
"language_id": 5,
"category_id": 8
},
{
"title": "Filter Complex Conditions with filter()",
"code": "# Greater than\nusers = User.query.filter(User.id > 5).all()\n\n# Multiple conditions (AND)\ncheats = Cheat.query.filter(\n Cheat.language_id == 5,\n Cheat.category_id > 2\n).all()\n\n# OR conditions\nfrom sqlalchemy import or_\nusers = User.query.filter(\n or_(User.name == \"Josh\", User.name == \"Sarah\")\n).all()\n\n# Example\nrecent_cheats = Cheat.query.filter(Cheat.id > 10).all()\n# Result: [<Cheat 11>, <Cheat 12>, <Cheat 13>]",
"notes": "Complex filtering with comparison operators and logic. Use Model.column for conditions. Comma separates AND conditions. Import or_ for OR logic. Use .filter_by() for simple equality. Chain with .all() or .first() to execute.",
"language_id": 5,
"category_id": 8
},
{
"title": "Get by Primary Key with session.get()",
"code": "# Modern way (SQLAlchemy 2.0+)\nuser = db.session.get(User, 5)\n\n# OLD way (deprecated)\n# user = User.query.get(5)\n\n# Example\ncheat = db.session.get(Cheat, 42)\n# Result: <Cheat 42> or None",
"notes": "Modern SQLAlchemy 2.0+ method for primary key lookup. First arg is model, second is ID. Returns record or None. Replaces deprecated Model.query.get(). Fastest way to get by ID. Use .filter_by() for non-ID columns. Only works with primary keys.",
"language_id": 5,
"category_id": 8
},
{
"title": "Case-Insensitive Search with ilike()",
"code": "# Search with wildcards\nusers = User.query.filter(User.name.ilike('%josh%')).all()\n\n# Starts with\ncheats = Cheat.query.filter(Cheat.title.ilike('python%')).all()\n\n# Example\nsearch = \"REACT\"\nresults = Cheat.query.filter(Cheat.title.ilike(f'%{search}%')).all()\n# Result: Finds \"react\", \"React\", \"REACT\"",
"notes": "Case-insensitive pattern matching. Use % as wildcard for any characters. Good for user search features. Use .like() for case-sensitive. Use .filter_by() for exact match. Works on string columns only. Surround with % for contains search.",
"language_id": 5,
"category_id": 8
},
{
"title": "Filter by List with in_()",
"code": "# Filter by ID list\nids = [1, 2, 3, 5, 8]\nusers = User.query.filter(User.id.in_(ids)).all()\n\n# Example\nselected_ids = [10, 20, 30]\ncheats = Cheat.query.filter(Cheat.id.in_(selected_ids)).all()\n# Result: [<Cheat 10>, <Cheat 20>, <Cheat 30>]",
"notes": "SQL IN clause for multiple values. Pass list or tuple to in_(). Good for bulk lookups by ID. Use on column object not model. Efficient for small to medium lists. Very large lists (10000+) may be slow - batch instead.",
"language_id": 5,
"category_id": 8
},
{
"title": "Sort Results with order_by()",
"code": "# Sort ascending (A to Z, 1 to 10)\nusers = User.query.order_by(User.name).all()\n\n# Sort descending (Z to A, 10 to 1)\ncheats = Cheat.query.order_by(Cheat.id.desc()).all()\n\n# Multiple sorts\nresults = Cheat.query.order_by(\n Cheat.language_id,\n Cheat.title.desc()\n).all()\n\n# Example\nrecent_first = Cheat.query.order_by(Cheat.id.desc()).all()\n# Result: [<Cheat 100>, <Cheat 99>, <Cheat 98>...]",
"notes": "Sorts query results by column. Default is ascending use .desc() for descending. Use .asc() to be explicit about ascending. Chain multiple order_by for secondary sorts. Must call before .all() or .first(). Use on Query object. Good for displaying sorted lists.",
"language_id": 5,
"category_id": 8
},
{
"title": "Limit Results with limit()",
"code": "# Get first 10 users\nusers = User.query.limit(10).all()\n\n# With offset for pagination (skip first 20, get next 10)\npage_2 = Cheat.query.offset(20).limit(10).all()\n\n# Example - get 5 most recent cheats\nrecent = Cheat.query.order_by(Cheat.id.desc()).limit(5).all()\n# Result: [<Cheat 100>, <Cheat 99>, <Cheat 98>, <Cheat 97>, <Cheat 96>]",
"notes": "Limits number of results returned. Good for pagination and performance. Use .offset() to skip records. Chain with .order_by() for consistent results. Use before .all(). Don't use if need all records. Combine offset and limit for page navigation.",
"language_id": 5,
"category_id": 8
},
{
"title": "Access Relationship Records",
"code": "# Access collection relationship\nuser = db.session.get(User, 1)\nuser_cheats = user.cheats\n# Result: [<Cheat 1>, <Cheat 2>, <Cheat 3>]\n\n# Access parent relationship\ncheat = db.session.get(Cheat, 5)\ncheat_author = cheat.user\n# Result: <User Josh>\n\n# Example\njosh = User.query.filter_by(name=\"Josh\").first()\nall_josh_cheats = josh.cheats\n# Result: List of all cheats belonging to Josh",
"notes": "Access related records through relationship properties defined in models. Collection relationships return list. Parent relationships return single object. Automatically queries database when accessed. Good for simple related data access. If need filtering use .query.join() instead. Returns actual objects not query.",
"language_id": 5,
"category_id": 8
},
{
"title": "List Directory Contents with ls",
"code": "# Basic list\nls\n\n# List with hidden files (starts with .)\nls -a\n\n# List with details (permissions, size, date)\nls -l\n\n# Combine flags (long format + hidden)\nls -la\n\n# Example in project directory\nls\n# Result: client server README.md\n\nls -a\n# Result: . .. .git .gitignore client server README.md",
"notes": "Lists files and folders in current directory. -a shows hidden files starting with dot. -l shows long format with permissions and dates. Combine flags like -la. Use before navigating to see what's available. Hidden files include .git .env .gitignore.",
"language_id": 9,
"category_id": 8
},
{
"title": "Print Working Directory with pwd",
"code": "# Show current full path\npwd\n\n# Example\ncd ~/Desktop/projects/cheat-app\npwd\n# Result: /Users/josh/Desktop/projects/cheat-app",
"notes": "Prints full path of current directory. Useful when lost in filesystem. Shows absolute path from root. Use after cd to confirm location. Good for scripts that need current path.",
"language_id": 9,
"category_id": 8
},
{
"title": "Move or Rename with mv",
"code": "# Rename file\nmv oldname.txt newname.txt\n\n# Move file to folder\nmv file.txt folder/\n\n# Move and rename\nmv old.txt folder/new.txt\n\n# Move multiple files\nmv file1.txt file2.txt destination-folder/\n\n# Example\nmv app.py main.py\n# Result: Renames app.py to main.py\n\nmv config.py server/\n# Result: Moves config.py into server folder",
"notes": "Moves or renames files and directories. Same command for both operations. Overwrites destination if exists. Use with caution. Can move multiple files to directory. Destination must be folder when moving multiple. No undo.",
"language_id": 9,
"category_id": 8
},
{
"title": "Marshmallow schema with ma.Method for custom field serialization",
"code": "class UserSchema(ma.SQLAlchemyAutoSchema):\n languages = ma.Method(\"get_languages_with_cheats\")\n \n def get_languages_with_cheats(self, user):\n # Custom grouping logic here\n return [...]",
"notes": "I'm using Marshmallow SQLAlchemyAutoSchema with custom serialization methods defined using ma.Method. This allows me to override specific fields with custom logic while keeping automatic serialization for other fields.",
"language_id": 5,
"category_id": 2
},
{
"title": "Remove Screenshots in Downloads",
"code": "rm ~/Downloads/screenshot*.png",
"notes": "Removes all files titled 'screenshot_...' in the Downloads folder",
"language_id": 9,
"category_id": 8
},
{
"title": "Remove and Rebuild Instance and Migration",
"code": "rm -rf migrations instance\nflask db init\nflask db migrate -m \"initial migration\"\nflask db upgrade\npython seed.py",
"notes": "Includes seed.py to reseed the database after rebuilding",
"language_id": 9,
"category_id": 9
},
{
"title": "CRT Phosphorus Green Screen Full (version 1)",
"code": "@import url('https://fonts.googleapis.com/css2?family=VT323&display=swap');\n/* =========================================================\n ROOT CONTAINER - WIDER\n ========================================================= */\n\n:root {\n --phosphor-main: #33ff00;\n --phosphor-dim: #1a8000;\n --bg-color: #050a05;\n}\n#root > * {\n position: relative;\n z-index: 5;\n \n}\n#root {\n max-width: 1400px;\n margin: 0 auto;\n padding: 20px 40px;\n min-height: 100vh;\n border-left: 2px solid var(--phosphor-dim);\n border-right: 2px solid var(--phosphor-dim);\n position: relative;\n}\n\n/* =========================================================\n GLOBAL RESET\n ========================================================= */\n* {\n box-sizing: border-box;\n}\n\nhtml, body {\n margin: 0;\n padding: 0;\n background-color: var(--bg-color);\n color: var(--phosphor-main);\n font-family: 'VT323', monospace;\n font-size: 20px;\n height: 100%;\n width: 100%;\n overflow-x: hidden;\n\n /* phosphor bloom */\n text-shadow:\n 0 0 1px var(--phosphor-main),\n 0 0 6px rgba(51,255,0,0.45);\n}\n\n/* =========================================================\n PHOSPHOR DOT GRID (SHADOW MASK)\n ========================================================= */\nbody::before {\n content: \"\";\n position: fixed;\n inset: 0;\n pointer-events: none;\n z-index: 9997;\n\n background-image:\n radial-gradient(\n rgba(51,255,0,0.04) 1px,\n transparent 1px\n );\n\n background-size: 4px 4px;\n opacity: 0.18;\n filter: blur(0.6px);\n}\n/* =========================================================\n SCANLINES + RGB BLEED\n ========================================================= */\nbody::after {\n content: \"\";\n position: fixed;\n inset: 0;\n pointer-events: none;\n z-index: 9998;\n\n background:\n repeating-linear-gradient(\n to bottom,\n rgba(0,0,0,0.28),\n rgba(0,0,0,0.28) 1px,\n rgba(0,0,0,0) 2px\n ),\n linear-gradient(\n 90deg,\n rgba(255,0,0,0.05),\n rgba(0,255,0,0.02),\n rgba(0,0,255,0.05)\n );\n\n background-size: 100% 3px, 4px 100%;\n animation: crt-flicker 0.14s infinite;\n}\n\n@keyframes crt-flicker {\n 0% { opacity: 0.94; }\n 50% { opacity: 1; }\n 100% { opacity: 0.96; }\n}\n\n/* =========================================================\n CRT FALL-OFF + CURVATURE\n ========================================================= */\n\n\n#root::before {\n content: \"\";\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: 2;\n\n /* tube luminance falloff */\n background:\n radial-gradient(\n ellipse at center,\n rgba(0,0,0,0) 55%,\n rgba(0,0,0,0.35) 100%\n ),\n linear-gradient(\n to bottom,\n rgba(0,0,0,0.25),\n rgba(0,0,0,0),\n rgba(0,0,0,0.25)\n );\n\n mix-blend-mode: multiply;\n}\n\n/* =========================================================\n TYPOGRAPHY\n ========================================================= */\nh1, h2, h3, label {\n text-transform: uppercase;\n font-weight: 400;\n letter-spacing: 1px;\n}\n\na {\n color: var(--phosphor-main);\n text-decoration: none;\n border-bottom: 1px dashed var(--phosphor-dim);\n}\n\na:hover {\n background: var(--phosphor-main);\n color: #000;\n text-shadow: none;\n}\n/* =========================================================\n ASCII TITLE\n ========================================================= */\n.ascii-title {\n font-family: 'VT323', monospace;\n font-size: 0.5rem;\n line-height: 1.0;\n color: var(--phosphor-main);\n text-align: center;\n margin: 10px 0 20px 0;\n white-space: pre;\n text-shadow: \n 0 0 10px rgba(51,255,0,0.6),\n 0 0 20px rgba(51,255,0,0.3);\n overflow-x: auto;\n}\n/* =========================================================\n FORMS & INPUTS\n ========================================================= */\ninput, select, textarea, button {\n background: #000;\n border: 2px solid var(--phosphor-main);\n color: var(--phosphor-main);\n font-family: inherit;\n font-size: 1.1rem;\n padding: 8px;\n outline: none;\n text-transform: uppercase;\n\n box-shadow:\n inset 0 0 6px rgba(51,255,0,0.35),\n 0 0 4px rgba(51,255,0,0.3);\n}\n\ninput:focus,\nselect:focus,\ntextarea:focus {\n background: var(--phosphor-dim);\n color: #fff;\n}\n\n/* =========================================================\n BUTTONS\n ========================================================= */\nbutton {\n cursor: pointer;\n transition: all 0.08s linear;\n}\n\nbutton:hover {\n background: var(--phosphor-main);\n color: #000;\n box-shadow: 0 0 12px var(--phosphor-main);\n text-shadow: none;\n}\n\nbutton.active {\n background: var(--phosphor-main);\n color: #000;\n text-shadow: none;\n}\n\n/* =========================================================\n FILTER PANEL\n ========================================================= */\n.filter-panel {\n border: 4px double var(--phosphor-main);\n padding: 20px;\n margin-bottom: 20px;\n background: rgba(0,20,0,0.55);\n}\n\n.filter-section {\n margin-bottom: 20px;\n}\n\n.filter-section label {\n display: inline-block;\n background: var(--phosphor-main);\n color: #000;\n padding: 2px 8px;\n margin-bottom: 10px;\n text-shadow: none;\n}\n\n.language-buttons,\n.category-buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n}\n\n/* =========================================================\n RESULTS COUNT\n ========================================================= */\n.results-count {\n margin: 20px 0;\n padding: 10px 0;\n border-top: 1px dashed var(--phosphor-main);\n border-bottom: 1px dashed var(--phosphor-main);\n\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n/* =========================================================\n TABLE\n ========================================================= */\ntable {\n width: 100%;\n border-collapse: collapse;\n margin-top: 20px;\n border: 2px solid var(--phosphor-main);\n}\n\nthead {\n background: var(--phosphor-dim);\n}\n\nth {\n padding: 10px;\n color: #000;\n border-bottom: 2px solid var(--phosphor-main);\n text-shadow: none;\n}\n\ntd {\n padding: 10px;\n border-bottom: 1px solid var(--phosphor-dim);\n}\n\ntr:hover td {\n background: rgba(51,255,0,0.1);\n}\ntd:last-child {\n white-space: nowrap;\n}\n\ntd:last-child button {\n display: inline-block;\n margin-right: 5px;\n margin-bottom: 0;\n padding: 4px 8px;\n font-size: 0.9rem;\n}\n/* =========================================================\n NAV BAR\n ========================================================= */\nnav {\n display: flex;\n justify-content: space-between;\n align-items: center;\n border-bottom: 4px double var(--phosphor-main);\n padding: 10px 0;\n margin-bottom: 30px;\n}\n\nnav a {\n margin-left: 20px;\n padding: 5px 10px;\n}\n\nnav a.active {\n background: var(--phosphor-main);\n color: #000;\n text-shadow: none;\n}\n\n/* =========================================================\n LOGIN\n ========================================================= */\n.login-card {\n border: 4px double var(--phosphor-main);\n padding: 40px;\n max-width: 400px;\n margin: 0 auto;\n text-align: center;\n}\n\n.login-card form {\n display: flex;\n flex-direction: column;\n gap: 15px;\n}\n\n/* =========================================================\n CLOCK / SVG\n ========================================================= */\n.dt-svg {\n stroke: var(--phosphor-main);\n fill: var(--phosphor-main);\n filter: drop-shadow(0 0 4px rgba(51,255,0,0.7));\n}\n\n\n/* =========================================================\n OUTRUN GRID FLOOR\n ========================================================= */\n.outrun-grid {\n position: fixed;\n bottom: -10vh;\n left: -10%;\n width: 120%;\n height: 60vh;\n pointer-events: none;\n z-index: 1;\n background:\n linear-gradient(rgba(51,255,0,0.45), transparent 60%),\n repeating-linear-gradient(to right, rgba(51,255,0,0.3), rgba(51,255,0,0.3) 1px, transparent 1px, transparent 48px),\n repeating-linear-gradient(to top, rgba(51,255,0,0.35), rgba(51,255,0,0.35) 1px, transparent 1px, transparent 28px);\n transform: perspective(500px) rotateX(68deg) translateZ(-120px);\n opacity: 0.45;\n filter: blur(0.2px);\n animation: grid-crawl 20s linear infinite;\n}\n\n/* Grid crawl animation */\n@keyframes grid-crawl {\n 0% { background-position: 0 0, 0 0, 0 0; }\n 100% { background-position: 0 0, -480px 0, 0 -168px; }\n}\n\n/* Horizontal slow drift */\nbody {\n animation: h-drift 10s ease-in-out infinite alternate;\n}\n\n@keyframes h-drift {\n 0% { transform: translateX(0); }\n 100% { transform: translateX(1px); }\n}\n\n/* Phosphor decay effect for dynamic updates */\n.phosphor-decay {\n animation: decay-glow 0.6s ease-out;\n}\n\n@keyframes decay-glow {\n 0% { text-shadow: 0 0 10px var(--phosphor-main), 0 0 20px rgba(51,255,0,0.6); }\n 100% { text-shadow: 0 0 1px var(--phosphor-main), 0 0 6px rgba(51,255,0,0.45); }\n}\n\n/* =========================================================\n DATE TIME - TINY INLINE\n ========================================================= */\n.dt-inline {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 0.85rem;\n}\n\n.dt-date {\n line-height: 1;\n}\n\n.dt-clock {\n position: relative;\n width: 10px;\n height: 10px;\n flex-shrink: 0;\n}\n\n.dt-svg {\n width: 100%;\n height: 100%;\n stroke: var(--phosphor-main);\n stroke-width: 1;\n filter: none;\n}\n\n.dt-ampm {\n position: absolute;\n bottom: -2px;\n right: -4px;\n font-size: 0.45rem;\n font-weight: bold;\n}\n\nbutton {\n background: #000;\n border: 1px solid var(--phosphor-main);\n color: var(--phosphor-main);\n padding: 6px 10px;\n box-shadow: inset 0 0 0 1px rgba(51,255,0,0.25);\n}\n\nbutton:hover {\n background: var(--phosphor-main);\n color: #000;\n box-shadow: inset 0 0 0 1px #000;\n}\n\n.filter-panel,\n.login-card,\ntable {\n border-image:\n repeating-linear-gradient(\n 90deg,\n var(--phosphor-main),\n var(--phosphor-main) 2px,\n transparent 2px,\n transparent 6px\n ) 2;\n}\n",
"notes": "A good version that is very basic and digital",
"language_id": 1,
"category_id": 9
},
{
"title": "CRT Phosphorus Green Screen Full (version 2)",
"code": "@import url('https://fonts.googleapis.com/css2?family=VT323&display=swap');\n\n/* =========================================================\n ROOT CONTAINER\n========================================================= */\n:root {\n --phosphor-main: #33ff00;\n --phosphor-dim: #1a8000;\n --bg-color: #050a05;\n}\n\n#root {\n max-width: 1400px;\n margin: 0 auto;\n padding: 20px 40px;\n min-height: 100vh;\n border-left: 2px solid var(--phosphor-dim);\n border-right: 2px solid var(--phosphor-dim);\n position: relative;\n}\n\n#root > * {\n position: relative;\n z-index: 5;\n}\n\n/* =========================================================\n GLOBAL RESET\n========================================================= */\n* {\n box-sizing: border-box;\n}\n\nhtml, body {\n margin: 0;\n padding: 0;\n background-color: var(--bg-color);\n color: var(--phosphor-main);\n font-family: 'VT323', monospace;\n font-size: 20px;\n height: 100%;\n width: 100%;\n overflow-x: hidden;\n text-shadow: 0 0 1px var(--phosphor-main),\n 0 0 6px rgba(51,255,0,0.45);\n}\n\n/* =========================================================\n PHOSPHOR DOT GRID & SCANLINES\n========================================================= */\nbody::before {\n content: \"\";\n position: fixed;\n inset: 0;\n pointer-events: none;\n z-index: 9997;\n background-image: radial-gradient(rgba(51,255,0,0.04) 1px, transparent 1px);\n background-size: 4px 4px;\n opacity: 0.18;\n filter: blur(0.6px);\n}\n\nbody::after {\n content: \"\";\n position: fixed;\n inset: 0;\n pointer-events: none;\n z-index: 9998;\n background:\n repeating-linear-gradient(to bottom, rgba(0,0,0,0.28), rgba(0,0,0,0.28) 1px, rgba(0,0,0,0) 2px),\n linear-gradient(90deg, rgba(255,0,0,0.05), rgba(0,255,0,0.02), rgba(0,0,255,0.05));\n background-size: 100% 3px, 4px 100%;\n animation: crt-flicker 0.14s infinite;\n}\n\n@keyframes crt-flicker {\n 0% { opacity: 0.94; }\n 50% { opacity: 1; }\n 100% { opacity: 0.96; }\n}\n\n#root::before {\n content: \"\";\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: 2;\n background:\n radial-gradient(ellipse at center, rgba(0,0,0,0) 55%, rgba(0,0,0,0.35) 100%),\n linear-gradient(to bottom, rgba(0,0,0,0.25), rgba(0,0,0,0), rgba(0,0,0,0.25));\n mix-blend-mode: multiply;\n}\n\n/* =========================================================\n TYPOGRAPHY\n========================================================= */\nh1, h2, h3, label {\n text-transform: uppercase;\n font-weight: 400;\n letter-spacing: 1px;\n}\n\na {\n color: var(--phosphor-main);\n text-decoration: none;\n border-bottom: 1px dashed var(--phosphor-dim);\n cursor: pointer;\n}\na:hover {\n background: var(--phosphor-main);\n color: #000;\n text-shadow: none;\n}\n\n/* =========================================================\n ASCII TITLE\n========================================================= */\n.ascii-title {\n font-family: 'VT323', monospace;\n font-size: 0.5rem;\n line-height: 1;\n color: var(--phosphor-main);\n text-align: center;\n margin: 10px 0 20px;\n white-space: pre;\n text-shadow: 0 0 10px rgba(51,255,0,0.6),\n 0 0 20px rgba(51,255,0,0.3);\n overflow-x: auto;\n}\n.ascii-title, textarea.terminal-input, textarea.code-input, code {\n font-family: 'Courier New', monospace;\n}\n\n\n/* =========================================================\n FORMS, INPUTS & PANELS (FIXED HERE)\n========================================================= */\n/* Common panel style (used for Filter, Login, Cheat Form) */\n.filter-panel, .login-card, .retro-panel {\n border: 4px double var(--phosphor-main);\n padding: 30px; \n margin-bottom: 20px;\n background: #000; /* Solid black background to block grid */\n border-image: repeating-linear-gradient(90deg, var(--phosphor-main), var(--phosphor-main) 2px, transparent 2px, transparent 6px) 2;\n box-shadow: 0 0 20px rgba(51,255,0,0.15);\n position: relative;\n z-index: 10;\n}\n\n.form-group {\n margin-bottom: 1.5rem;\n}\n\n.form-group label {\n display: block;\n margin-bottom: 0.5rem;\n color: #000;\n background: var(--phosphor-main); /* Inverted label */\n width: fit-content;\n padding: 2px 8px;\n font-weight: bold;\n}\n\ninput, select, textarea, button {\n background: #050a05;\n border: 2px solid var(--phosphor-dim);\n color: var(--phosphor-main);\n font-family: inherit;\n font-size: 1.2rem;\n padding: 12px;\n outline: none;\n text-transform: uppercase;\n width: 100%;\n transition: all 0.2s ease;\n}\n\ninput:focus, select:focus, textarea:focus {\n border-color: var(--phosphor-main);\n background: #000;\n box-shadow: 0 0 15px rgba(51,255,0,0.25);\n}\n\n/* Specific styling for the code text area */\ntextarea.terminal-input, textarea.code-input {\n font-family: 'Courier New', monospace;\n font-size: 1rem;\n text-transform: none; /* Keep code case-sensitive */\n line-height: 1.4;\n background-color: #000;\n color: #ccffcc; /* Slightly brighter for code */\n border: 1px solid var(--phosphor-main);\n}\n\n/* =========================================================\n BUTTONS\n========================================================= */\nbutton {\n cursor: pointer;\n width: auto;\n display: inline-block;\n background: #000;\n border: 1px solid var(--phosphor-main);\n color: var(--phosphor-main);\n padding: 8px 16px;\n box-shadow: inset 0 0 0 1px rgba(51,255,0,0.25);\n}\nbutton:hover {\n background: var(--phosphor-main);\n color: #000;\n box-shadow: 0 0 12px var(--phosphor-main), inset 0 0 0 1px #000;\n text-shadow: none;\n}\n\n/* =========================================================\n CHEAT FORM SPECIFIC (FIXED HERE)\n========================================================= */\n.form-page-wrapper {\n display: flex;\n justify-content: center;\n padding-top: 20px;\n padding-bottom: 100px; /* Space for scrolling */\n position: relative;\n z-index: 10;\n}\n\n.form-panel {\n width: 100%;\n max-width: 900px;\n}\n\n.form-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 30px;\n border-bottom: 2px dashed var(--phosphor-dim);\n padding-bottom: 10px;\n}\n\n.form-header h2 { margin: 0; }\n\n.form-row {\n display: flex;\n gap: 20px;\n}\n.form-group.half { flex: 1; }\n\n.form-actions {\n display: flex;\n gap: 20px;\n margin-top: 30px;\n border-top: 2px dashed var(--phosphor-dim);\n padding-top: 20px;\n}\n\n.action-primary {\n font-weight: bold;\n border-width: 2px;\n flex: 2;\n}\n.action-secondary {\n flex: 1;\n border-color: var(--phosphor-dim);\n color: var(--phosphor-dim);\n}\n.action-secondary:hover {\n border-color: #ff3333;\n color: #ff3333;\n box-shadow: 0 0 10px rgba(255, 0, 0, 0.5);\n background: transparent;\n}\n\n/* =========================================================\n NAV BAR\n========================================================= */\nnav {\n display: flex;\n justify-content: space-between;\n align-items: center;\n border-bottom: 4px double var(--phosphor-main);\n padding: 15px 0;\n margin-bottom: 40px;\n background: #000; /* Solid background */\n position: relative;\n z-index: 20;\n}\n.nav-brand {\n display: flex;\n align-items: center;\n font-size: 1.4rem;\n font-weight: bold;\n letter-spacing: 2px;\n text-shadow: 0 0 5px var(--phosphor-main);\n}\n\n/* Specific styling for the logo link to reset standard nav button styles */\n.nav-brand a.brand-link {\n border: none;\n padding: 0;\n margin-right: 10px;\n background: transparent !important;\n box-shadow: none !important;\n display: inline-flex;\n align-items: center;\n gap: 10px;\n}\n\n.nav-brand a.brand-link:hover {\n text-shadow: 0 0 8px #fff; /* Brighter glow on hover instead of box */\n color: #fff;\n}\n\n.version {\n font-size: 0.8rem;\n opacity: 0.7;\n margin-left: 5px;\n transform: translateY(2px); /* Slight alignment fix */\n}\n.nav-menu {\n display: flex;\n align-items: center;\n gap: 15px;\n}\nnav a {\n color: var(--phosphor-main);\n text-decoration: none;\n border: 1px solid transparent;\n padding: 5px 10px;\n transition: all 0.2s;\n font-size: 1rem;\n}\nnav a:hover {\n background: rgba(51, 255, 0, 0.1);\n box-shadow: 0 0 8px rgba(51, 255, 0, 0.3);\n text-shadow: none;\n}\nnav a.active {\n background: var(--phosphor-main);\n color: #000;\n border-color: var(--phosphor-main);\n box-shadow: 0 0 10px var(--phosphor-main);\n text-shadow: none;\n}\n.user-info { color: var(--phosphor-dim); font-size: 0.9rem; }\n.separator { color: var(--phosphor-dim); }\n.status-offline { color: #ff3333; margin-right: 15px; font-size: 0.9rem; text-shadow: 0 0 3px #ff3333; }\n.nav-logout-btn {\n background: transparent;\n border: 1px solid var(--phosphor-dim);\n color: var(--phosphor-dim);\n font-size: 0.9rem;\n padding: 5px 10px;\n margin-left: 10px;\n}\n.nav-logout-btn:hover {\n border-color: #ff3333;\n color: #ff3333;\n box-shadow: 0 0 8px rgba(255, 51, 51, 0.4);\n background: transparent;\n}\n.cursor-blink { animation: blink 1s step-end infinite; }\n@keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }\n\n/* =========================================================\n LOGIN / SIGNUP PAGE SPECIFIC\n========================================================= */\n.login-page-container {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 60vh;\n}\n.login-card {\n width: 100%;\n max-width: 450px;\n position: relative;\n}\n.login-card h1 {\n text-align: center;\n border-bottom: 2px solid var(--phosphor-dim);\n padding-bottom: 15px;\n margin-bottom: 25px;\n}\n.login-error {\n background: rgba(255, 0, 0, 0.2);\n border: 1px solid #ff3333;\n color: #ff3333;\n padding: 10px;\n margin-bottom: 20px;\n text-align: center;\n text-shadow: 0 0 5px #ff3333;\n}\n.form-actions.vertical {\n display: flex;\n flex-direction: column;\n gap: 15px;\n text-align: center;\n}\n.auth-link { font-size: 0.9rem; margin-top: 10px; }\n.auth-link span { opacity: 0.7; margin-right: 8px; }\n.dev-hack-btn {\n position: absolute;\n top: 10px;\n right: 10px;\n padding: 2px 6px;\n font-size: 12px;\n border: none;\n background: transparent;\n color: var(--phosphor-dim);\n box-shadow: none;\n width: auto;\n}\n.dev-hack-btn:hover {\n color: var(--phosphor-main);\n background: transparent;\n box-shadow: none;\n}\n\n/* =========================================================\n CHEAT ITEM / LIST / OTHER\n========================================================= */\n.terminal-screen {\n position: relative;\n background: #000;\n border: 1px solid var(--phosphor-dim);\n padding: 12px;\n cursor: pointer;\n transition: border-color 0.2s;\n min-width: 250px;\n max-width: 400px;\n}\n.terminal-screen:hover {\n border-color: var(--phosphor-main);\n box-shadow: 0 0 10px rgba(51,255,0,0.2);\n}\n.terminal-screen pre {\n margin: 0;\n overflow-x: auto;\n white-space: pre-wrap;\n scrollbar-width: thin;\n scrollbar-color: var(--phosphor-dim) #000;\n}\n.terminal-screen code {\n font-family: 'Courier New', monospace;\n font-size: 14px;\n color: var(--phosphor-main);\n text-shadow: none;\n}\n.source-view-label {\n position: absolute;\n top: 0;\n right: 0;\n background: var(--phosphor-main);\n color: #000;\n font-size: 10px;\n padding: 2px 6px;\n pointer-events: none;\n}\n.language-buttons, .category-buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n}\n.results-count {\n margin: 20px 0;\n padding: 10px 0;\n border-top: 1px dashed var(--phosphor-main);\n border-bottom: 1px dashed var(--phosphor-main);\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\ntable {\n width: 100%;\n border-collapse: collapse;\n margin-top: 20px;\n}\nthead { background: var(--phosphor-dim); }\nth { padding: 10px; color: #000; }\ntd { padding: 10px; border-bottom: 1px solid var(--phosphor-dim); }\ntr:hover td { background: rgba(51,255,0,0.1); }\ntd:last-child { white-space: nowrap; }\n\n/* =========================================================\n OUTRUN GRID\n========================================================= */\n.outrun-grid {\n position: fixed;\n bottom: -10vh;\n left: -10%;\n width: 120%;\n height: 60vh;\n pointer-events: none;\n z-index: 1;\n background:\n linear-gradient(rgba(51,255,0,0.45), transparent 60%),\n repeating-linear-gradient(to right, rgba(51,255,0,0.3), rgba(51,255,0,0.3) 1px, transparent 1px, transparent 48px),\n repeating-linear-gradient(to top, rgba(51,255,0,0.35), rgba(51,255,0,0.35) 1px, transparent 1px, transparent 28px);\n transform: perspective(500px) rotateX(68deg) translateZ(-120px);\n opacity: 0.45;\n filter: blur(0.2px);\n animation: grid-crawl 20s linear infinite;\n}\n\n@keyframes grid-crawl {\n 0% { background-position: 0 0, 0 0, 0 0; }\n 100% { background-position: 0 0, -480px 0, 0 -168px; }\n}\n\n/* =========================================================\n SEARCH BAR & CLEAR BUTTON\n========================================================= */\n.search-wrapper { position: relative; margin-bottom: 1rem; width: 100%; }\n.search-wrapper input { width: 100%; padding-right: 35px; }\n.clear-btn {\n position: absolute;\n right: 8px;\n top: 50%;\n transform: translateY(-50%);\n background: none;\n border: none;\n padding: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--phosphor-dim);\n cursor: pointer;\n transition: color 0.2s;\n}\n.clear-btn:hover { color: var(--phosphor-main); }\n\n/* =========================================================\n FILTER BUTTON ICONS\n========================================================= */\n.button-grid {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n margin-bottom: 16px;\n}\n\n.tile-btn {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n width: 80px;\n height: 80px;\n padding: 6px;\n gap: 4px;\n border: 2px solid #444;\n border-radius: 8px;\n background: #111;\n color: #fff;\n font-size: 0.8rem;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 2px 2px 5px rgba(0,0,0,0.5);\n}\n\n.tile-btn:hover {\n transform: translateY(-2px);\n border-color: #33ff00;\n box-shadow: 4px 4px 8px rgba(0,0,0,0.7);\n}\n\n.tile-btn.active {\n border-color: #33ff00;\n background: #222;\n}\n\n.tile-label {\n font-size: 0.75rem;\n text-align: center;\n}\n\n.tile-count {\n font-size: 0.65rem;\n font-weight: bold;\n color: #33ff00;\n}\n\n\n/* =========================================================\n CHEAT DETAIL PAGE (The \"Authentic\" Look)\n========================================================= */\n\n.page-wrapper.detail-view {\n display: flex;\n justify-content: center;\n padding-top: 40px;\n padding-bottom: 100px;\n}\n\n.cheat-detail-panel {\n width: 100%;\n max-width: 900px;\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n/* HEADER */\n.detail-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n border-bottom: 2px solid var(--phosphor-dim);\n padding-bottom: 15px;\n margin-bottom: 10px;\n}\n\n.system-id {\n font-family: 'Courier New', monospace;\n font-size: 0.8rem;\n color: var(--phosphor-dim);\n letter-spacing: 2px;\n}\n\n/* GLITCH TITLE */\n.glitch-title {\n font-size: 3rem;\n margin: 0;\n text-transform: uppercase;\n position: relative;\n width: fit-content;\n text-shadow: 2px 2px var(--phosphor-dim);\n}\n\n.glitch-title::before,\n.glitch-title::after {\n content: attr(data-text);\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: #000;\n}\n\n.glitch-title::before {\n left: 2px;\n text-shadow: -1px 0 #ff3333;\n clip: rect(24px, 550px, 90px, 0);\n animation: glitch-anim-2 3s infinite linear alternate-reverse;\n}\n\n.glitch-title::after {\n left: -2px;\n text-shadow: -1px 0 #33ff00;\n clip: rect(85px, 550px, 140px, 0);\n animation: glitch-anim 2.5s infinite linear alternate-reverse;\n}\n\n@keyframes glitch-anim {\n 0% { clip: rect(10px, 9999px, 30px, 0); }\n 20% { clip: rect(80px, 9999px, 100px, 0); }\n 40% { clip: rect(10px, 9999px, 60px, 0); }\n 60% { clip: rect(60px, 9999px, 90px, 0); }\n 80% { clip: rect(30px, 9999px, 70px, 0); }\n 100% { clip: rect(90px, 9999px, 100px, 0); }\n}\n\n@keyframes glitch-anim-2 {\n 0% { clip: rect(60px, 9999px, 90px, 0); }\n 20% { clip: rect(10px, 9999px, 50px, 0); }\n 40% { clip: rect(80px, 9999px, 100px, 0); }\n 60% { clip: rect(30px, 9999px, 40px, 0); }\n 80% { clip: rect(90px, 9999px, 100px, 0); }\n 100% { clip: rect(10px, 9999px, 40px, 0); }\n}\n\n/* META STRIP (Clutter) */\n.meta-strip {\n display: flex;\n gap: 20px;\n border-top: 1px dashed var(--phosphor-dim);\n border-bottom: 1px dashed var(--phosphor-dim);\n padding: 8px 0;\n font-family: 'Courier New', monospace;\n font-size: 0.9rem;\n}\n\n.meta-item .label {\n color: var(--phosphor-dim);\n margin-right: 5px;\n}\n\n.meta-item .value {\n color: var(--phosphor-main);\n font-weight: bold;\n}\n\n/* LARGE TERMINAL */\n.terminal-screen.large {\n min-height: 300px;\n font-size: 1.1rem;\n}\n\n/* NOTES & FOOTER */\n.detail-footer {\n display: flex;\n justify-content: space-between;\n align-items: flex-end;\n margin-top: 20px;\n border-top: 4px double var(--phosphor-dim);\n padding-top: 20px;\n}\n\n.notes-block {\n max-width: 60%;\n}\n\n.notes-block .label {\n color: var(--phosphor-dim);\n margin-bottom: 5px;\n font-size: 0.9rem;\n}\n\n.timestamps {\n text-align: right;\n font-size: 0.8rem;\n color: var(--phosphor-dim);\n display: flex;\n flex-direction: column;\n gap: 5px;\n}\n\n/* =========================================================\n FIXES: LOADING STATE & LABELS\n========================================================= */\n\n/* 1. THE LOADING STATE (Blinking Centered Text) */\n.loading-state {\n display: flex;\n justify-content: center;\n align-items: center;\n height: 60vh; /* Centers it vertically */\n font-size: 2rem;\n font-weight: bold;\n color: var(--phosphor-main);\n text-shadow: 0 0 15px var(--phosphor-main);\n animation: blink 0.5s step-end infinite alternate;\n letter-spacing: 4px;\n}\n\n/* 2. ANNOTATIONS LABEL (Inverted Header Block) */\n.notes-block .label {\n display: inline-block;\n background: var(--phosphor-main); /* Solid Green Block */\n color: #000; /* Black Text */\n padding: 4px 8px;\n font-weight: bold;\n margin-bottom: 10px;\n font-size: 1.1rem;\n box-shadow: 0 0 8px rgba(51, 255, 0, 0.4);\n}\n\n.notes-block p {\n margin-top: 0;\n line-height: 1.5;\n color: #ccffcc; /* Slightly lighter text for readability */\n border-left: 2px solid var(--phosphor-dim);\n padding-left: 15px;\n}\n\n/* =========================================================\n FILTER PANEL & TILES (COMPACT)\n========================================================= */\n\n.filter-wrapper {\n margin-bottom: 30px; /* slightly smaller spacing */\n}\n\n.filter-controls {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n gap: 12px; /* tighter gap between search and buttons */\n}\n\n.search-section {\n flex-grow: 1;\n}\n\n/* BUTTON GRID (Tiles) */\n.button-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));\n gap: 8px; /* tighter spacing */\n margin-bottom: 20px;\n}\n\n/* TILE BUTTONS */\n.tile-btn {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: #000;\n border: 1px solid var(--phosphor-dim);\n color: var(--phosphor-dim);\n padding: 4px 6px;\n height: 60px; /* compact height */\n font-size: 0.75rem;\n gap: 2px; /* smaller space between icon and label */\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s ease;\n position: relative;\n overflow: hidden;\n}\n\n.tile-btn svg {\n margin-bottom: 4px;\n opacity: 0.6;\n transition: all 0.2s;\n width: 20px;\n height: 20px;\n}\n\n.tile-info {\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 100%;\n}\n\n.tile-label {\n font-size: 0.7rem;\n letter-spacing: 1px;\n font-weight: bold;\n text-align: center;\n}\n\n.tile-count {\n font-size: 0.65rem;\n position: absolute;\n top: 3px;\n right: 5px;\n opacity: 0.6;\n}\n\n/* Hover State */\n.tile-btn:hover {\n border-color: var(--phosphor-main);\n color: var(--phosphor-main);\n box-shadow: 0 0 8px rgba(51, 255, 0, 0.2);\n transform: translateY(-1px);\n}\n\n.tile-btn:hover svg {\n opacity: 1;\n filter: drop-shadow(0 0 4px var(--phosphor-main));\n}\n\n/* Active State */\n.tile-btn.active {\n background: var(--phosphor-main);\n color: #000;\n border-color: var(--phosphor-main);\n box-shadow: 0 0 10px rgba(51, 255, 0, 0.4);\n}\n\n.tile-btn.active svg {\n opacity: 1;\n color: #000;\n stroke: #000;\n filter: none;\n}\n\n/* MAIN ACTION BUTTON (New Entry) */\n.new-cheat-button.main-action {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 40px; /* slightly shorter */\n background: rgba(51, 255, 0, 0.1);\n border: 1px solid var(--phosphor-main);\n color: var(--phosphor-main);\n padding: 0 16px;\n font-weight: bold;\n}\n\n.new-cheat-button.main-action:hover {\n background: var(--phosphor-main);\n color: #000;\n box-shadow: 0 0 12px var(--phosphor-main);\n}\n\n.blink-text {\n animation: blink 1.5s infinite;\n margin-left: 6px;\n color: var(--phosphor-main);\n}\n\n\n/* =========================================================\n NO RESULTS (DATA VOID)\n========================================================= */\n\n.no-results-panel {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 60px 20px;\n min-height: 400px;\n border-style: dashed; /* Dashed border distinguishes empty state */\n position: relative;\n overflow: hidden;\n background: rgba(0, 5, 0, 0.9);\n}\n\n.icon-wrapper {\n margin-bottom: 20px;\n color: var(--phosphor-dim);\n animation: float 4s ease-in-out infinite;\n}\n\n@keyframes float {\n 0% { transform: translateY(0px); opacity: 0.6; }\n 50% { transform: translateY(-10px); opacity: 0.3; }\n 100% { transform: translateY(0px); opacity: 0.6; }\n}\n\n/* ERROR GLITCH TITLE */\n.glitch-error {\n font-size: 4rem;\n margin: 0 0 20px 0;\n color: var(--phosphor-dim);\n position: relative;\n letter-spacing: 5px;\n}\n\n.glitch-error::before,\n.glitch-error::after {\n content: attr(data-text);\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: #000;\n opacity: 0.7;\n}\n\n.glitch-error::before {\n left: 2px;\n text-shadow: -1px 0 #ff3333; /* Red shift for error feel */\n clip: rect(24px, 550px, 90px, 0);\n animation: glitch-anim-2 3s infinite linear alternate-reverse;\n}\n\n.glitch-error::after {\n left: -2px;\n text-shadow: -1px 0 var(--phosphor-main);\n clip: rect(85px, 550px, 140px, 0);\n animation: glitch-anim 2.5s infinite linear alternate-reverse;\n}\n\n/* ERROR TEXT DETAILS */\n.error-details {\n font-family: 'Courier New', monospace;\n font-size: 1rem;\n color: var(--phosphor-dim);\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.error-details p {\n margin: 0;\n}\n\n.blink-warning {\n margin-top: 15px;\n color: #ff3333; /* Red warning text */\n text-shadow: 0 0 5px #ff3333;\n animation: blink 0.5s step-end infinite alternate;\n}\n\n/* =========================================================\n RETRO TAGS / BADGES\n========================================================= */\n\n.tags-cell {\n vertical-align: middle;\n}\n\n.tag-wrapper {\n display: flex;\n flex-direction: column; /* Stack them for compactness */\n gap: 6px;\n align-items: flex-start;\n}\n\n.retro-badge {\n font-family: 'Courier New', monospace;\n font-size: 0.75rem;\n font-weight: bold;\n letter-spacing: 1px;\n padding: 2px 4px;\n white-space: nowrap;\n}\n\n/* STYLE 1: LANGUAGE (Bracket Style) */\n/* Looks like: [ JS ] */\n.lang-badge {\n color: var(--phosphor-main);\n border: none;\n text-shadow: 0 0 2px var(--phosphor-main);\n}\n\n/* STYLE 2: CATEGORY (Solid Block Style) */\n/* Looks like: PUBLIC (Black text on Green bg) */\n.cat-badge {\n background: var(--phosphor-dim);\n color: #000;\n padding: 2px 6px;\n box-shadow: 0 0 5px rgba(51, 255, 0, 0.3);\n}\n\n/* Hover effect for a bit of life */\n.cheat-item:hover .cat-badge {\n background: var(--phosphor-main); /* Brighten on hover */\n}\n\n\n/* =========================================================\n COMPACT CODE ACTIONS\n========================================================= */\n\n.code-cell.compact {\n width: 160px; /* Fixed width to prevent jumping */\n}\n\n.compact-actions {\n display: flex;\n gap: 8px;\n}\n\n.mini-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 0.8rem;\n padding: 4px 8px;\n background: black;\n border: 1px solid var(--phosphor-dim);\n color: var(--phosphor-dim);\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.mini-btn:hover {\n border-color: var(--phosphor-main);\n color: var(--phosphor-main);\n box-shadow: 0 0 8px rgba(51, 255, 0, 0.2);\n}\n\n/* Success state for Copy button */\n.mini-btn.success {\n border-color: var(--phosphor-main);\n background: var(--phosphor-main);\n color: black;\n}\n\n/* =========================================================\n RETRO CODE MODAL\n========================================================= */\n\n.retro-modal-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n background: rgba(0, 0, 0, 0.85); /* Dim background */\n backdrop-filter: blur(2px); /* Slight blur behind */\n z-index: 9999;\n display: flex;\n justify-content: center;\n align-items: center;\n animation: fade-in 0.2s ease-out;\n}\n\n.retro-modal-content {\n background: #000;\n border: 4px double var(--phosphor-main);\n width: 80%;\n max-width: 800px;\n max-height: 80vh;\n display: flex;\n flex-direction: column;\n box-shadow: 0 0 30px rgba(51, 255, 0, 0.2);\n animation: scale-up 0.2s ease-out;\n position: relative;\n}\n\n/* Modal Header */\n.modal-header {\n background: var(--phosphor-dim);\n color: #000;\n padding: 8px 12px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n font-weight: bold;\n}\n\n.close-btn {\n background: transparent;\n border: none;\n color: #000;\n padding: 0;\n box-shadow: none;\n}\n.close-btn:hover {\n background: transparent;\n color: #fff;\n box-shadow: none;\n transform: scale(1.1);\n}\n\n/* Modal Body (Scrollable Code) */\n.modal-body {\n padding: 20px;\n overflow-y: auto;\n background: #050a05;\n}\n\n.modal-body pre {\n margin: 0;\n white-space: pre-wrap;\n color: var(--phosphor-main);\n font-family: 'Courier New', monospace;\n font-size: 1rem;\n}\n\n/* Modal Footer */\n.modal-footer {\n border-top: 1px dashed var(--phosphor-dim);\n padding: 5px 12px;\n text-align: right;\n font-size: 0.8rem;\n color: var(--phosphor-dim);\n}\n\n@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }\n@keyframes scale-up { from { transform: scale(0.9); } to { transform: scale(1); } }\n\n.modal-header {\n background: var(--phosphor-dim);\n color: #000;\n padding: 8px 12px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n font-weight: bold;\n}\n\n/* NEW: Wrapper for the buttons on the right */\n.modal-controls {\n display: flex;\n align-items: center;\n gap: 15px;\n}\n\n/* NEW: The Modal Copy Button */\n.modal-copy-btn {\n background: #000;\n color: var(--phosphor-main);\n border: 1px solid #000;\n padding: 2px 8px;\n font-size: 0.8rem;\n display: flex;\n align-items: center;\n gap: 6px;\n box-shadow: none;\n}\n\n.modal-copy-btn:hover {\n background: var(--phosphor-main);\n color: #000;\n text-shadow: none;\n box-shadow: 0 0 5px rgba(0,0,0,0.5);\n}\n\n.modal-copy-btn.success {\n background: #fff;\n color: #000;\n border-color: #fff;\n}",
"notes": "Final version clean and current",
"language_id": 1,
"category_id": 9
},
{
"title": "Boutique Minimal Theme",
"code": "/* ============================================\n DEMOLITION - BOUTIQUE MINIMAL THEME\n Cream & Charcoal with vibrant accents\n Tailwind-inspired, fast & responsive\n ============================================ */\n\n/* ============================================\n GLOBAL RESETS & BASE\n ============================================ */\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n margin: 0;\n background: #faf8f5;\n color: #2d2d2d;\n font-family: -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', system-ui, sans-serif;\n font-size: 15px;\n line-height: 1.6;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n/* ============================================\n THEME TOGGLE\n ============================================ */\n\n.theme-toggle {\n position: fixed;\n top: 20px;\n right: 20px;\n display: flex;\n gap: 8px;\n align-items: center;\n background: white;\n padding: 8px 16px;\n border-radius: 100px;\n box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);\n z-index: 9999;\n border: 1px solid #e8e6e1;\n}\n\n.theme-label {\n font-size: 12px;\n color: #6b6b6b;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.theme-btn {\n padding: 6px 14px;\n font-size: 12px;\n background: transparent;\n color: #6b6b6b;\n border: none;\n border-radius: 100px;\n cursor: pointer;\n font-weight: 500;\n transition: all 0.2s ease;\n}\n\n.theme-btn:hover {\n background: #f5f3f0;\n color: #2d2d2d;\n}\n\n.theme-btn.active {\n background: #2d2d2d;\n color: white;\n}\n\n/* ============================================\n NAVBAR\n ============================================ */\n\n.navbar-container {\n background: white;\n padding: 16px 32px;\n border-bottom: 1px solid #e8e6e1;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);\n}\n\n.navbar-container nav {\n display: flex;\n gap: 24px;\n align-items: center;\n max-width: 1400px;\n margin: 0 auto;\n}\n\n.navbar-container a {\n color: #6b6b6b;\n text-decoration: none;\n font-size: 14px;\n font-weight: 500;\n padding: 8px 16px;\n border-radius: 8px;\n transition: all 0.2s ease;\n}\n\n.navbar-container a:hover {\n color: #2d2d2d;\n background: #f5f3f0;\n}\n\n.navbar-container a.active {\n background: #2d2d2d;\n color: white;\n}\n\n.navbar-container button {\n padding: 8px 20px;\n background: #ff6b6b;\n color: white;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n margin-left: auto;\n transition: all 0.2s ease;\n}\n\n.navbar-container button:hover {\n background: #ff5252;\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(255, 107, 107, 0.3);\n}\n\n/* ============================================\n HOMEPAGE CONTAINER\n ============================================ */\n\n.homepage-container {\n padding: 32px;\n max-width: 1400px;\n margin: 0 auto;\n}\n\n.homepage-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 32px;\n padding-bottom: 24px;\n border-bottom: 2px solid #e8e6e1;\n}\n\n.homepage-welcome {\n font-size: 32px;\n font-weight: 700;\n color: #2d2d2d;\n letter-spacing: -0.5px;\n}\n\n/* ============================================\n BUTTONS\n ============================================ */\n\nbutton,\n.toggle-button,\n.sort-button,\n.add-button,\n.genre-button,\n.status-button {\n padding: 10px 20px;\n background: white;\n color: #2d2d2d;\n border: 1.5px solid #e8e6e1;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n font-family: inherit;\n}\n\nbutton:hover,\n.toggle-button:hover,\n.sort-button:hover,\n.add-button:hover,\n.genre-button:hover,\n.status-button:hover {\n border-color: #2d2d2d;\n background: #faf8f5;\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n}\n\n.genre-button.active,\n.status-button.active {\n background: #6366f1;\n color: white;\n border-color: #6366f1;\n}\n\n.genre-button.active:hover,\n.status-button.active:hover {\n background: #4f46e5;\n border-color: #4f46e5;\n}\n\n/* Add button accent */\n.add-button {\n background: #10b981;\n color: white;\n border-color: #10b981;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.add-button:hover {\n background: #059669;\n border-color: #059669;\n}\n/* ============================================\n CATEGORY & GENRE BUTTONS SPACING\n ============================================ */\n\n.user-genre-buttons,\n.user-status-buttons {\n display: flex;\n flex-wrap: wrap; /* Wrap buttons to new lines if needed */\n gap: 12px 16px; /* Vertical 12px, horizontal 16px spacing */\n padding: 24px; /* More breathing room inside container */\n margin-bottom: 24px; /* Space below the container */\n background: white;\n border-radius: 12px;\n border: 1px solid #e8e6e1;\n box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);\n}\n\n.genre-button,\n.status-button {\n flex: none; /* Prevent buttons from stretching */\n min-width: 100px; /* Optional: uniform button size */\n text-align: center;\n padding: 12px 24px; /* Slightly larger click area */\n font-size: 14px;\n}\n\n@media (max-width: 768px) {\n .user-genre-buttons,\n .user-status-buttons {\n justify-content: flex-start;\n gap: 10px 12px;\n padding: 16px;\n }\n\n .genre-button,\n .status-button {\n padding: 10px 16px;\n min-width: 80px;\n }\n}\n/* Cancel button */\n.cancel-btn {\n background: white;\n border-color: #ff6b6b;\n color: #ff6b6b;\n}\n\n.cancel-btn:hover {\n background: #ff6b6b;\n color: white;\n}\n\n/* Submit button */\nbutton[type=\"submit\"] {\n background: #2d2d2d;\n color: white;\n border-color: #2d2d2d;\n}\n\nbutton[type=\"submit\"]:hover {\n background: #1a1a1a;\n border-color: #1a1a1a;\n}\n\n/* Secondary buttons */\n.secondary-btn {\n background: #f5f3f0;\n border-color: #e8e6e1;\n font-size: 13px;\n padding: 8px 16px;\n}\n\n/* ============================================\n INPUTS & FORMS\n ============================================ */\n\ninput,\ntextarea,\nselect {\n width: 100%;\n padding: 12px 16px;\n background: white;\n border: 1.5px solid #e8e6e1;\n border-radius: 8px;\n color: #2d2d2d;\n font-family: inherit;\n font-size: 15px;\n transition: all 0.2s ease;\n}\n\ninput:focus,\ntextarea:focus,\nselect:focus {\n outline: none;\n border-color: #6366f1;\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n}\n\ninput::placeholder,\ntextarea::placeholder {\n color: #9ca3af;\n}\n\nlabel,\nlabel span {\n color: #2d2d2d;\n font-size: 14px;\n font-weight: 600;\n margin-bottom: 8px;\n display: block;\n}\n\n/* ============================================\n FILTER SECTIONS\n ============================================ */\n\n.user-genre-buttons,\n.user-status-buttons {\n padding: 20px;\n margin-bottom: 20px;\n background: white;\n border-radius: 12px;\n border: 1px solid #e8e6e1;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);\n}\n\n.active-filters {\n display: flex;\n gap: 12px;\n align-items: center;\n margin-bottom: 20px;\n padding: 16px;\n background: white;\n border-radius: 12px;\n border: 1px solid #e8e6e1;\n}\n\n.active-filters span {\n color: #6b6b6b;\n font-size: 13px;\n font-weight: 600;\n}\n\n.filter-tag {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n background: #fef3c7;\n color: #92400e;\n border-radius: 100px;\n font-size: 13px;\n font-weight: 600;\n border: 1px solid #fde68a;\n}\n\n.filter-tag button {\n background: none;\n border: none;\n color: #92400e;\n padding: 0;\n font-size: 16px;\n cursor: pointer;\n font-weight: bold;\n}\n\n.filter-tag button:hover {\n color: #78350f;\n transform: none;\n box-shadow: none;\n}\n\n/* ============================================\n SEARCH BAR\n ============================================ */\n\n.song-search-bar {\n position: relative;\n margin-bottom: 20px;\n}\n\n.song-search-bar input {\n padding-right: 44px;\n}\n\n.clear-search {\n position: absolute;\n right: 12px;\n top: 50%;\n transform: translateY(-50%);\n background: none;\n border: none;\n color: #9ca3af;\n font-size: 24px;\n cursor: pointer;\n padding: 4px;\n line-height: 1;\n transition: color 0.2s;\n}\n\n.clear-search:hover {\n color: #ff6b6b;\n}\n\n/* ============================================\n CONTROLS HEADER\n ============================================ */\n\n.controls-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n}\n\n/* ============================================\n TABLES\n ============================================ */\n\ntable,\n.songlist-table,\n.statebar-table {\n width: 100%;\n border-collapse: separate;\n border-spacing: 0;\n background: white;\n border-radius: 12px;\n overflow: visible; /* Change to visible */\n border: 1px solid #e8e6e1;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);\n}\n\nthead,\n.songlist-table thead,\n.statebar-table thead {\n background: #faf8f5;\n}\n\nth {\n padding: 16px;\n text-align: left;\n color: #2d2d2d;\n font-size: 13px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n border-bottom: 2px solid #e8e6e1;\n}\n\ntbody tr,\n.song-item-row {\n border-bottom: 1px solid #f5f3f0;\n transition: all 0.2s ease;\n}\n\ntbody tr:hover,\n.song-item-row:hover {\n background: #faf8f5;\n}\n\ntbody tr:last-child {\n border-bottom: none;\n}\n\ntd {\n padding: 16px;\n color: #2d2d2d;\n font-size: 14px;\n}\n\n.song-item-date {\n color: #9ca3af;\n font-size: 13px;\n}\n\n/* State Bar */\n.section-header {\n background: #e0e7ff;\n color: #4f46e5;\n text-align: center;\n font-weight: 700;\n}\n\n.section-divider {\n background: #f5f3f0;\n}\n\n.id-badge {\n color: #9ca3af;\n font-size: 12px;\n font-weight: 400;\n}\n\n.status-true {\n color: #10b981;\n font-weight: 700;\n}\n\n.status-false {\n color: #ef4444;\n font-weight: 700;\n}\n\n/* ============================================\n LINKS & BUBBLES\n ============================================ */\n\na {\n color: #6366f1;\n text-decoration: none;\n transition: color 0.2s;\n}\n\na:hover {\n color: #4f46e5;\n}\n\n.links-toggle {\n background: white;\n border: 1.5px solid #e8e6e1;\n color: #6366f1;\n padding: 6px 12px;\n font-size: 13px;\n font-weight: 600;\n border-radius: 6px;\n}\n\n.links-toggle:hover {\n background: #eef2ff;\n border-color: #6366f1;\n}\n\n.links-bubble {\n position: absolute;\n top: 100%;\n left: 0;\n margin-top: 8px;\n background: white;\n border: 1px solid #e8e6e1;\n border-radius: 12px;\n padding: 12px;\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);\n z-index: 1000;\n display: flex;\n flex-direction: column;\n gap: 8px;\n min-width: 160px;\n}\n\n.link-button {\n padding: 10px 14px;\n background: #faf8f5;\n border: 1px solid #e8e6e1;\n border-radius: 8px;\n color: #2d2d2d;\n font-size: 13px;\n font-weight: 500;\n text-align: center;\n transition: all 0.2s ease;\n}\n\n.link-button:hover {\n background: #6366f1;\n color: white;\n border-color: #6366f1;\n transform: translateX(2px);\n}\n\n.song-item-actions {\n position: relative;\n}\n\n/* ============================================\n CARDS\n ============================================ */\n\n.song-form-page,\n.login-page-container {\n min-height: 100vh;\n display: flex;\n align-items: flex-start;\n justify-content: center;\n padding: 48px 24px;\n}\n\n.song-form-card,\n.song-card,\n.login-card {\n background: white;\n padding: 40px;\n border-radius: 16px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);\n width: 100%;\n max-width: 700px;\n border: 1px solid #e8e6e1;\n}\n\n.song-form-card h2,\n.song-card h3,\n.login-card h1 {\n color: #2d2d2d;\n font-size: 32px;\n font-weight: 700;\n margin-bottom: 32px;\n text-align: center;\n letter-spacing: -0.5px;\n}\n\n.song-card:hover {\n box-shadow: 0 12px 48px rgba(0, 0, 0, 0.12);\n}\n\n.song-card p {\n margin: 12px 0;\n color: #2d2d2d;\n font-size: 15px;\n line-height: 1.6;\n}\n\n.song-card p strong {\n color: #1a1a1a;\n font-weight: 600;\n}\n\n/* ============================================\n FORM LAYOUT\n ============================================ */\n\n.song-form-card label {\n display: block;\n margin-bottom: 20px;\n}\n\n.form-row {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 20px;\n margin-bottom: 20px;\n}\n\n.form-buttons {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 16px;\n margin-top: 32px;\n}\n\n/* ============================================\n ARTIST AUTOCOMPLETE\n ============================================ */\n\n.artist-suggestions {\n position: absolute;\n width: 100%;\n max-height: 240px;\n overflow-y: auto;\n background: white;\n border: 1px solid #e8e6e1;\n border-top: none;\n border-radius: 0 0 8px 8px;\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);\n z-index: 10;\n}\n\n.artist-suggestion-item {\n padding: 12px 16px;\n cursor: pointer;\n color: #2d2d2d;\n font-size: 14px;\n border-bottom: 1px solid #f5f3f0;\n transition: all 0.15s;\n}\n\n.artist-suggestion-item:hover {\n background: #eef2ff;\n color: #4f46e5;\n}\n\n/* ============================================\n LINKS SECTION\n ============================================ */\n\n.links-section {\n margin-top: 32px;\n padding-top: 32px;\n border-top: 2px solid #e8e6e1;\n}\n\n.links-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n}\n\n.saved-links-container,\n.pending-links-container {\n margin-top: 16px;\n padding: 16px;\n background: #faf8f5;\n border-radius: 8px;\n border: 1px solid #e8e6e1;\n}\n\n.pending-links-container {\n background: #fef3c7;\n border-color: #fde68a;\n}\n\n.links-label {\n font-weight: 700;\n color: #2d2d2d;\n display: block;\n margin-bottom: 12px;\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.pending-links-container .links-label {\n color: #92400e;\n}\n\n.link-item {\n display: flex;\n gap: 12px;\n font-size: 14px;\n margin-top: 8px;\n}\n\n.link-type {\n font-weight: 600;\n min-width: 100px;\n color: #6366f1;\n}\n\n.link-url {\n word-break: break-all;\n color: #2d2d2d;\n}\n\n.pending-link-item {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-top: 8px;\n}\n\n.remove-link-btn {\n background: none !important;\n border: none !important;\n color: #ff6b6b !important;\n font-size: 20px;\n padding: 0 !important;\n cursor: pointer;\n transition: color 0.2s;\n}\n\n.remove-link-btn:hover {\n color: #ff5252 !important;\n transform: none !important;\n box-shadow: none !important;\n}\n\n/* ============================================\n BACK BUTTON\n ============================================ */\n\n.back-btn {\n background: none !important;\n border: none !important;\n color: #6366f1 !important;\n padding: 0 !important;\n margin-bottom: 20px;\n display: inline-flex;\n align-items: center;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: color 0.2s;\n box-shadow: none !important;\n}\n\n.back-btn:hover {\n color: #4f46e5 !important;\n text-decoration: underline;\n background: none !important;\n transform: none !important;\n}\n\n/* ============================================\n ERROR PAGE\n ============================================ */\n\n.error-container {\n min-height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 48px;\n}\n\n.error-content {\n background: white;\n padding: 48px;\n border-radius: 16px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);\n text-align: center;\n max-width: 600px;\n border: 1px solid #e8e6e1;\n}\n\n.error-content h1 {\n font-size: 72px;\n color: #ff6b6b;\n margin-bottom: 24px;\n font-weight: 700;\n}\n\n.error-content p {\n font-size: 16px;\n color: #6b6b6b;\n margin-bottom: 16px;\n line-height: 1.6;\n}\n\n.error-content i {\n color: #9ca3af;\n font-size: 14px;\n}\n\n.error-home-button {\n margin-top: 32px;\n padding: 12px 32px;\n background: #2d2d2d;\n color: white;\n border: none;\n border-radius: 8px;\n font-size: 15px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s;\n}\n\n.error-home-button:hover {\n background: #1a1a1a;\n transform: translateY(-2px);\n box-shadow: 0 8px 24px rgba(45, 45, 45, 0.25);\n}\n/* ============================================\n LOGIN/SIGNUP\n ============================================ */\n\n.login-card form {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.login-error {\n background: #fee2e2;\n color: #991b1b;\n padding: 14px;\n border-radius: 8px;\n font-size: 14px;\n border: 1px solid #fecaca;\n}\n\n.login-card p {\n text-align: center;\n margin-top: 20px;\n color: #6b6b6b;\n font-size: 14px;\n}\n\n.login-card p a {\n color: #6366f1;\n font-weight: 600;\n text-decoration: underline;\n}\n\n/* ============================================\n SONG CARD BUTTONS\n ============================================ */\n\n.song-card-buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n margin: 20px 0;\n padding-top: 20px;\n border-top: 1px solid #e8e6e1;\n}\n\n.song-card-buttons:first-of-type {\n border-top: none;\n padding-top: 0;\n margin-top: 16px;\n}\n\n.link-btn {\n padding: 10px 18px;\n background: #6366f1;\n color: white;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n font-size: 13px;\n font-weight: 600;\n transition: all 0.2s;\n text-decoration: none;\n display: inline-block;\n}\n\n.link-btn:hover {\n background: #4f46e5;\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);\n}\n\n/* Action buttons (Edit/Delete) */\n.song-card-buttons:last-child button:first-child {\n background: #f59e0b;\n color: white;\n border: none;\n}\n\n.song-card-buttons:last-child button:first-child:hover {\n background: #d97706;\n}\n\n.song-card-buttons:last-child button:last-child {\n background: #ef4444;\n color: white;\n border: none;\n}\n\n.song-card-buttons:last-child button:last-child:hover {\n background: #dc2626;\n}\n\n/* ============================================\n LINK FORM\n ============================================ */\n\n.link-form {\n margin-top: 16px;\n padding: 16px;\n border: 1px dashed #e8e6e1;\n border-radius: 8px;\n background: #faf8f5;\n}\n\n.link-form > div {\n display: flex;\n gap: 12px;\n align-items: flex-end;\n}\n\n.link-form label {\n flex: 3;\n}\n\n.link-form label:last-of-type {\n flex: 1;\n}\n\n.link-form button {\n padding: 12px 20px;\n background: #10b981;\n color: white;\n border: none;\n border-radius: 8px;\n font-weight: 600;\n}\n\n.link-form button:hover {\n background: #059669;\n}\n\n.link-form button:disabled {\n background: #d1d5db;\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n/* ============================================\n MISC\n ============================================ */\n\n.no-songs,\n.no-songs-message {\n text-align: center;\n padding: 48px;\n color: #9ca3af;\n font-size: 16px;\n}\n\n.songlist-container {\n padding: 0;\n margin-top: 0;\n}\n\n.statebar-container {\n padding: 0;\n margin-bottom: 20px;\n background: transparent;\n border: none;\n}\n\n/* ============================================\n SCROLLBAR\n ============================================ */\n\n::-webkit-scrollbar {\n width: 10px;\n height: 10px;\n}\n\n::-webkit-scrollbar-track {\n background: #faf8f5;\n}\n\n::-webkit-scrollbar-thumb {\n background: #d1d5db;\n border-radius: 10px;\n}\n\n::-webkit-scrollbar-thumb:hover {\n background: #9ca3af;\n}\n\n/* ============================================\n SELECTION\n ============================================ */\n\n::selection {\n background: #c7d2fe;\n color: #1e1b4b;\n}\n\n/* ============================================\n RESPONSIVE\n ============================================ */\n\n@media (max-width: 768px) {\n .homepage-container {\n padding: 20px;\n }\n\n .homepage-header {\n flex-direction: column;\n gap: 16px;\n align-items: flex-start;\n }\n\n .homepage-welcome {\n font-size: 24px;\n }\n\n .controls-header {\n flex-direction: column;\n gap: 12px;\n }\n\n .form-row {\n grid-template-columns: 1fr;\n }\n\n .navbar-container nav {\n flex-wrap: wrap;\n gap: 12px;\n }\n\n .song-form-card,\n .song-card,\n .login-card {\n padding: 24px;\n }\n\n th, td {\n padding: 12px 8px;\n font-size: 13px;\n }\n\n .link-form > div {\n flex-direction: column;\n align-items: stretch;\n }\n\n .link-form label {\n flex: 1 !important;\n }\n}",
"notes": "Inspired by Tailwind",
"language_id": 1,
"category_id": 9
},
{
"title": "Export all code from project",
"code": "import os\n\nIGNORE_DIRS = {\n 'node_modules', '.git', '__pycache__',\n 'venv', '.venv', 'env',\n '.vscode', 'dist', 'build', 'coverage'\n}\n\nIGNORE_EXTENSIONS = {\n '.png', '.jpg', '.jpeg', '.gif', '.ico', '.svg',\n '.pyc', '.zip', '.tar', '.gz', '.map', '.lock',\n '.woff', '.woff2', '.ttf', '.eot', '.mp3', '.mp4'\n}\n\nIGNORE_FILES = {\n 'package-lock.json', 'yarn.lock',\n '.DS_Store', 'pack_project.py',\n 'project_context.txt'\n}\n\ndef pack_files(start_path='.'):\n with open('project_context.txt', 'w', encoding='utf-8') as outfile:\n for root, dirs, files in os.walk(start_path):\n dirs[:] = [d for d in dirs if d not in IGNORE_DIRS]\n\n for file in files:\n if file in IGNORE_FILES:\n continue\n\n _, ext = os.path.splitext(file)\n if ext.lower() in IGNORE_EXTENSIONS:\n continue\n\n filepath = os.path.join(root, file)\n\n try:\n with open(filepath, 'r', encoding='utf-8') as infile:\n content = infile.read()\n except Exception:\n continue\n\n outfile.write(\"\\n\" + \"=\" * 60 + \"\\n\")\n outfile.write(f\"FILE: {filepath}\\n\")\n outfile.write(\"=\" * 60 + \"\\n\\n\")\n outfile.write(content + \"\\n\")\n\nif __name__ == \"__main__\":\n pack_files()\n print(\"Done! Saved to project_context.txt\")\n",
"notes": "In root, create 'pack_project.py' and run python pack_project.py for backend, and python3 pack_project.py for Frontend",
"language_id": 5,
"category_id": 7
},
{
"title": "Search code for text",
"code": "grep -rn \"useCatering\" src/ \u2192 include line numbers\ngrep -r \"useCatering(\" src/ \u2192 find function calls specifically\ngrep -rl \"useCatering\" src/ \u2192 list only filenames containing it",
"notes": "Find where a hook, function, or identifier is used, trace imports or references across a codebase",
"language_id": 9,
"category_id": 7
},
{
"title": "Color Palette ",
"code": "Orange: #eb5638\nBlack: #2b2b2b \nWhite: #ebe5c0",
"notes": "Color list with css hex codes",
"language_id": 1,
"category_id": 5
}
]
}