Add support page, admin features, and auth hardening.

Rename public affiliate route to /support with localized nav labels, and include affiliate/social/wallpaper admin, 2FA login, and related site updates.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Atakan Doğan Özban
2026-07-29 20:25:55 +02:00
co-authored by Cursor
parent 202dc16a52
commit fc45c35dbe
149 changed files with 3496 additions and 11263 deletions
+59
View File
@@ -77,4 +77,63 @@ body {
.project-iframe {
border: 0;
}
/*
* Affiliate links
*/
.affiliate-list {
display: flex;
flex-direction: column;
gap: 0.9rem;
}
.affiliate-card {
display: flex;
align-items: center;
gap: 1rem;
padding: 0.85rem 1.1rem;
border-radius: 0.75rem;
background-color: rgba(255, 255, 255, .05);
border: 1px solid rgba(255, 255, 255, .1);
text-decoration: none;
color: inherit;
text-align: left;
transition: transform .2s ease, background-color .2s ease, border-color .2s ease, box-shadow .2s ease;
}
.affiliate-card:hover,
.affiliate-card:focus {
background-color: rgba(255, 255, 255, .1);
border-color: rgba(255, 255, 255, .3);
transform: translateY(-3px);
box-shadow: 0 .5rem 1.25rem rgba(0, 0, 0, .3);
color: inherit;
text-decoration: none;
}
.affiliate-logo {
flex-shrink: 0;
width: 3rem;
height: 3rem;
object-fit: contain;
background: #fff;
border-radius: 0.5rem;
padding: 0.25rem;
}
.affiliate-text {
min-width: 0;
}
.affiliate-title {
font-weight: 700;
color: #fff;
}
.affiliate-desc {
color: rgba(255, 255, 255, .6);
font-size: 0.9rem;
margin-top: 0.1rem;
}
@@ -0,0 +1,75 @@
var PasteImageModal = (function () {
var bsModal, targetEl, previewEl, defaultText;
var currentInputSelector, currentPreviewSelector;
function init() {
var modalEl = document.getElementById('pasteImageModal');
if (!modalEl || typeof bootstrap === 'undefined') return false;
targetEl = document.getElementById('pasteImageTarget');
previewEl = document.getElementById('pasteImageModalPreview');
defaultText = targetEl.textContent;
bsModal = new bootstrap.Modal(modalEl);
modalEl.addEventListener('shown.bs.modal', function () {
targetEl.textContent = defaultText;
previewEl.style.display = 'none';
previewEl.removeAttribute('src');
targetEl.focus();
});
targetEl.addEventListener('paste', function (e) {
var clipboard = e.clipboardData || window.clipboardData;
var items = clipboard ? clipboard.items : null;
if (!items) return;
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (item.kind === 'file' && item.type.indexOf('image/') === 0) {
e.preventDefault();
var blob = item.getAsFile();
if (!blob) continue;
var ext = (blob.type.split('/')[1] || 'png').toLowerCase();
var pastedFile = new File([blob], 'pasted-image-' + Date.now() + '.' + ext, { type: blob.type });
var input = document.querySelector(currentInputSelector);
if (input) {
var dt = new DataTransfer();
dt.items.add(pastedFile);
input.files = dt.files;
input.dispatchEvent(new Event('change', { bubbles: true }));
}
var url = URL.createObjectURL(pastedFile);
previewEl.src = url;
previewEl.style.display = '';
targetEl.textContent = 'Image pasted!';
if (currentPreviewSelector) {
var extPreview = document.querySelector(currentPreviewSelector);
if (extPreview) {
extPreview.src = url;
extPreview.style.display = '';
}
}
setTimeout(function () { bsModal.hide(); }, 400);
break;
}
}
});
return true;
}
function open(inputSelector, previewSelector) {
if (!bsModal && !init()) return;
currentInputSelector = inputSelector;
currentPreviewSelector = previewSelector || null;
bsModal.show();
}
return { open: open };
})();