1660 lines
59 KiB
Go Template
1660 lines
59 KiB
Go Template
{{template "base/head" .}}
|
||
{{if .IsSigned}}
|
||
{{template "user/dashboard/dashboard" .}}
|
||
{{else}}
|
||
<style>
|
||
/* ═══════════════════════════════════════════════════════════════════════
|
||
GitDXD 2026 Landing Page — Omarchy × JetBrains × GitHub/GitLab ×
|
||
CachyOS × Hack Club × Lovable
|
||
═══════════════════════════════════════════════════════════════════════ */
|
||
.page-content.home {
|
||
position: relative;
|
||
overflow-x: hidden;
|
||
padding-top: 0 !important;
|
||
}
|
||
|
||
/* Subtle architectural grid + dual aurora spotlight */
|
||
.dxd-backdrop {
|
||
position: absolute;
|
||
inset: 0;
|
||
pointer-events: none;
|
||
z-index: 0;
|
||
background-image:
|
||
linear-gradient(to right, rgba(148, 163, 184, 0.055) 1px, transparent 1px),
|
||
linear-gradient(to bottom, rgba(148, 163, 184, 0.055) 1px, transparent 1px);
|
||
background-size: 56px 56px;
|
||
mask-image: radial-gradient(ellipse 85% 55% at 50% 8%, #000 35%, transparent 90%);
|
||
-webkit-mask-image: radial-gradient(ellipse 85% 55% at 50% 8%, #000 35%, transparent 90%);
|
||
}
|
||
|
||
.dxd-landing {
|
||
--dxd-surface: var(--color-box-body, #111520);
|
||
--dxd-surface-hi: var(--color-box-body-highlight, #181f2e);
|
||
--dxd-bg: var(--color-body, #0b0d13);
|
||
--dxd-well: var(--color-input-background, #080a10);
|
||
--dxd-text: var(--color-text, #e2e8f0);
|
||
--dxd-focus: var(--color-text-focus, #f8fafc);
|
||
--dxd-muted: var(--color-text-light-2, #94a3b8);
|
||
--dxd-dim: var(--color-text-light-3, #64748b);
|
||
--dxd-accent: var(--color-primary, #38bdf8);
|
||
--dxd-teal: var(--color-teal, #2dd4bf);
|
||
--dxd-violet: var(--color-purple, #a78bfa);
|
||
--dxd-coral: var(--color-red, #fb7185);
|
||
--dxd-amber: var(--color-yellow, #fbbf24);
|
||
--dxd-emerald: var(--color-green, #34d399);
|
||
--dxd-border: var(--nm-divider, rgba(148, 163, 184, 0.14));
|
||
position: relative;
|
||
z-index: 1;
|
||
color: var(--dxd-text);
|
||
max-width: 1220px;
|
||
margin: 0 auto;
|
||
padding: 2.25rem 1.5rem 3rem;
|
||
}
|
||
|
||
/* ── Section Hairline Index (Omarchy / JetBrains style) ─────────── */
|
||
.dxd-sec-bar {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.85rem;
|
||
margin-bottom: 1.5rem;
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.73rem;
|
||
letter-spacing: 0.12em;
|
||
text-transform: uppercase;
|
||
}
|
||
.dxd-sec-idx {
|
||
color: var(--dxd-accent);
|
||
font-weight: 700;
|
||
padding: 0.25rem 0.6rem;
|
||
border-radius: 6px;
|
||
background: var(--color-primary-alpha-10, rgba(56, 189, 248, 0.10));
|
||
box-shadow: 0 0 0 1px var(--color-primary-alpha-20, rgba(56, 189, 248, 0.22));
|
||
}
|
||
.dxd-sec-line {
|
||
flex: 1;
|
||
height: 1px;
|
||
background: linear-gradient(90deg, var(--dxd-border), transparent 95%);
|
||
}
|
||
.dxd-sec-tag {
|
||
color: var(--dxd-dim);
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* ══════════════════════════════════════════════════════════════════
|
||
HERO — Centered Spotlight + Command Bar + Interactive Workbench
|
||
══════════════════════════════════════════════════════════════════ */
|
||
.dxd-hero {
|
||
text-align: center;
|
||
padding: 1.5rem 0 2.5rem;
|
||
}
|
||
|
||
.dxd-status-pill {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 0.6rem;
|
||
padding: 0.38rem 0.9rem;
|
||
border-radius: 999px;
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.74rem;
|
||
font-weight: 600;
|
||
color: var(--dxd-text);
|
||
background: var(--dxd-surface);
|
||
box-shadow: var(--nm-raised-xs);
|
||
margin-bottom: 1.4rem;
|
||
}
|
||
.dxd-status-pill .pulse {
|
||
width: 8px;
|
||
height: 8px;
|
||
border-radius: 50%;
|
||
background: var(--dxd-emerald);
|
||
box-shadow: 0 0 10px var(--dxd-emerald);
|
||
animation: dxdPulse 2.2s infinite ease-in-out;
|
||
}
|
||
.dxd-status-pill .sep {
|
||
color: var(--dxd-dim);
|
||
}
|
||
.dxd-status-pill a {
|
||
color: var(--dxd-accent) !important;
|
||
font-weight: 700;
|
||
}
|
||
@keyframes dxdPulse {
|
||
0%, 100% { opacity: 1; transform: scale(1); }
|
||
50% { opacity: 0.45; transform: scale(0.88); }
|
||
}
|
||
|
||
.dxd-hero h1 {
|
||
font-size: clamp(2.35rem, 5.2vw, 4.15rem);
|
||
line-height: 1.04;
|
||
font-weight: 800;
|
||
letter-spacing: -0.035em;
|
||
max-width: 18ch;
|
||
margin: 0 auto 1.15rem;
|
||
color: var(--dxd-focus);
|
||
}
|
||
.dxd-hero h1 em {
|
||
font-style: normal;
|
||
background: linear-gradient(120deg, var(--dxd-accent) 0%, var(--dxd-teal) 36%, var(--dxd-violet) 72%, var(--dxd-coral) 100%);
|
||
-webkit-background-clip: text;
|
||
background-clip: text;
|
||
color: transparent;
|
||
}
|
||
|
||
.dxd-lede {
|
||
font-size: clamp(1rem, 1.4vw, 1.16rem);
|
||
line-height: 1.65;
|
||
color: var(--dxd-muted);
|
||
max-width: 44rem;
|
||
margin: 0 auto 1.85rem;
|
||
}
|
||
|
||
.dxd-hero-actions {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
justify-content: center;
|
||
align-items: center;
|
||
gap: 0.75rem;
|
||
margin-bottom: 1.1rem;
|
||
}
|
||
.dxd-hero-actions .dxd-btn {
|
||
font-size: 0.96rem !important;
|
||
padding: 0.82rem 1.45rem !important;
|
||
border-radius: 10px !important;
|
||
}
|
||
|
||
/* Copyable git command bar */
|
||
.dxd-cmd-pill {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 0.65rem;
|
||
padding: 0.52rem 0.65rem 0.52rem 0.95rem;
|
||
border-radius: 10px;
|
||
background: var(--dxd-well);
|
||
box-shadow: var(--nm-inset-sm);
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.78rem;
|
||
color: var(--dxd-muted);
|
||
max-width: 100%;
|
||
}
|
||
.dxd-cmd-pill .prompt {
|
||
color: var(--dxd-emerald);
|
||
font-weight: 700;
|
||
user-select: none;
|
||
}
|
||
.dxd-cmd-pill code {
|
||
color: var(--dxd-text);
|
||
background: transparent !important;
|
||
padding: 0 !important;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
.dxd-cmd-copy {
|
||
border: none;
|
||
cursor: pointer;
|
||
padding: 0.32rem 0.62rem;
|
||
border-radius: 6px;
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.71rem;
|
||
font-weight: 600;
|
||
color: var(--dxd-accent);
|
||
background: var(--color-primary-alpha-10, rgba(56, 189, 248, 0.12));
|
||
transition: background 0.15s ease, color 0.15s ease;
|
||
}
|
||
.dxd-cmd-copy:hover {
|
||
background: var(--color-primary-alpha-20, rgba(56, 189, 248, 0.24));
|
||
}
|
||
|
||
.dxd-subnote {
|
||
margin: 0.8rem 0 2.4rem;
|
||
font-size: 0.85rem;
|
||
color: var(--dxd-dim);
|
||
}
|
||
.dxd-subnote a {
|
||
color: var(--dxd-accent) !important;
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* ══════════════════════════════════════════════════════════════════
|
||
INTERACTIVE WORKBENCH WINDOW (JetBrains × GitHub × GitLab)
|
||
══════════════════════════════════════════════════════════════════ */
|
||
.dxd-workbench {
|
||
text-align: left;
|
||
background: var(--dxd-surface);
|
||
border-radius: 16px;
|
||
box-shadow: var(--nm-raised);
|
||
overflow: hidden;
|
||
margin-bottom: 2.75rem;
|
||
}
|
||
|
||
.dxd-wb-titlebar {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 1rem;
|
||
padding: 0.65rem 1rem;
|
||
background: var(--color-header-wrapper, var(--dxd-well));
|
||
border-bottom: 1px solid var(--dxd-border);
|
||
flex-wrap: wrap;
|
||
}
|
||
.dxd-wb-dots {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.42rem;
|
||
}
|
||
.dxd-wb-dots span {
|
||
width: 11px;
|
||
height: 11px;
|
||
border-radius: 50%;
|
||
}
|
||
.dxd-wb-dots .r { background: #ec3750; }
|
||
.dxd-wb-dots .y { background: #fbbf24; }
|
||
.dxd-wb-dots .g { background: #34d399; }
|
||
|
||
.dxd-wb-tabs {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.35rem;
|
||
flex-wrap: wrap;
|
||
}
|
||
.dxd-wb-tab {
|
||
border: none;
|
||
cursor: pointer;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 0.45rem;
|
||
padding: 0.38rem 0.78rem;
|
||
border-radius: 8px;
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.75rem;
|
||
font-weight: 600;
|
||
color: var(--dxd-muted);
|
||
background: transparent;
|
||
transition: all 0.15s ease;
|
||
}
|
||
.dxd-wb-tab:hover {
|
||
color: var(--dxd-focus);
|
||
background: rgba(148, 163, 184, 0.08);
|
||
}
|
||
.dxd-wb-tab.is-active {
|
||
color: var(--dxd-accent);
|
||
background: var(--color-primary-alpha-10, rgba(56, 189, 248, 0.14));
|
||
box-shadow: 0 0 0 1px var(--color-primary-alpha-30, rgba(56, 189, 248, 0.30));
|
||
}
|
||
.dxd-wb-tab .badge {
|
||
font-size: 0.66rem;
|
||
padding: 0.08rem 0.4rem;
|
||
border-radius: 999px;
|
||
background: rgba(148, 163, 184, 0.14);
|
||
color: var(--dxd-text);
|
||
}
|
||
|
||
.dxd-wb-url {
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.72rem;
|
||
color: var(--dxd-dim);
|
||
padding: 0.25rem 0.65rem;
|
||
border-radius: 6px;
|
||
background: var(--dxd-well);
|
||
box-shadow: var(--nm-inset-sm);
|
||
}
|
||
|
||
.dxd-wb-pane {
|
||
display: none;
|
||
padding: 1.15rem 1.25rem;
|
||
}
|
||
.dxd-wb-pane.is-active {
|
||
display: block;
|
||
}
|
||
|
||
/* Pane 1: Repository + Split File Tree & Code View */
|
||
.dxd-repo-bar {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 0.75rem;
|
||
flex-wrap: wrap;
|
||
padding-bottom: 0.9rem;
|
||
margin-bottom: 0.95rem;
|
||
border-bottom: 1px solid var(--dxd-border);
|
||
}
|
||
.dxd-repo-id {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.7rem;
|
||
}
|
||
.dxd-repo-avatar {
|
||
width: 36px;
|
||
height: 36px;
|
||
border-radius: 9px;
|
||
display: grid;
|
||
place-items: center;
|
||
font-weight: 800;
|
||
font-size: 0.95rem;
|
||
color: #050811;
|
||
background: linear-gradient(135deg, var(--dxd-accent), var(--dxd-teal));
|
||
}
|
||
.dxd-repo-path {
|
||
font-size: 0.95rem;
|
||
color: var(--dxd-muted);
|
||
}
|
||
.dxd-repo-path strong {
|
||
color: var(--dxd-focus);
|
||
font-weight: 700;
|
||
}
|
||
.dxd-repo-meta {
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.72rem;
|
||
color: var(--dxd-dim);
|
||
}
|
||
.dxd-repo-pills {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.45rem;
|
||
flex-wrap: wrap;
|
||
}
|
||
.dxd-rpill {
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.71rem;
|
||
font-weight: 600;
|
||
padding: 0.28rem 0.65rem;
|
||
border-radius: 999px;
|
||
background: var(--dxd-well);
|
||
box-shadow: var(--nm-raised-xs);
|
||
color: var(--dxd-muted);
|
||
}
|
||
.dxd-rpill.ok { color: var(--dxd-emerald); }
|
||
.dxd-rpill.star { color: var(--dxd-amber); }
|
||
|
||
.dxd-repo-split {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1.35fr;
|
||
gap: 1rem;
|
||
align-items: stretch;
|
||
}
|
||
@media (max-width: 860px) {
|
||
.dxd-repo-split { grid-template-columns: 1fr; }
|
||
}
|
||
|
||
.dxd-tree {
|
||
background: var(--dxd-well);
|
||
border-radius: 10px;
|
||
box-shadow: var(--nm-inset-sm);
|
||
padding: 0.55rem;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 0.2rem;
|
||
}
|
||
.dxd-tree-head {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 0.35rem 0.55rem 0.5rem;
|
||
border-bottom: 1px solid var(--dxd-border);
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.72rem;
|
||
color: var(--dxd-dim);
|
||
}
|
||
.dxd-tree-head b { color: var(--dxd-accent); }
|
||
.dxd-tree-row {
|
||
border: none;
|
||
width: 100%;
|
||
text-align: left;
|
||
cursor: pointer;
|
||
display: grid;
|
||
grid-template-columns: 18px 1.1fr 1.2fr auto;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
padding: 0.42rem 0.55rem;
|
||
border-radius: 7px;
|
||
background: transparent;
|
||
color: var(--dxd-muted);
|
||
font-size: 0.76rem;
|
||
transition: background 0.14s ease;
|
||
}
|
||
.dxd-tree-row:hover,
|
||
.dxd-tree-row.is-selected {
|
||
background: var(--color-primary-alpha-10, rgba(56, 189, 248, 0.12));
|
||
}
|
||
.dxd-tree-row .fname {
|
||
font-family: var(--fonts-monospace);
|
||
color: var(--dxd-accent);
|
||
font-weight: 600;
|
||
}
|
||
.dxd-tree-row .fmsg {
|
||
color: var(--dxd-dim);
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
.dxd-tree-row .fage {
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.69rem;
|
||
color: var(--dxd-dim);
|
||
}
|
||
|
||
.dxd-codebox {
|
||
background: var(--dxd-well);
|
||
border-radius: 10px;
|
||
box-shadow: var(--nm-inset-sm);
|
||
overflow: hidden;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
.dxd-codebox-bar {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 0.45rem 0.8rem;
|
||
border-bottom: 1px solid var(--dxd-border);
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.72rem;
|
||
color: var(--dxd-muted);
|
||
}
|
||
.dxd-codebox-bar .lang {
|
||
color: var(--dxd-teal);
|
||
font-weight: 600;
|
||
}
|
||
.dxd-codebox pre {
|
||
margin: 0 !important;
|
||
padding: 0.85rem 1rem !important;
|
||
background: transparent !important;
|
||
box-shadow: none !important;
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.75rem;
|
||
line-height: 1.62;
|
||
color: var(--dxd-text);
|
||
overflow-x: auto;
|
||
}
|
||
.dxd-codebox .ln { color: var(--dxd-dim); user-select: none; margin-right: 0.85rem; }
|
||
.dxd-codebox .kw { color: var(--dxd-coral); font-weight: 600; }
|
||
.dxd-codebox .fn { color: var(--dxd-accent); }
|
||
.dxd-codebox .st { color: var(--dxd-emerald); }
|
||
.dxd-codebox .cm { color: var(--dxd-dim); font-style: italic; }
|
||
.dxd-codebox .va { color: var(--dxd-violet); }
|
||
|
||
/* Pane 2: Pull Request Diff */
|
||
.dxd-pr-head {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
flex-wrap: wrap;
|
||
gap: 0.75rem;
|
||
margin-bottom: 0.85rem;
|
||
}
|
||
.dxd-pr-title {
|
||
font-size: 0.95rem;
|
||
font-weight: 700;
|
||
color: var(--dxd-focus);
|
||
}
|
||
.dxd-pr-title span {
|
||
color: var(--dxd-dim);
|
||
font-family: var(--fonts-monospace);
|
||
font-weight: 500;
|
||
}
|
||
.dxd-pr-badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 0.35rem;
|
||
padding: 0.25rem 0.7rem;
|
||
border-radius: 999px;
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.72rem;
|
||
font-weight: 700;
|
||
color: var(--dxd-emerald);
|
||
background: rgba(52, 211, 153, 0.14);
|
||
box-shadow: 0 0 0 1px rgba(52, 211, 153, 0.32);
|
||
}
|
||
.dxd-diff {
|
||
background: var(--dxd-well);
|
||
border-radius: 10px;
|
||
box-shadow: var(--nm-inset-sm);
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.75rem;
|
||
overflow: hidden;
|
||
}
|
||
.dxd-diff-line {
|
||
padding: 0.28rem 0.85rem;
|
||
white-space: pre;
|
||
overflow-x: auto;
|
||
}
|
||
.dxd-diff-line.del {
|
||
background: rgba(236, 55, 80, 0.13);
|
||
color: #fda4af;
|
||
border-left: 3px solid var(--dxd-coral);
|
||
}
|
||
.dxd-diff-line.add {
|
||
background: rgba(16, 185, 129, 0.13);
|
||
color: #6ee7b7;
|
||
border-left: 3px solid var(--dxd-emerald);
|
||
}
|
||
.dxd-diff-line.ctx {
|
||
color: var(--dxd-muted);
|
||
}
|
||
|
||
/* Pane 3: Actions CI Pipeline */
|
||
.dxd-ci-stages {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(175px, 1fr));
|
||
gap: 0.75rem;
|
||
margin-bottom: 0.9rem;
|
||
}
|
||
.dxd-ci-stage {
|
||
padding: 0.7rem 0.85rem;
|
||
border-radius: 10px;
|
||
background: var(--dxd-well);
|
||
box-shadow: var(--nm-inset-sm);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.75rem;
|
||
}
|
||
.dxd-ci-stage .sname {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.45rem;
|
||
color: var(--dxd-focus);
|
||
font-weight: 600;
|
||
}
|
||
.dxd-ci-stage .ok { color: var(--dxd-emerald); }
|
||
.dxd-ci-stage .time { color: var(--dxd-dim); font-size: 0.7rem; }
|
||
|
||
/* ══════════════════════════════════════════════════════════════════
|
||
00 // TELEMETRY & SPEC STRIP (CachyOS × Omarchy)
|
||
══════════════════════════════════════════════════════════════════ */
|
||
.dxd-specs {
|
||
display: grid;
|
||
grid-template-columns: repeat(4, 1fr);
|
||
background: var(--dxd-surface);
|
||
border-radius: 14px;
|
||
box-shadow: var(--nm-raised);
|
||
overflow: hidden;
|
||
margin-bottom: 3.5rem;
|
||
}
|
||
@media (max-width: 860px) {
|
||
.dxd-specs { grid-template-columns: repeat(2, 1fr); }
|
||
}
|
||
@media (max-width: 500px) {
|
||
.dxd-specs { grid-template-columns: 1fr; }
|
||
}
|
||
.dxd-spec {
|
||
padding: 1.35rem 1.4rem;
|
||
border-right: 1px solid var(--dxd-border);
|
||
}
|
||
.dxd-spec:last-child { border-right: none; }
|
||
.dxd-spec-val {
|
||
font-family: var(--fonts-monospace);
|
||
font-size: clamp(1.55rem, 2.5vw, 2.1rem);
|
||
font-weight: 800;
|
||
letter-spacing: -0.03em;
|
||
color: var(--dxd-focus);
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: 0.4rem;
|
||
}
|
||
.dxd-spec-val span {
|
||
font-size: 0.75rem;
|
||
color: var(--dxd-accent);
|
||
font-weight: 700;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.08em;
|
||
}
|
||
.dxd-spec-label {
|
||
margin-top: 0.25rem;
|
||
font-size: 0.83rem;
|
||
color: var(--dxd-muted);
|
||
}
|
||
|
||
/* ══════════════════════════════════════════════════════════════════
|
||
01 // ASYMMETRIC 2026 BENTO GRID (JetBrains × Lovable × GitHub)
|
||
══════════════════════════════════════════════════════════════════ */
|
||
.dxd-section {
|
||
padding: 1.5rem 0 2.5rem;
|
||
}
|
||
.dxd-section-head {
|
||
margin-bottom: 1.65rem;
|
||
}
|
||
.dxd-section-head h2 {
|
||
font-size: clamp(1.65rem, 3vw, 2.35rem);
|
||
font-weight: 800;
|
||
letter-spacing: -0.025em;
|
||
margin: 0 0 0.45rem;
|
||
color: var(--dxd-focus);
|
||
}
|
||
.dxd-section-head h2 span {
|
||
background: linear-gradient(120deg, var(--dxd-accent), var(--dxd-teal), var(--dxd-violet));
|
||
-webkit-background-clip: text;
|
||
background-clip: text;
|
||
color: transparent;
|
||
}
|
||
.dxd-section-head p {
|
||
margin: 0;
|
||
font-size: 1rem;
|
||
color: var(--dxd-muted);
|
||
max-width: 42rem;
|
||
}
|
||
|
||
.dxd-bento {
|
||
display: grid;
|
||
grid-template-columns: repeat(12, 1fr);
|
||
gap: 1.15rem;
|
||
}
|
||
.dxd-bcard {
|
||
grid-column: span 4;
|
||
background: var(--dxd-surface);
|
||
border-radius: 16px;
|
||
box-shadow: var(--nm-raised);
|
||
padding: 1.5rem;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
gap: 1.1rem;
|
||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
.dxd-bcard.span-7 { grid-column: span 7; }
|
||
.dxd-bcard.span-5 { grid-column: span 5; }
|
||
.dxd-bcard.span-6 { grid-column: span 6; }
|
||
@media (max-width: 960px) {
|
||
.dxd-bcard,
|
||
.dxd-bcard.span-7,
|
||
.dxd-bcard.span-5,
|
||
.dxd-bcard.span-6 {
|
||
grid-column: span 12;
|
||
}
|
||
}
|
||
.dxd-bcard:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: var(--dxd-2026-glow-card, var(--nm-raised));
|
||
}
|
||
|
||
.dxd-bcard-top {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 0.75rem;
|
||
}
|
||
.dxd-bcard-icon {
|
||
width: 40px;
|
||
height: 40px;
|
||
border-radius: 10px;
|
||
display: grid;
|
||
place-items: center;
|
||
background: var(--dxd-well);
|
||
box-shadow: var(--nm-inset-sm);
|
||
color: var(--dxd-accent);
|
||
}
|
||
.dxd-bcard-icon svg { width: 20px; height: 20px; }
|
||
.dxd-bcard-kicker {
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.69rem;
|
||
font-weight: 700;
|
||
letter-spacing: 0.1em;
|
||
text-transform: uppercase;
|
||
color: var(--dxd-dim);
|
||
}
|
||
.dxd-bcard h3 {
|
||
margin: 0.2rem 0 0.35rem;
|
||
font-size: 1.16rem;
|
||
font-weight: 700;
|
||
letter-spacing: -0.015em;
|
||
color: var(--dxd-focus);
|
||
}
|
||
.dxd-bcard p {
|
||
margin: 0;
|
||
font-size: 0.89rem;
|
||
line-height: 1.6;
|
||
color: var(--dxd-muted);
|
||
}
|
||
|
||
/* Micro-UI visuals inside Bento cards */
|
||
.dxd-bcard-viz {
|
||
background: var(--dxd-well);
|
||
border-radius: 10px;
|
||
box-shadow: var(--nm-inset-sm);
|
||
padding: 0.75rem 0.9rem;
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.73rem;
|
||
}
|
||
.dxd-tag-row {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 0.4rem;
|
||
}
|
||
.dxd-tag {
|
||
padding: 0.22rem 0.55rem;
|
||
border-radius: 6px;
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.7rem;
|
||
color: var(--dxd-text);
|
||
background: rgba(148, 163, 184, 0.10);
|
||
}
|
||
.dxd-tag.cyan { color: var(--dxd-accent); background: rgba(56, 189, 248, 0.12); }
|
||
.dxd-tag.emerald { color: var(--dxd-emerald); background: rgba(52, 211, 153, 0.12); }
|
||
.dxd-tag.violet { color: var(--dxd-violet); background: rgba(167, 139, 250, 0.12); }
|
||
.dxd-tag.coral { color: var(--dxd-coral); background: rgba(251, 113, 133, 0.12); }
|
||
|
||
/* ══════════════════════════════════════════════════════════════════
|
||
02 // OMARCHY-STYLE LIVE THEME SWITCHER ("Pick a theme, change everything")
|
||
══════════════════════════════════════════════════════════════════ */
|
||
.dxd-theme-studio {
|
||
background: var(--dxd-surface);
|
||
border-radius: 16px;
|
||
box-shadow: var(--nm-raised);
|
||
padding: 1.6rem;
|
||
}
|
||
.dxd-ts-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
flex-wrap: wrap;
|
||
gap: 1rem;
|
||
margin-bottom: 1.25rem;
|
||
}
|
||
.dxd-ts-kbd {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 0.45rem;
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.75rem;
|
||
color: var(--dxd-muted);
|
||
background: var(--dxd-well);
|
||
padding: 0.38rem 0.75rem;
|
||
border-radius: 8px;
|
||
box-shadow: var(--nm-inset-sm);
|
||
}
|
||
.dxd-ts-kbd kbd {
|
||
display: inline-block;
|
||
padding: 0.1rem 0.42rem;
|
||
border-radius: 5px;
|
||
background: var(--dxd-surface-hi);
|
||
color: var(--dxd-accent);
|
||
font-weight: 700;
|
||
box-shadow: 0 0 0 1px var(--dxd-border);
|
||
}
|
||
.dxd-ts-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(195px, 1fr));
|
||
gap: 0.75rem;
|
||
}
|
||
.dxd-ts-btn {
|
||
border: none;
|
||
cursor: pointer;
|
||
text-align: left;
|
||
padding: 0.78rem 0.9rem;
|
||
border-radius: 10px;
|
||
background: var(--dxd-well);
|
||
box-shadow: var(--nm-inset-sm);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 0.6rem;
|
||
transition: all 0.16s ease;
|
||
}
|
||
.dxd-ts-btn:hover {
|
||
transform: translateY(-1px);
|
||
box-shadow: 0 0 0 1px var(--dxd-accent);
|
||
}
|
||
.dxd-ts-btn.is-active {
|
||
box-shadow: 0 0 0 1.5px var(--dxd-accent), 0 0 18px -4px rgba(56, 189, 248, 0.35);
|
||
background: var(--color-primary-alpha-10, rgba(56, 189, 248, 0.10));
|
||
}
|
||
.dxd-ts-name {
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.78rem;
|
||
font-weight: 700;
|
||
color: var(--dxd-focus);
|
||
}
|
||
.dxd-ts-sub {
|
||
display: block;
|
||
font-size: 0.68rem;
|
||
color: var(--dxd-dim);
|
||
margin-top: 0.12rem;
|
||
}
|
||
.dxd-ts-swatches {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
}
|
||
.dxd-ts-swatches i {
|
||
width: 11px;
|
||
height: 11px;
|
||
border-radius: 50%;
|
||
display: inline-block;
|
||
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16);
|
||
}
|
||
|
||
/* ══════════════════════════════════════════════════════════════════
|
||
03 // MANIFESTO (home_forgejo.tmpl) & COMPARISON MATRIX
|
||
══════════════════════════════════════════════════════════════════ */
|
||
.dxd-manifesto-head {
|
||
display: flex;
|
||
align-items: flex-end;
|
||
justify-content: space-between;
|
||
flex-wrap: wrap;
|
||
gap: 1rem;
|
||
}
|
||
.dxd-manifesto-badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
padding: 0.38rem 0.85rem;
|
||
border-radius: 999px;
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.74rem;
|
||
font-weight: 700;
|
||
color: var(--dxd-coral);
|
||
background: rgba(251, 113, 133, 0.10);
|
||
box-shadow: 0 0 0 1px rgba(251, 113, 133, 0.28);
|
||
}
|
||
.dxd-manifesto-badge .dot {
|
||
width: 7px;
|
||
height: 7px;
|
||
border-radius: 50%;
|
||
background: var(--dxd-coral);
|
||
}
|
||
|
||
.dxd-manifesto-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
||
gap: 1.15rem;
|
||
margin-bottom: 1.75rem;
|
||
}
|
||
.dxd-mcard {
|
||
background: var(--dxd-surface);
|
||
border-radius: 16px;
|
||
box-shadow: var(--nm-raised);
|
||
padding: 1.45rem 1.5rem;
|
||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||
position: relative;
|
||
}
|
||
.dxd-mcard:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: var(--dxd-2026-glow-card, var(--nm-raised));
|
||
}
|
||
.dxd-mcard-top {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.6rem;
|
||
margin-bottom: 0.9rem;
|
||
}
|
||
.dxd-mcard-num {
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.78rem;
|
||
font-weight: 800;
|
||
color: var(--dxd-accent);
|
||
}
|
||
.dxd-mcard-pill {
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.66rem;
|
||
font-weight: 700;
|
||
letter-spacing: 0.08em;
|
||
padding: 0.2rem 0.55rem;
|
||
border-radius: 6px;
|
||
background: var(--dxd-well);
|
||
color: var(--dxd-muted);
|
||
box-shadow: var(--nm-inset-sm);
|
||
}
|
||
.dxd-mcard[data-tone="coral"] .dxd-mcard-num,
|
||
.dxd-mcard[data-tone="coral"] .dxd-mcard-pill { color: var(--dxd-coral); }
|
||
.dxd-mcard[data-tone="amber"] .dxd-mcard-num,
|
||
.dxd-mcard[data-tone="amber"] .dxd-mcard-pill { color: var(--dxd-amber); }
|
||
.dxd-mcard[data-tone="violet"] .dxd-mcard-num,
|
||
.dxd-mcard[data-tone="violet"] .dxd-mcard-pill { color: var(--dxd-violet); }
|
||
.dxd-mcard[data-tone="emerald"] .dxd-mcard-num,
|
||
.dxd-mcard[data-tone="emerald"] .dxd-mcard-pill { color: var(--dxd-emerald); }
|
||
.dxd-mcard[data-tone="teal"] .dxd-mcard-num,
|
||
.dxd-mcard[data-tone="teal"] .dxd-mcard-pill { color: var(--dxd-teal); }
|
||
|
||
.dxd-mcard-icon {
|
||
margin-left: auto;
|
||
width: 38px;
|
||
height: 38px;
|
||
border-radius: 10px;
|
||
display: grid;
|
||
place-items: center;
|
||
background: var(--dxd-well);
|
||
box-shadow: var(--nm-inset-sm);
|
||
}
|
||
.dxd-mcard-icon img {
|
||
width: 22px;
|
||
height: 22px;
|
||
filter: saturate(0.85) brightness(1.05);
|
||
}
|
||
.dxd-mcard h3 {
|
||
margin: 0 0 0.45rem;
|
||
font-size: 1.12rem;
|
||
font-weight: 700;
|
||
color: var(--dxd-focus);
|
||
}
|
||
.dxd-mcard p {
|
||
margin: 0;
|
||
font-size: 0.88rem;
|
||
line-height: 1.62;
|
||
color: var(--dxd-muted);
|
||
}
|
||
|
||
/* Comparison Matrix */
|
||
.dxd-compare {
|
||
background: var(--dxd-surface);
|
||
border-radius: 16px;
|
||
box-shadow: var(--nm-raised);
|
||
overflow: hidden;
|
||
}
|
||
.dxd-compare-head {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
flex-wrap: wrap;
|
||
gap: 0.5rem;
|
||
padding: 0.9rem 1.25rem;
|
||
background: var(--dxd-well);
|
||
border-bottom: 1px solid var(--dxd-border);
|
||
}
|
||
.dxd-compare-title {
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.74rem;
|
||
font-weight: 700;
|
||
letter-spacing: 0.1em;
|
||
color: var(--dxd-accent);
|
||
}
|
||
.dxd-compare-sub {
|
||
font-size: 0.78rem;
|
||
color: var(--dxd-dim);
|
||
}
|
||
.dxd-compare-table-wrap {
|
||
overflow-x: auto;
|
||
}
|
||
.dxd-compare-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
font-size: 0.85rem;
|
||
}
|
||
.dxd-compare-table th,
|
||
.dxd-compare-table td {
|
||
padding: 0.85rem 1.15rem;
|
||
text-align: left;
|
||
border-bottom: 1px solid var(--dxd-border);
|
||
}
|
||
.dxd-compare-table th {
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.74rem;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.08em;
|
||
color: var(--dxd-muted);
|
||
}
|
||
.dxd-compare-table th.is-dxd,
|
||
.dxd-compare-table td.is-dxd {
|
||
background: var(--color-primary-alpha-10, rgba(56, 189, 248, 0.07));
|
||
color: var(--dxd-focus);
|
||
font-weight: 600;
|
||
}
|
||
.dxd-compare-table .yes { color: var(--dxd-emerald); font-weight: 800; margin-right: 0.35rem; }
|
||
.dxd-compare-table .no { color: var(--dxd-coral); font-weight: 800; margin-right: 0.35rem; }
|
||
.dxd-compare-table .warn { color: var(--dxd-amber); font-weight: 800; margin-right: 0.35rem; }
|
||
|
||
/* ══════════════════════════════════════════════════════════════════
|
||
04 // LAUNCHPAD CTA BAND
|
||
══════════════════════════════════════════════════════════════════ */
|
||
.dxd-cta-band {
|
||
margin: 2rem 0 0.5rem;
|
||
padding: 2.6rem 2rem;
|
||
border-radius: 20px;
|
||
text-align: center;
|
||
background: var(--dxd-surface);
|
||
box-shadow: var(--nm-raised);
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
.dxd-cta-band h2 {
|
||
margin: 0 0 0.55rem;
|
||
font-size: clamp(1.6rem, 3vw, 2.25rem);
|
||
font-weight: 800;
|
||
letter-spacing: -0.025em;
|
||
color: var(--dxd-focus);
|
||
}
|
||
.dxd-cta-band p {
|
||
margin: 0 auto 1.4rem;
|
||
color: var(--dxd-muted);
|
||
max-width: 36rem;
|
||
font-size: 0.98rem;
|
||
}
|
||
.dxd-steps {
|
||
display: inline-flex;
|
||
flex-wrap: wrap;
|
||
justify-content: center;
|
||
gap: 0.6rem;
|
||
margin-bottom: 1.6rem;
|
||
font-family: var(--fonts-monospace);
|
||
font-size: 0.76rem;
|
||
}
|
||
.dxd-step {
|
||
padding: 0.38rem 0.8rem;
|
||
border-radius: 8px;
|
||
background: var(--dxd-well);
|
||
box-shadow: var(--nm-inset-sm);
|
||
color: var(--dxd-text);
|
||
}
|
||
.dxd-step b { color: var(--dxd-accent); margin-right: 0.3rem; }
|
||
</style>
|
||
|
||
<div role="main" aria-label="{{ctx.Locale.Tr "home"}}" class="page-content home">
|
||
<div class="dxd-backdrop" aria-hidden="true"></div>
|
||
|
||
<div class="dxd-landing">
|
||
|
||
<!-- ── HERO ─────────────────────────────────────────────────── -->
|
||
<section class="dxd-hero">
|
||
<div class="dxd-status-pill">
|
||
<span class="pulse"></span>
|
||
<span>FORGEJO 15 · SELF-HOSTED</span>
|
||
<span class="sep">·</span>
|
||
<span>ZERO TELEMETRY</span>
|
||
<span class="sep">·</span>
|
||
<a href="/explore/repos">Explore repos →</a>
|
||
</div>
|
||
|
||
<h1>Code belongs to builders.<br>Not <em>monopolies</em>.</h1>
|
||
|
||
<p class="dxd-lede">
|
||
<strong>{{AppDisplayName}}</strong> is a fast, independent Git forge for repositories,
|
||
pull requests, issues, packages, and Docker CI runners — hosted on dedicated iron
|
||
with zero Microsoft bloat, zero trackers, and zero AI training scrapers.
|
||
</p>
|
||
|
||
<div class="dxd-hero-actions">
|
||
<a class="ui primary button dxd-btn" href="/user/sign_up">Start forging →</a>
|
||
<a class="ui basic button dxd-btn" href="/explore/repos">Browse repositories</a>
|
||
<div class="dxd-cmd-pill" title="Push any existing repo to GitDXD">
|
||
<span class="prompt">$</span>
|
||
<code id="dxd-clone-cmd">git remote add dxd https://git.dvorakmortonxd.dev/you/repo.git</code>
|
||
<button type="button" class="dxd-cmd-copy" id="dxd-copy-btn">Copy</button>
|
||
</div>
|
||
</div>
|
||
|
||
<p class="dxd-subnote">
|
||
Already have an account? <a href="/user/login">Sign in</a> · Or press <kbd style="font-family:var(--fonts-monospace);padding:0.1rem 0.4rem;border-radius:4px;background:var(--dxd-surface);box-shadow:var(--nm-raised-xs);">T</kbd> anytime to cycle live themes
|
||
</p>
|
||
|
||
<!-- ── Interactive 4-Tab Developer Workbench ──────────────── -->
|
||
<div class="dxd-workbench">
|
||
<div class="dxd-wb-titlebar">
|
||
<div class="dxd-wb-dots">
|
||
<span class="r"></span><span class="y"></span><span class="g"></span>
|
||
</div>
|
||
|
||
<div class="dxd-wb-tabs" role="tablist" aria-label="Preview workbench">
|
||
<button type="button" class="dxd-wb-tab is-active" data-wb-tab="repo">
|
||
</> Repository <span class="badge">main</span>
|
||
</button>
|
||
<button type="button" class="dxd-wb-tab" data-wb-tab="pr">
|
||
⑂ Pull Request <span class="badge">#42</span>
|
||
</button>
|
||
<button type="button" class="dxd-wb-tab" data-wb-tab="ci">
|
||
⚡ Actions CI <span class="badge" style="color:var(--dxd-emerald)">✓ 18s</span>
|
||
</button>
|
||
<button type="button" class="dxd-wb-tab" data-wb-tab="cli">
|
||
>_ Terminal Push
|
||
</button>
|
||
</div>
|
||
|
||
<div class="dxd-wb-url">git.dvorakmortonxd.dev/dvorakmortonxd/gitdxd-theme</div>
|
||
</div>
|
||
|
||
<!-- TAB 1: Repository + Interactive File Preview -->
|
||
<div class="dxd-wb-pane is-active" data-wb-pane="repo">
|
||
<div class="dxd-repo-bar">
|
||
<div class="dxd-repo-id">
|
||
<div class="dxd-repo-avatar">D</div>
|
||
<div>
|
||
<div class="dxd-repo-path">dvorakmortonxd / <strong>gitdxd-theme</strong></div>
|
||
<div class="dxd-repo-meta">commit 9eea655 · "Add 2026-dark theme and set as default"</div>
|
||
</div>
|
||
</div>
|
||
<div class="dxd-repo-pills">
|
||
<span class="dxd-rpill ok">● CI Passing</span>
|
||
<span class="dxd-rpill">GPL-3.0-only</span>
|
||
<span class="dxd-rpill star">★ 128</span>
|
||
<span class="dxd-rpill">⑂ 14 Forks</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="dxd-repo-split">
|
||
<div class="dxd-tree" role="listbox" aria-label="Repository files">
|
||
<div class="dxd-tree-head">
|
||
<span>branch: <b>main</b></span>
|
||
<span>click a file to inspect</span>
|
||
</div>
|
||
<button type="button" class="dxd-tree-row is-selected" data-file="theme">
|
||
<span>📄</span>
|
||
<span class="fname">themes/theme-2026-dark.css</span>
|
||
<span class="fmsg">Obsidian + cyan/violet/coral</span>
|
||
<span class="fage">now</span>
|
||
</button>
|
||
<button type="button" class="dxd-tree-row" data-file="flake">
|
||
<span>⚙️</span>
|
||
<span class="fname">.forgejo/workflows/ci.yml</span>
|
||
<span class="fmsg">Run isolated Docker jobs</span>
|
||
<span class="fage">2h</span>
|
||
</button>
|
||
<button type="button" class="dxd-tree-row" data-file="install">
|
||
<span>🐚</span>
|
||
<span class="fname">install.sh</span>
|
||
<span class="fmsg">Deploy custom assets & templates</span>
|
||
<span class="fage">4h</span>
|
||
</button>
|
||
<button type="button" class="dxd-tree-row" data-file="readme">
|
||
<span>📘</span>
|
||
<span class="fname">README.md</span>
|
||
<span class="fmsg">Document 2026-dark architecture</span>
|
||
<span class="fage">1d</span>
|
||
</button>
|
||
</div>
|
||
|
||
<div class="dxd-codebox">
|
||
<div class="dxd-codebox-bar">
|
||
<span id="dxd-code-filename">themes/theme-2026-dark.css</span>
|
||
<span class="lang" id="dxd-code-lang">CSS · UTF-8</span>
|
||
</div>
|
||
<pre id="dxd-code-content"><span class="ln"> 1</span><span class="cm">/* 2026 Dark — Obsidian + Cyan / Violet / Coral */</span>
|
||
<span class="ln"> 2</span><span class="kw">:root</span> {
|
||
<span class="ln"> 3</span> <span class="va">--color-body</span>: <span class="st">#0b0d13</span>;
|
||
<span class="ln"> 4</span> <span class="va">--color-box-body</span>: <span class="st">#111520</span>;
|
||
<span class="ln"> 5</span> <span class="va">--color-primary</span>: <span class="st">#38bdf8</span>;
|
||
<span class="ln"> 6</span> <span class="va">--color-teal</span>: <span class="st">#2dd4bf</span>;
|
||
<span class="ln"> 7</span> <span class="va">--color-purple</span>: <span class="st">#a78bfa</span>;
|
||
<span class="ln"> 8</span> <span class="va">--color-red</span>: <span class="st">#fb7185</span>;
|
||
<span class="ln"> 9</span> <span class="va">--nm-raised</span>: <span class="fn">0 0 0 1px</span> rgba(148,163,184,.12),
|
||
<span class="ln">10</span> <span class="fn">inset 0 1px 0</span> rgba(255,255,255,.06);
|
||
<span class="ln">11</span>}</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- TAB 2: Pull Request Diff -->
|
||
<div class="dxd-wb-pane" data-wb-pane="pr">
|
||
<div class="dxd-pr-head">
|
||
<div class="dxd-pr-title">
|
||
feat(ui): ship 2026-dark obsidian bento theme & strip telemetry <span>#42</span>
|
||
</div>
|
||
<span class="dxd-pr-badge">✓ Approved · Ready to merge</span>
|
||
</div>
|
||
<div class="dxd-diff">
|
||
<div class="dxd-diff-line ctx">@@ -61,6 +61,7 @@ [ui]</div>
|
||
<div class="dxd-diff-line del">-DEFAULT_THEME = aurora-light</div>
|
||
<div class="dxd-diff-line del">-ENABLE_TELEMETRY = true</div>
|
||
<div class="dxd-diff-line add">+THEMES = forgejo-auto,forgejo-light,forgejo-dark,2026-dark,aurora-dark,aurora-light,gruvbox-dark,terminal</div>
|
||
<div class="dxd-diff-line add">+DEFAULT_THEME = 2026-dark</div>
|
||
<div class="dxd-diff-line add">+OFFLINE_MODE = true</div>
|
||
<div class="dxd-diff-line ctx"> [service]</div>
|
||
<div class="dxd-diff-line ctx"> REQUIRE_SIGNIN_VIEW = false</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- TAB 3: Actions CI -->
|
||
<div class="dxd-wb-pane" data-wb-pane="ci">
|
||
<div class="dxd-ci-stages">
|
||
<div class="dxd-ci-stage">
|
||
<span class="sname"><span class="ok">✓</span> 1. Checkout & Lint</span>
|
||
<span class="time">1.4s</span>
|
||
</div>
|
||
<div class="dxd-ci-stage">
|
||
<span class="sname"><span class="ok">✓</span> 2. Verify CSS Tokens</span>
|
||
<span class="time">2.1s</span>
|
||
</div>
|
||
<div class="dxd-ci-stage">
|
||
<span class="sname"><span class="ok">✓</span> 3. Build OCI Image</span>
|
||
<span class="time">9.8s</span>
|
||
</div>
|
||
<div class="dxd-ci-stage">
|
||
<span class="sname"><span class="ok">✓</span> 4. Publish Release</span>
|
||
<span class="time">4.7s</span>
|
||
</div>
|
||
</div>
|
||
<div class="dxd-codebox">
|
||
<div class="dxd-codebox-bar">
|
||
<span>runner: gitdxd-runner-1 (docker://ubuntu-latest)</span>
|
||
<span class="lang">EXIT 0</span>
|
||
</div>
|
||
<pre><span class="ln">01</span>[21:58:01] <span class="fn">INFO</span> Spawning ephemeral container <span class="st">catthehacker/ubuntu:act-latest</span>
|
||
<span class="ln">02</span>[21:58:03] <span class="fn">RUN</span> ./install.sh /tmp/forgejo-custom
|
||
<span class="ln">03</span>[21:58:05] <span class="st">PASS</span> 16 theme stylesheets validated (0 warnings)
|
||
<span class="ln">04</span>[21:58:18] <span class="st">DONE</span> Job completed in 18.0s — container destroyed cleanly.</pre>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- TAB 4: Terminal Push -->
|
||
<div class="dxd-wb-pane" data-wb-pane="cli">
|
||
<div class="dxd-codebox">
|
||
<div class="dxd-codebox-bar">
|
||
<span>zsh — ~/projects/my-app</span>
|
||
<span class="lang">HTTPS GIT</span>
|
||
</div>
|
||
<pre><span class="st">❯</span> git remote add dxd https://git.dvorakmortonxd.dev/dvorakmortonxd/my-app.git
|
||
<span class="st">❯</span> git push -u dxd main
|
||
Enumerating objects: 48, done.
|
||
Counting objects: 100% (48/48), done.
|
||
Delta compression using up to 16 threads
|
||
Compressing objects: 100% (34/34), done.
|
||
Writing objects: 100% (48/48), 19.42 KiB | 19.42 MiB/s, done.
|
||
remote: <span class="fn">Forgejo:</span> Buat/update branch <span class="va">main</span> -> <span class="st">https://git.dvorakmortonxd.dev/dvorakmortonxd/my-app</span>
|
||
To https://git.dvorakmortonxd.dev/dvorakmortonxd/my-app.git
|
||
* [new branch] main -> main</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ── 00 // TELEMETRY & SPEC STRIP ─────────────────────────── -->
|
||
<div class="dxd-specs" aria-label="Platform telemetry and specs">
|
||
<div class="dxd-spec">
|
||
<div class="dxd-spec-val">0 <span>Trackers</span></div>
|
||
<div class="dxd-spec-label">No analytics beacons, ad pixels, or third-party scripts</div>
|
||
</div>
|
||
<div class="dxd-spec">
|
||
<div class="dxd-spec-val">0% <span>AI Scraping</span></div>
|
||
<div class="dxd-spec-label">Your repositories are never used to train corporate models</div>
|
||
</div>
|
||
<div class="dxd-spec">
|
||
<div class="dxd-spec-val">GPLv3 <span>Libre</span></div>
|
||
<div class="dxd-spec-label">Powered by Forgejo — community-governed open source</div>
|
||
</div>
|
||
<div class="dxd-spec">
|
||
<div class="dxd-spec-val">100% <span>Self-Hosted</span></div>
|
||
<div class="dxd-spec-label">Dedicated Linux hardware with isolated Docker CI runners</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ── 01 // ASYMMETRIC BENTO GRID ──────────────────────────── -->
|
||
<section class="dxd-section">
|
||
<div class="dxd-sec-bar">
|
||
<span class="dxd-sec-idx">01 // ARCHITECTURE</span>
|
||
<span class="dxd-sec-line"></span>
|
||
<span class="dxd-sec-tag">BUILT FOR SPEED & AUTONOMY</span>
|
||
</div>
|
||
|
||
<div class="dxd-section-head">
|
||
<h2>Everything you need to <span>ship</span>.</h2>
|
||
<p>The complete developer workflow — without the bloated enterprise upsells.</p>
|
||
</div>
|
||
|
||
<div class="dxd-bento">
|
||
<!-- Span 7: Git & Code -->
|
||
<div class="dxd-bcard span-7">
|
||
<div>
|
||
<div class="dxd-bcard-top">
|
||
<div class="dxd-bcard-icon">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M4 5.5A2.5 2.5 0 0 1 6.5 3H19a1 1 0 0 1 1 1v14"/><path d="M4 5.5A2.5 2.5 0 0 0 6.5 8H20"/><path d="M4 5.5V18a3 3 0 0 0 3 3h13"/></svg>
|
||
</div>
|
||
<span class="dxd-bcard-kicker">GIT CORE // LFS</span>
|
||
</div>
|
||
<h3>Unlimited Public & Private Repositories</h3>
|
||
<p>
|
||
Fast HTTPS clones, Git LFS for large assets, branch protection rules, commit graph visualization,
|
||
wikis, webhooks, and instant repository mirroring from external hosts.
|
||
</p>
|
||
</div>
|
||
<div class="dxd-bcard-viz">
|
||
<div class="dxd-tag-row">
|
||
<span class="dxd-tag cyan">main ●──●──●──●</span>
|
||
<span class="dxd-tag emerald">feat/2026-ui ⑂ merged</span>
|
||
<span class="dxd-tag">Git LFS</span>
|
||
<span class="dxd-tag">Commit Graph</span>
|
||
<span class="dxd-tag">Webhooks</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Span 5: Actions CI -->
|
||
<div class="dxd-bcard span-5">
|
||
<div>
|
||
<div class="dxd-bcard-top">
|
||
<div class="dxd-bcard-icon">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M13.5 3 5 13.5h5.5L10 21l8.5-10.5H13z"/></svg>
|
||
</div>
|
||
<span class="dxd-bcard-kicker">FORGEJO ACTIONS // CI/CD</span>
|
||
</div>
|
||
<h3>Ephemeral Docker CI Runners</h3>
|
||
<p>
|
||
Drop a workflow into <code>.forgejo/workflows/</code> and build, test, and release inside isolated
|
||
throwaway containers right next to your code.
|
||
</p>
|
||
</div>
|
||
<div class="dxd-bcard-viz">
|
||
<div class="dxd-tag-row">
|
||
<span class="dxd-tag emerald">✓ ubuntu-latest</span>
|
||
<span class="dxd-tag cyan">✓ node-22</span>
|
||
<span class="dxd-tag violet">Isolated Docker</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Span 4: Pull Requests -->
|
||
<div class="dxd-bcard">
|
||
<div>
|
||
<div class="dxd-bcard-top">
|
||
<div class="dxd-bcard-icon">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.4"/><circle cx="6" cy="18" r="2.4"/><circle cx="18" cy="6" r="2.4"/><path d="M6 8.4v7.2"/><path d="M15.6 6h-3.2a4 4 0 0 0-4 4v0"/><path d="M18 8.4v3.1a4 4 0 0 1-4 4h-3"/></svg>
|
||
</div>
|
||
<span class="dxd-bcard-kicker">CODE REVIEW</span>
|
||
</div>
|
||
<h3>Pull Requests & Diffs</h3>
|
||
<p>Side-by-side and unified diffs, inline review threads, required status checks, and squash/rebase/merge strategies.</p>
|
||
</div>
|
||
<div class="dxd-bcard-viz">
|
||
<span class="dxd-tag emerald">+652 additions</span>
|
||
<span class="dxd-tag coral">-12 deletions</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Span 4: Issues & Kanban -->
|
||
<div class="dxd-bcard">
|
||
<div>
|
||
<div class="dxd-bcard-top">
|
||
<div class="dxd-bcard-icon">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8.5"/><circle cx="12" cy="12" r="2.6" fill="currentColor" stroke="none"/></svg>
|
||
</div>
|
||
<span class="dxd-bcard-kicker">PLANNING</span>
|
||
</div>
|
||
<h3>Issues, Milestones & Boards</h3>
|
||
<p>Organize bugs and roadmaps with custom color labels, time tracking, issue dependencies, and Kanban boards.</p>
|
||
</div>
|
||
<div class="dxd-bcard-viz">
|
||
<div class="dxd-tag-row">
|
||
<span class="dxd-tag coral">bug</span>
|
||
<span class="dxd-tag cyan">enhancement</span>
|
||
<span class="dxd-tag violet">v2026.1</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Span 4: Packages -->
|
||
<div class="dxd-bcard">
|
||
<div>
|
||
<div class="dxd-bcard-top">
|
||
<div class="dxd-bcard-icon">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3 20 7.5v9L12 21 4 16.5v-9z"/><path d="M4 7.5 12 12l8-4.5"/><path d="M12 12v9"/></svg>
|
||
</div>
|
||
<span class="dxd-bcard-kicker">REGISTRY</span>
|
||
</div>
|
||
<h3>Packages & Containers</h3>
|
||
<p>Publish OCI/Docker images, npm, PyPI, Cargo, Go, and Maven artifacts directly from your workflows.</p>
|
||
</div>
|
||
<div class="dxd-bcard-viz">
|
||
<div class="dxd-tag-row">
|
||
<span class="dxd-tag cyan">OCI / Docker</span>
|
||
<span class="dxd-tag">Cargo</span>
|
||
<span class="dxd-tag">npm</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ── 02 // OMARCHY LIVE THEME STUDIO ──────────────────────── -->
|
||
<section class="dxd-section">
|
||
<div class="dxd-sec-bar">
|
||
<span class="dxd-sec-idx">02 // AESTHETICS</span>
|
||
<span class="dxd-sec-line"></span>
|
||
<span class="dxd-sec-tag">INSPIRED BY OMARCHY · JETBRAINS · CACHYOS</span>
|
||
</div>
|
||
|
||
<div class="dxd-theme-studio">
|
||
<div class="dxd-ts-header">
|
||
<div class="dxd-section-head" style="margin-bottom:0">
|
||
<h2>Pick a theme, <span>change everything</span>.</h2>
|
||
<p>Preview every installed palette right now — or press <strong>T</strong> on your keyboard to cycle through them.</p>
|
||
</div>
|
||
<div class="dxd-ts-kbd">
|
||
<span>Shortcut:</span> <kbd>T</kbd> <span>next theme</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="dxd-ts-grid" id="dxd-theme-grid">
|
||
<button type="button" class="dxd-ts-btn is-active" data-set-theme="2026-dark">
|
||
<div>
|
||
<span class="dxd-ts-name">2026-dark ★</span>
|
||
<span class="dxd-ts-sub">Obsidian · Cyan · Violet · Coral</span>
|
||
</div>
|
||
<span class="dxd-ts-swatches">
|
||
<i style="background:#0b0d13"></i><i style="background:#38bdf8"></i><i style="background:#2dd4bf"></i><i style="background:#a78bfa"></i><i style="background:#fb7185"></i>
|
||
</span>
|
||
</button>
|
||
|
||
<button type="button" class="dxd-ts-btn" data-set-theme="aurora-dark">
|
||
<div>
|
||
<span class="dxd-ts-name">aurora-dark</span>
|
||
<span class="dxd-ts-sub">Neutral Charcoal · Blue · Teal</span>
|
||
</div>
|
||
<span class="dxd-ts-swatches">
|
||
<i style="background:#191a1c"></i><i style="background:#3b82f6"></i><i style="background:#2dd4bf"></i><i style="background:#4ade80"></i>
|
||
</span>
|
||
</button>
|
||
|
||
<button type="button" class="dxd-ts-btn" data-set-theme="aurora-light">
|
||
<div>
|
||
<span class="dxd-ts-name">aurora-light</span>
|
||
<span class="dxd-ts-sub">Soft Slate · Vivid Blue · Light</span>
|
||
</div>
|
||
<span class="dxd-ts-swatches">
|
||
<i style="background:#dee4ec"></i><i style="background:#2563eb"></i><i style="background:#0d9488"></i><i style="background:#20262f"></i>
|
||
</span>
|
||
</button>
|
||
|
||
<button type="button" class="dxd-ts-btn" data-set-theme="terminal">
|
||
<div>
|
||
<span class="dxd-ts-name">terminal</span>
|
||
<span class="dxd-ts-sub">CRT Phosphor Green</span>
|
||
</div>
|
||
<span class="dxd-ts-swatches">
|
||
<i style="background:#101410"></i><i style="background:#33ff66"></i><i style="background:#8ee6a5"></i><i style="background:#ff7540"></i>
|
||
</span>
|
||
</button>
|
||
|
||
<button type="button" class="dxd-ts-btn" data-set-theme="gruvbox-dark">
|
||
<div>
|
||
<span class="dxd-ts-name">gruvbox-dark</span>
|
||
<span class="dxd-ts-sub">Warm Retro · Aqua & Gold</span>
|
||
</div>
|
||
<span class="dxd-ts-swatches">
|
||
<i style="background:#282828"></i><i style="background:#8ec07c"></i><i style="background:#fabd2f"></i><i style="background:#fb4934"></i>
|
||
</span>
|
||
</button>
|
||
|
||
<button type="button" class="dxd-ts-btn" data-set-theme="gruvbox-light">
|
||
<div>
|
||
<span class="dxd-ts-name">gruvbox-light</span>
|
||
<span class="dxd-ts-sub">Warm Paper · Retro Light</span>
|
||
</div>
|
||
<span class="dxd-ts-swatches">
|
||
<i style="background:#fbf1c7"></i><i style="background:#689d6a"></i><i style="background:#d79921"></i><i style="background:#cc241d"></i>
|
||
</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ── 03 // MANIFESTO (Why not GitHub?) ────────────────────── -->
|
||
{{template "home_forgejo" .}}
|
||
|
||
<!-- ── 04 // LAUNCHPAD CTA BAND ─────────────────────────────── -->
|
||
<section class="dxd-cta-band">
|
||
<div class="dxd-sec-bar" style="justify-content:center;margin-bottom:1rem">
|
||
<span class="dxd-sec-idx">04 // LAUNCHPAD</span>
|
||
</div>
|
||
<h2>Ready to forge something real?</h2>
|
||
<p>Spin up an account and push your first repository in under sixty seconds.</p>
|
||
<div class="dxd-steps">
|
||
<span class="dxd-step"><b>01</b> Create account</span>
|
||
<span class="dxd-step"><b>02</b> New repository</span>
|
||
<span class="dxd-step"><b>03</b> git push -u origin main</span>
|
||
</div>
|
||
<div class="dxd-hero-actions" style="margin-bottom:0">
|
||
<a class="ui primary button dxd-btn" href="/user/sign_up">Create your account</a>
|
||
<a class="ui basic button dxd-btn" href="/user/login">Sign in</a>
|
||
<a class="ui basic button dxd-btn" href="/explore/repos">Explore public code</a>
|
||
</div>
|
||
</section>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
(function () {
|
||
"use strict";
|
||
|
||
/* 1. Copy command button */
|
||
var copyBtn = document.getElementById("dxd-copy-btn");
|
||
var cmdEl = document.getElementById("dxd-clone-cmd");
|
||
if (copyBtn && cmdEl) {
|
||
copyBtn.addEventListener("click", function () {
|
||
var text = cmdEl.textContent || "";
|
||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||
navigator.clipboard.writeText(text);
|
||
}
|
||
copyBtn.textContent = "✓ Copied";
|
||
setTimeout(function () { copyBtn.textContent = "Copy"; }, 1800);
|
||
});
|
||
}
|
||
|
||
/* 2. Workbench tab switcher */
|
||
var tabs = document.querySelectorAll("[data-wb-tab]");
|
||
var panes = document.querySelectorAll("[data-wb-pane]");
|
||
tabs.forEach(function (tab) {
|
||
tab.addEventListener("click", function () {
|
||
var target = tab.getAttribute("data-wb-tab");
|
||
tabs.forEach(function (t) { t.classList.toggle("is-active", t === tab); });
|
||
panes.forEach(function (p) {
|
||
p.classList.toggle("is-active", p.getAttribute("data-wb-pane") === target);
|
||
});
|
||
});
|
||
});
|
||
|
||
/* 3. Interactive repository file preview */
|
||
var files = {
|
||
theme: {
|
||
name: "themes/theme-2026-dark.css",
|
||
lang: "CSS · UTF-8",
|
||
html:
|
||
'<span class="ln"> 1</span><span class="cm">/* 2026 Dark — Obsidian + Cyan / Violet / Coral */</span>\n' +
|
||
'<span class="ln"> 2</span><span class="kw">:root</span> {\n' +
|
||
'<span class="ln"> 3</span> <span class="va">--color-body</span>: <span class="st">#0b0d13</span>;\n' +
|
||
'<span class="ln"> 4</span> <span class="va">--color-box-body</span>: <span class="st">#111520</span>;\n' +
|
||
'<span class="ln"> 5</span> <span class="va">--color-primary</span>: <span class="st">#38bdf8</span>;\n' +
|
||
'<span class="ln"> 6</span> <span class="va">--color-teal</span>: <span class="st">#2dd4bf</span>;\n' +
|
||
'<span class="ln"> 7</span> <span class="va">--color-purple</span>: <span class="st">#a78bfa</span>;\n' +
|
||
'<span class="ln"> 8</span> <span class="va">--color-red</span>: <span class="st">#fb7185</span>;\n' +
|
||
'<span class="ln"> 9</span> <span class="va">--nm-raised</span>: <span class="fn">0 0 0 1px</span> rgba(148,163,184,.12),\n' +
|
||
'<span class="ln">10</span> <span class="fn">inset 0 1px 0</span> rgba(255,255,255,.06);\n' +
|
||
'<span class="ln">11</span>}'
|
||
},
|
||
flake: {
|
||
name: ".forgejo/workflows/ci.yml",
|
||
lang: "YAML · Actions",
|
||
html:
|
||
'<span class="ln"> 1</span><span class="kw">name</span>: <span class="st">verify-themes</span>\n' +
|
||
'<span class="ln"> 2</span><span class="kw">on</span>: [<span class="va">push</span>, <span class="va">pull_request</span>]\n' +
|
||
'<span class="ln"> 3</span><span class="kw">jobs</span>:\n' +
|
||
'<span class="ln"> 4</span> <span class="fn">build</span>:\n' +
|
||
'<span class="ln"> 5</span> <span class="kw">runs-on</span>: <span class="st">ubuntu-latest</span>\n' +
|
||
'<span class="ln"> 6</span> <span class="kw">steps</span>:\n' +
|
||
'<span class="ln"> 7</span> - <span class="kw">uses</span>: <span class="st">actions/checkout@v4</span>\n' +
|
||
'<span class="ln"> 8</span> - <span class="kw">run</span>: <span class="st">./install.sh /tmp/custom && echo "All themes valid"</span>'
|
||
},
|
||
install: {
|
||
name: "install.sh",
|
||
lang: "POSIX sh · GPL-3.0",
|
||
html:
|
||
'<span class="ln"> 1</span><span class="cm">#!/bin/sh</span>\n' +
|
||
'<span class="ln"> 2</span><span class="kw">set</span> -eu\n' +
|
||
'<span class="ln"> 3</span><span class="va">CUSTOM</span>=<span class="st">"${1:?usage: ./install.sh /path/to/custom}"</span>\n' +
|
||
'<span class="ln"> 4</span><span class="fn">cp</span> themes/*.css <span class="st">"$CUSTOM/public/assets/css/"</span>\n' +
|
||
'<span class="ln"> 5</span><span class="fn">cp</span> templates/home*.tmpl <span class="st">"$CUSTOM/templates/"</span>\n' +
|
||
'<span class="ln"> 6</span><span class="fn">echo</span> <span class="st">"Installed 2026-dark + homepage to $CUSTOM"</span>'
|
||
},
|
||
readme: {
|
||
name: "README.md",
|
||
lang: "Markdown",
|
||
html:
|
||
'<span class="ln"> 1</span><span class="fn"># GitDXD — 2026 Dark & Custom Forgejo Suite</span>\n' +
|
||
'<span class="ln"> 2</span>\n' +
|
||
'<span class="ln"> 3</span>Default theme: <span class="st">`2026-dark`</span> (Obsidian + Cyan/Violet/Coral).\n' +
|
||
'<span class="ln"> 4</span>Inspired by <span class="va">Omarchy</span>, <span class="va">JetBrains</span>, <span class="va">GitHub</span>,\n' +
|
||
'<span class="ln"> 5</span><span class="va">GitLab</span>, <span class="va">CachyOS</span>, <span class="va">Hack Club</span> & <span class="va">Lovable</span>.\n' +
|
||
'<span class="ln"> 6</span>\n' +
|
||
'<span class="ln"> 7</span>- Zero corporate telemetry\n' +
|
||
'<span class="ln"> 8</span>- Press <span class="kw">T</span> to live-switch palettes'
|
||
}
|
||
};
|
||
|
||
var fileBtns = document.querySelectorAll("[data-file]");
|
||
var codeName = document.getElementById("dxd-code-filename");
|
||
var codeLang = document.getElementById("dxd-code-lang");
|
||
var codeBody = document.getElementById("dxd-code-content");
|
||
fileBtns.forEach(function (btn) {
|
||
btn.addEventListener("click", function () {
|
||
var key = btn.getAttribute("data-file");
|
||
var item = files[key];
|
||
if (!item) return;
|
||
fileBtns.forEach(function (b) { b.classList.toggle("is-selected", b === btn); });
|
||
if (codeName) codeName.textContent = item.name;
|
||
if (codeLang) codeLang.textContent = item.lang;
|
||
if (codeBody) codeBody.innerHTML = item.html;
|
||
});
|
||
});
|
||
|
||
/* 4. Live Theme Studio + Keyboard Shortcut 'T' (Omarchy style) */
|
||
var themeBtns = Array.prototype.slice.call(document.querySelectorAll("[data-set-theme]"));
|
||
var themeOrder = themeBtns.map(function (b) { return b.getAttribute("data-set-theme"); });
|
||
|
||
function getCurrentTheme() {
|
||
var link = document.querySelector('link[rel="stylesheet"][href*="/css/theme-"]');
|
||
if (!link) return "2026-dark";
|
||
var m = link.getAttribute("href").match(/\/theme-([^\/?]+)\.css/);
|
||
return m ? m[1] : "2026-dark";
|
||
}
|
||
|
||
function setLiveTheme(name) {
|
||
var link = document.querySelector('link[rel="stylesheet"][href*="/css/theme-"]');
|
||
if (link) {
|
||
var href = link.getAttribute("href");
|
||
link.setAttribute("href", href.replace(/\/theme-[^\/?]+\.css/, "/theme-" + name + ".css"));
|
||
}
|
||
document.documentElement.setAttribute("data-theme", name);
|
||
themeBtns.forEach(function (b) {
|
||
b.classList.toggle("is-active", b.getAttribute("data-set-theme") === name);
|
||
});
|
||
var navToggle = document.getElementById("dxd-theme-toggle");
|
||
if (navToggle) {
|
||
var isLight = /-light$/.test(name);
|
||
navToggle.setAttribute("data-mode", isLight ? "light" : "dark");
|
||
navToggle.setAttribute("aria-checked", isLight ? "false" : "true");
|
||
}
|
||
}
|
||
|
||
themeBtns.forEach(function (btn) {
|
||
btn.addEventListener("click", function () {
|
||
var name = btn.getAttribute("data-set-theme");
|
||
if (name) setLiveTheme(name);
|
||
});
|
||
});
|
||
|
||
/* Sync active button on initial load */
|
||
setLiveTheme(getCurrentTheme());
|
||
|
||
document.addEventListener("keydown", function (e) {
|
||
if (e.defaultPrevented || e.metaKey || e.ctrlKey || e.altKey) return;
|
||
var tag = (e.target && e.target.tagName) ? e.target.tagName.toLowerCase() : "";
|
||
if (tag === "input" || tag === "textarea" || tag === "select" || (e.target && e.target.isContentEditable)) return;
|
||
if (e.key === "t" || e.key === "T") {
|
||
var cur = getCurrentTheme();
|
||
var idx = themeOrder.indexOf(cur);
|
||
var next = themeOrder[(idx + 1) % themeOrder.length] || "2026-dark";
|
||
setLiveTheme(next);
|
||
}
|
||
});
|
||
})();
|
||
</script>
|
||
{{end}}
|
||
{{template "base/footer" .}}
|