feat(developers): add developer program signup with SilverDESK integration

Add developer application page with form submission that creates tickets
in SilverDESK. Includes provisioning service scaffolding for Mattermost,
Mailcow, and Gitea account creation. Fixes API key header casing
(X-API-Key) and ticket payload to match SilverDESK's CreateTicketDto
contract.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-21 20:51:36 +00:00
parent d2780e9295
commit 21c07adf54
11 changed files with 1056 additions and 3 deletions

View File

@@ -0,0 +1,423 @@
/* Developers Page Styles */
.dev-container {
max-width: 860px;
margin: 0 auto;
padding: 0 2rem 4rem;
}
.dev-header {
text-align: center;
margin-bottom: 3rem;
}
.dev-header h1 {
font-size: 2.8rem;
margin-bottom: 1rem;
background: linear-gradient(135deg, #4DD0E1 0%, #00B8D4 40%, #1E5A9E 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.dev-subtitle {
font-size: 1.15rem;
color: rgba(255, 255, 255, 0.7);
max-width: 600px;
margin: 0 auto;
line-height: 1.6;
}
/* Sections */
.dev-section {
background: rgba(255, 255, 255, 0.06);
backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
padding: 2rem;
margin-bottom: 1.5rem;
animation: devFadeIn 0.5s ease both;
}
.dev-section:nth-child(2) { animation-delay: 0.1s; }
.dev-section:nth-child(3) { animation-delay: 0.15s; }
.dev-section:nth-child(4) { animation-delay: 0.2s; }
.dev-section:nth-child(5) { animation-delay: 0.25s; }
.dev-section:nth-child(6) { animation-delay: 0.3s; }
@keyframes devFadeIn {
from { opacity: 0; transform: translateY(16px); }
to { opacity: 1; transform: translateY(0); }
}
.dev-section-fade-in {
animation: devFadeIn 0.4s ease both !important;
}
.dev-section-title {
font-size: 1.4rem;
margin-bottom: 0.75rem;
color: #4DD0E1;
}
.dev-section-desc {
color: rgba(255, 255, 255, 0.6);
margin-bottom: 1rem;
line-height: 1.5;
}
/* Role Selector */
.role-selector {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
.role-card {
background: rgba(255, 255, 255, 0.04);
border: 2px solid rgba(255, 255, 255, 0.12);
border-radius: 14px;
padding: 1.5rem;
cursor: pointer;
transition: all 0.25s ease;
text-align: center;
}
.role-card:hover {
border-color: rgba(77, 208, 225, 0.4);
background: rgba(77, 208, 225, 0.06);
}
.role-card.role-active {
border-color: #4DD0E1;
background: rgba(77, 208, 225, 0.1);
box-shadow: 0 0 24px rgba(77, 208, 225, 0.15);
}
.role-icon {
width: 56px;
height: 56px;
margin: 0 auto 0.75rem;
background: rgba(255, 255, 255, 0.08);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.25s ease;
}
.role-active .role-icon {
background: rgba(77, 208, 225, 0.18);
}
.role-icon svg {
width: 28px;
height: 28px;
stroke: rgba(255, 255, 255, 0.6);
transition: stroke 0.25s ease;
}
.role-active .role-icon svg {
stroke: #4DD0E1;
}
.role-card h3 {
font-size: 1.2rem;
margin-bottom: 0.4rem;
color: #fff;
}
.role-card p {
font-size: 0.85rem;
color: rgba(255, 255, 255, 0.55);
line-height: 1.4;
}
/* Form Elements */
.form-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1.25rem;
}
.form-group {
display: flex;
flex-direction: column;
}
.form-group label {
font-size: 0.85rem;
font-weight: 600;
color: rgba(255, 255, 255, 0.8);
margin-bottom: 0.4rem;
letter-spacing: 0.02em;
}
.form-input {
background: rgba(0, 0, 0, 0.25);
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 10px;
padding: 0.75rem 1rem;
color: #fff;
font-size: 0.95rem;
font-family: inherit;
transition: border-color 0.2s ease, box-shadow 0.2s ease;
outline: none;
width: 100%;
}
.form-input::placeholder {
color: rgba(255, 255, 255, 0.3);
}
.form-input:focus {
border-color: #4DD0E1;
box-shadow: 0 0 0 3px rgba(77, 208, 225, 0.12);
}
.form-textarea {
resize: vertical;
min-height: 100px;
}
.form-hint {
font-size: 0.78rem;
color: rgba(255, 255, 255, 0.4);
margin-top: 0.3rem;
}
/* Validation messages */
.validation-message {
color: #f87171;
font-size: 0.8rem;
margin-top: 0.3rem;
}
/* Platform Chips */
.platform-grid {
display: flex;
flex-wrap: wrap;
gap: 0.6rem;
}
.platform-chip {
display: flex;
align-items: center;
gap: 0.4rem;
padding: 0.5rem 1rem;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 100px;
cursor: pointer;
transition: all 0.2s ease;
color: rgba(255, 255, 255, 0.7);
font-size: 0.9rem;
user-select: none;
}
.platform-chip input[type="checkbox"] {
display: none;
}
.platform-chip:hover {
border-color: rgba(77, 208, 225, 0.4);
}
.platform-chip.platform-active {
background: rgba(77, 208, 225, 0.12);
border-color: #4DD0E1;
color: #4DD0E1;
}
/* Perks */
.dev-perks {
background: linear-gradient(135deg, rgba(30, 90, 158, 0.15) 0%, rgba(0, 184, 212, 0.08) 100%);
border-color: rgba(77, 208, 225, 0.2);
}
.perks-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
.perk-item {
display: flex;
flex-direction: column;
padding: 0.75rem;
background: rgba(255, 255, 255, 0.04);
border-radius: 10px;
}
.perk-item strong {
color: #4DD0E1;
font-size: 0.95rem;
margin-bottom: 0.2rem;
}
.perk-item span {
color: rgba(255, 255, 255, 0.55);
font-size: 0.82rem;
}
/* Submit Area */
.dev-submit-area {
text-align: center;
margin-top: 1.5rem;
margin-bottom: 2rem;
}
.dev-btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.85rem 2.5rem;
border-radius: 12px;
font-size: 1rem;
font-weight: 600;
text-decoration: none;
cursor: pointer;
transition: all 0.25s ease;
border: none;
font-family: inherit;
}
.dev-btn-primary {
background: linear-gradient(135deg, #1E5A9E 0%, #00B8D4 100%);
color: #fff;
box-shadow: 0 4px 20px rgba(0, 184, 212, 0.25);
}
.dev-btn-primary:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: 0 8px 30px rgba(0, 184, 212, 0.35);
}
.dev-btn-primary:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.dev-btn-secondary {
background: rgba(255, 255, 255, 0.1);
color: #fff;
border: 1px solid rgba(255, 255, 255, 0.2);
}
.dev-btn-secondary:hover {
background: rgba(255, 255, 255, 0.15);
}
.btn-spinner {
width: 18px;
height: 18px;
border: 2px solid rgba(255, 255, 255, 0.3);
border-top-color: #fff;
border-radius: 50%;
animation: spin 0.7s linear infinite;
}
/* Error / Success */
.dev-error {
background: rgba(248, 113, 113, 0.1);
border: 1px solid rgba(248, 113, 113, 0.3);
color: #f87171;
padding: 0.75rem 1rem;
border-radius: 10px;
margin-bottom: 1rem;
font-size: 0.9rem;
}
.dev-success-panel {
text-align: center;
padding: 4rem 2rem;
background: rgba(255, 255, 255, 0.06);
backdrop-filter: blur(12px);
border: 1px solid rgba(77, 208, 225, 0.25);
border-radius: 20px;
margin-bottom: 2rem;
animation: devFadeIn 0.5s ease both;
}
.success-icon {
width: 72px;
height: 72px;
margin: 0 auto 1.5rem;
background: rgba(77, 208, 225, 0.15);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.success-icon svg {
width: 36px;
height: 36px;
stroke: #4DD0E1;
}
.dev-success-panel h2 {
font-size: 1.8rem;
margin-bottom: 0.75rem;
color: #4DD0E1;
}
.dev-success-panel p {
color: rgba(255, 255, 255, 0.7);
margin-bottom: 2rem;
max-width: 500px;
margin-left: auto;
margin-right: auto;
line-height: 1.5;
}
/* Back Link - reuse from sdk-styles */
.dev-container .back-link {
display: inline-block;
margin-top: 1rem;
color: #4DD0E1;
text-decoration: none;
font-size: 1rem;
transition: color 0.2s ease;
}
.dev-container .back-link:hover {
color: #00B8D4;
}
/* Responsive */
@media (max-width: 768px) {
.dev-header h1 {
font-size: 2rem;
}
.role-selector {
grid-template-columns: 1fr;
}
.form-grid {
grid-template-columns: 1fr;
}
.perks-grid {
grid-template-columns: 1fr;
}
.dev-container {
padding: 0 1rem 3rem;
}
.dev-section {
padding: 1.5rem;
}
}
@media (max-width: 480px) {
.dev-header h1 {
font-size: 1.6rem;
}
.dev-subtitle {
font-size: 1rem;
}
}