2026-03-03 20:47:56 +01:00
<!DOCTYPE html>
< html lang = "de" >
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< title > DocuMentor — XSL-Transformationen unter Kontrolle< / title >
2026-03-03 21:19:54 +01:00
< link rel = "stylesheet" href = "fonts/fonts_v2.css" >
2026-03-03 20:47:56 +01:00
< style >
* , * :: before , * :: after {
margin : 0 ;
padding : 0 ;
box-sizing : border-box ;
}
: root {
--black : #000000 ;
--white : #ffffff ;
--off-white : #f0f0f0 ;
--neon-red : #ff0033 ;
--neon-red-dim : #cc0029 ;
--gray-dark : #1a1a1a ;
--gray-mid : #333333 ;
--gray-light : #888888 ;
--border-thick : 4 px ;
--border-thin : 2 px ;
--font-mono : 'Space Mono' , 'Courier New' , monospace ;
}
html {
scroll-behavior : auto ;
}
body {
font-family : var ( - - font - mono ) ;
background : var ( - - white ) ;
color : var ( - - black ) ;
line-height : 1.6 ;
overflow-x : hidden ;
}
/* ========== BRUTALIST RESETS ========== */
:: selection {
background : var ( - - neon - red ) ;
color : var ( - - white ) ;
}
a {
color : var ( - - neon - red ) ;
text-decoration : none ;
border-bottom : var ( - - border - thin ) solid var ( - - neon - red ) ;
}
a : hover {
background : var ( - - neon - red ) ;
color : var ( - - white ) ;
}
/* ========== GRID OVERLAY ========== */
body :: before {
content : '' ;
position : fixed ;
top : 0 ;
left : 0 ;
width : 100 % ;
height : 100 % ;
background-image :
linear-gradient ( 90 deg , rgba ( 0 , 0 , 0 , 0.03 ) 1 px , transparent 1 px ) ,
linear-gradient ( 0 deg , rgba ( 0 , 0 , 0 , 0.03 ) 1 px , transparent 1 px ) ;
background-size : 60 px 60 px ;
pointer-events : none ;
z-index : 0 ;
}
/* ========== NAVIGATION ========== */
nav {
position : fixed ;
top : 0 ;
left : 0 ;
width : 100 % ;
z-index : 1000 ;
background : var ( - - black ) ;
color : var ( - - white ) ;
border-bottom : var ( - - border - thick ) solid var ( - - neon - red ) ;
padding : 0 ;
}
nav . nav-inner {
display : flex ;
align-items : stretch ;
justify-content : space-between ;
max-width : 1400 px ;
margin : 0 auto ;
}
nav . nav-brand {
font-weight : 700 ;
font-size : 1.1 rem ;
text-transform : uppercase ;
letter-spacing : 3 px ;
padding : 14 px 24 px ;
border-right : var ( - - border - thin ) solid var ( - - gray - mid ) ;
color : var ( - - white ) ;
border-bottom : none ;
display : flex ;
align-items : center ;
gap : 8 px ;
}
nav . nav-brand span {
color : var ( - - neon - red ) ;
}
nav . nav-links {
display : flex ;
list-style : none ;
align-items : stretch ;
}
nav . nav-links li {
border-left : var ( - - border - thin ) solid var ( - - gray - mid ) ;
}
nav . nav-links a {
display : flex ;
align-items : center ;
padding : 14 px 20 px ;
color : var ( - - white ) ;
text-transform : uppercase ;
font-size : 0.7 rem ;
letter-spacing : 2 px ;
border-bottom : none ;
transition : none ;
}
nav . nav-links a : hover {
background : var ( - - neon - red ) ;
color : var ( - - white ) ;
}
/* ========== HERO ========== */
. hero {
position : relative ;
min-height : 100 vh ;
display : flex ;
flex-direction : column ;
justify-content : center ;
padding : 120 px 40 px 80 px ;
background : var ( - - black ) ;
color : var ( - - white ) ;
border-bottom : var ( - - border - thick ) solid var ( - - neon - red ) ;
overflow : hidden ;
}
. hero :: before {
content : 'XSL→PDF XSL→PDF XSL→PDF XSL→PDF XSL→PDF XSL→PDF XSL→PDF XSL→PDF XSL→PDF XSL→PDF XSL→PDF XSL→PDF XSL→PDF XSL→PDF XSL→PDF XSL→PDF XSL→PDF XSL→PDF XSL→PDF XSL→PDF' ;
position : absolute ;
top : 0 ;
left : 0 ;
width : 200 % ;
height : 100 % ;
font-size : 1.2 rem ;
color : rgba ( 255 , 255 , 255 , 0.03 ) ;
word-break : break-all ;
line-height : 2 ;
letter-spacing : 8 px ;
pointer-events : none ;
z-index : 0 ;
}
. hero-content {
position : relative ;
z-index : 1 ;
max-width : 1400 px ;
margin : 0 auto ;
width : 100 % ;
}
. hero-label {
display : inline-block ;
font-size : 0.7 rem ;
text-transform : uppercase ;
letter-spacing : 4 px ;
border : var ( - - border - thin ) solid var ( - - neon - red ) ;
padding : 6 px 16 px ;
margin-bottom : 40 px ;
color : var ( - - neon - red ) ;
}
. hero h1 {
font-family : var ( - - font - mono ) ;
font-size : clamp ( 3 rem , 10 vw , 8 rem ) ;
font-weight : 700 ;
text-transform : uppercase ;
line-height : 0.95 ;
letter-spacing : -3 px ;
margin-bottom : 40 px ;
}
. hero h1 . red {
color : var ( - - neon - red ) ;
display : block ;
}
. hero-tagline {
font-size : 1.1 rem ;
max-width : 700 px ;
line-height : 1.8 ;
color : var ( - - gray - light ) ;
border-left : var ( - - border - thick ) solid var ( - - neon - red ) ;
padding-left : 24 px ;
margin-bottom : 50 px ;
}
. hero-stats {
display : flex ;
gap : 0 ;
border : var ( - - border - thick ) solid var ( - - white ) ;
width : fit-content ;
}
. hero-stat {
padding : 20 px 32 px ;
border-right : var ( - - border - thin ) solid var ( - - gray - mid ) ;
text-align : center ;
}
. hero-stat : last-child {
border-right : none ;
}
. hero-stat . number {
font-size : 2 rem ;
font-weight : 700 ;
color : var ( - - neon - red ) ;
display : block ;
}
. hero-stat . label {
font-size : 0.6 rem ;
text-transform : uppercase ;
letter-spacing : 2 px ;
color : var ( - - gray - light ) ;
}
/* ========== SECTION BASE ========== */
section {
position : relative ;
z-index : 1 ;
padding : 100 px 40 px ;
}
. section-inner {
max-width : 1400 px ;
margin : 0 auto ;
}
. section-header {
margin-bottom : 60 px ;
}
. section-number {
font-size : 0.7 rem ;
text-transform : uppercase ;
letter-spacing : 4 px ;
color : var ( - - neon - red ) ;
margin-bottom : 12 px ;
display : block ;
}
. section-title {
font-size : clamp ( 2 rem , 5 vw , 3.5 rem ) ;
font-weight : 700 ;
text-transform : uppercase ;
letter-spacing : -1 px ;
line-height : 1.1 ;
}
. section-title . muted {
color : var ( - - gray - light ) ;
}
. section-divider {
width : 100 % ;
height : var ( - - border - thick ) ;
background : var ( - - black ) ;
margin-top : 20 px ;
}
/* ========== FEATURES ========== */
. features {
background : var ( - - white ) ;
border-bottom : var ( - - border - thick ) solid var ( - - black ) ;
}
. features-grid {
display : grid ;
grid-template-columns : repeat ( 3 , 1 fr ) ;
border : var ( - - border - thick ) solid var ( - - black ) ;
}
. feature-card {
padding : 40 px 32 px ;
border-right : var ( - - border - thin ) solid var ( - - black ) ;
border-bottom : var ( - - border - thin ) solid var ( - - black ) ;
position : relative ;
transition : none ;
}
. feature-card : nth-child ( 3n ) {
border-right : none ;
}
. feature-card : nth-child ( n + 4 ) {
border-bottom : none ;
}
. feature-card : hover {
background : var ( - - black ) ;
color : var ( - - white ) ;
}
. feature-card : hover . feature-icon {
color : var ( - - neon - red ) ;
}
. feature-card : hover . feature-num {
color : var ( - - neon - red ) ;
}
. feature-icon {
font-size : 2.5 rem ;
margin-bottom : 16 px ;
display : block ;
filter : grayscale ( 0 ) ;
}
. feature-num {
font-size : 0.65 rem ;
text-transform : uppercase ;
letter-spacing : 3 px ;
color : var ( - - gray - light ) ;
margin-bottom : 12 px ;
display : block ;
}
. feature-card h3 {
font-size : 1.1 rem ;
text-transform : uppercase ;
letter-spacing : 1 px ;
margin-bottom : 12 px ;
font-weight : 700 ;
}
. feature-card p {
font-size : 0.8 rem ;
line-height : 1.7 ;
color : var ( - - gray - light ) ;
}
. feature-card : hover p {
color : var ( - - gray - light ) ;
}
/* ========== WORKFLOW ========== */
. workflow {
background : var ( - - black ) ;
color : var ( - - white ) ;
border-bottom : var ( - - border - thick ) solid var ( - - neon - red ) ;
}
. workflow . section-title {
color : var ( - - white ) ;
}
. workflow . section-divider {
background : var ( - - white ) ;
}
. workflow-steps {
display : grid ;
grid-template-columns : repeat ( 4 , 1 fr ) ;
gap : 0 ;
border : var ( - - border - thick ) solid var ( - - white ) ;
}
. workflow-step {
padding : 40 px 28 px ;
border-right : var ( - - border - thin ) solid var ( - - gray - mid ) ;
position : relative ;
}
. workflow-step : last-child {
border-right : none ;
}
. step-num {
font-size : 4 rem ;
font-weight : 700 ;
color : var ( - - neon - red ) ;
line-height : 1 ;
margin-bottom : 20 px ;
display : block ;
}
. workflow-step h3 {
font-size : 1 rem ;
text-transform : uppercase ;
letter-spacing : 1 px ;
margin-bottom : 12 px ;
font-weight : 700 ;
}
. workflow-step p {
font-size : 0.78 rem ;
line-height : 1.7 ;
color : var ( - - gray - light ) ;
}
. workflow-step . arrow {
position : absolute ;
right : -14 px ;
top : 50 % ;
transform : translateY ( -50 % ) ;
font-size : 1.5 rem ;
color : var ( - - neon - red ) ;
z-index : 2 ;
}
/* ========== DEMO / SCREENSHOT ========== */
. demo {
background : var ( - - off - white ) ;
border-bottom : var ( - - border - thick ) solid var ( - - black ) ;
}
. demo-mockup {
border : var ( - - border - thick ) solid var ( - - black ) ;
background : var ( - - white ) ;
position : relative ;
}
. demo-titlebar {
background : var ( - - black ) ;
color : var ( - - white ) ;
padding : 10 px 20 px ;
display : flex ;
align-items : center ;
justify-content : space-between ;
font-size : 0.75 rem ;
text-transform : uppercase ;
letter-spacing : 2 px ;
}
. demo-dots {
display : flex ;
gap : 8 px ;
}
. demo-dot {
width : 12 px ;
height : 12 px ;
border : var ( - - border - thin ) solid var ( - - white ) ;
}
. demo-dot . red {
background : var ( - - neon - red ) ;
border-color : var ( - - neon - red ) ;
}
. demo-body {
display : grid ;
grid-template-columns : 260 px 1 fr ;
min-height : 500 px ;
}
. demo-sidebar {
border-right : var ( - - border - thick ) solid var ( - - black ) ;
padding : 20 px ;
font-size : 0.72 rem ;
background : var ( - - off - white ) ;
}
. demo-tree-item {
padding : 6 px 0 ;
padding-left : 0 ;
border-bottom : 1 px solid #ddd ;
}
. demo-tree-item . indent-1 { padding-left : 16 px ; }
. demo-tree-item . indent-2 { padding-left : 32 px ; }
. demo-tree-item . indent-3 { padding-left : 48 px ; }
. demo-tree-item . icon {
margin-right : 6 px ;
}
. demo-tree-item . active {
background : var ( - - neon - red ) ;
color : var ( - - white ) ;
padding : 6 px 8 px ;
margin : 0 -20 px ;
padding-left : 52 px ;
}
. demo-main {
display : grid ;
grid-template-columns : repeat ( 3 , 1 fr ) ;
}
. demo-panel {
border-right : var ( - - border - thin ) solid var ( - - black ) ;
position : relative ;
display : flex ;
flex-direction : column ;
}
. demo-panel : last-child {
border-right : none ;
}
. demo-panel-header {
padding : 10 px 16 px ;
font-size : 0.65 rem ;
text-transform : uppercase ;
letter-spacing : 2 px ;
border-bottom : var ( - - border - thin ) solid var ( - - black ) ;
background : var ( - - off - white ) ;
font-weight : 700 ;
}
. demo-panel-body {
flex : 1 ;
display : flex ;
align-items : center ;
justify-content : center ;
padding : 30 px ;
position : relative ;
min-height : 400 px ;
}
. demo-pdf-placeholder {
width : 100 % ;
height : 100 % ;
position : absolute ;
top : 0 ;
left : 0 ;
display : flex ;
flex-direction : column ;
align-items : center ;
justify-content : center ;
font-size : 0.7 rem ;
color : var ( - - gray - light ) ;
text-transform : uppercase ;
letter-spacing : 2 px ;
}
. demo-pdf-placeholder . pdf-icon {
font-size : 3 rem ;
margin-bottom : 12 px ;
opacity : 0.4 ;
}
. demo-panel . diff . demo-panel-header {
background : var ( - - neon - red ) ;
color : var ( - - white ) ;
}
. demo-panel . diff . demo-pdf-placeholder {
background : repeating-linear-gradient (
45 deg ,
transparent ,
transparent 10 px ,
rgba ( 255 , 0 , 51 , 0.04 ) 10 px ,
rgba ( 255 , 0 , 51 , 0.04 ) 20 px
) ;
}
. demo-statusbar {
background : var ( - - black ) ;
color : var ( - - gray - light ) ;
padding : 8 px 20 px ;
font-size : 0.65 rem ;
display : flex ;
justify-content : space-between ;
text-transform : uppercase ;
letter-spacing : 1 px ;
}
. demo-statusbar . status-ok {
color : #00ff66 ;
}
/* ========== TECH STACK ========== */
. tech {
background : var ( - - white ) ;
border-bottom : var ( - - border - thick ) solid var ( - - black ) ;
}
. tech-grid {
display : grid ;
grid-template-columns : repeat ( 4 , 1 fr ) ;
border : var ( - - border - thick ) solid var ( - - black ) ;
}
. tech-item {
padding : 32 px 24 px ;
border-right : var ( - - border - thin ) solid var ( - - black ) ;
border-bottom : var ( - - border - thin ) solid var ( - - black ) ;
text-align : center ;
}
. tech-item : nth-child ( 4n ) {
border-right : none ;
}
. tech-item : nth-child ( n + 5 ) {
border-bottom : none ;
}
. tech-item : hover {
background : var ( - - black ) ;
color : var ( - - white ) ;
}
. tech-item . tech-icon {
font-size : 2 rem ;
margin-bottom : 10 px ;
display : block ;
}
. tech-item h4 {
font-size : 0.85 rem ;
text-transform : uppercase ;
letter-spacing : 2 px ;
font-weight : 700 ;
margin-bottom : 6 px ;
}
. tech-item p {
font-size : 0.68 rem ;
color : var ( - - gray - light ) ;
letter-spacing : 1 px ;
}
. tech-item : hover p {
color : var ( - - gray - light ) ;
}
/* ========== DOWNLOAD ========== */
. download {
background : var ( - - black ) ;
color : var ( - - white ) ;
border-bottom : var ( - - border - thick ) solid var ( - - neon - red ) ;
}
. download . section-title {
color : var ( - - white ) ;
}
. download . section-divider {
background : var ( - - white ) ;
}
. download-content {
display : grid ;
grid-template-columns : 1 fr 1 fr ;
gap : 0 ;
border : var ( - - border - thick ) solid var ( - - white ) ;
}
. download-info {
padding : 48 px 40 px ;
border-right : var ( - - border - thick ) solid var ( - - white ) ;
}
. download-info h3 {
font-size : 1.2 rem ;
text-transform : uppercase ;
letter-spacing : 1 px ;
margin-bottom : 20 px ;
font-weight : 700 ;
}
. download-info p {
font-size : 0.82 rem ;
line-height : 1.8 ;
color : var ( - - gray - light ) ;
margin-bottom : 24 px ;
}
. download-info ul {
list-style : none ;
margin-bottom : 32 px ;
}
. download-info ul li {
padding : 8 px 0 ;
font-size : 0.78 rem ;
border-bottom : 1 px solid var ( - - gray - mid ) ;
display : flex ;
align-items : center ;
gap : 10 px ;
}
. download-info ul li . check {
color : var ( - - neon - red ) ;
font-weight : 700 ;
}
. download-code {
padding : 48 px 40 px ;
display : flex ;
flex-direction : column ;
justify-content : center ;
}
. code-block {
background : var ( - - gray - dark ) ;
border : var ( - - border - thin ) solid var ( - - gray - mid ) ;
padding : 0 ;
margin-bottom : 20 px ;
}
. code-block-header {
padding : 10 px 16 px ;
font-size : 0.6 rem ;
text-transform : uppercase ;
letter-spacing : 2 px ;
color : var ( - - gray - light ) ;
border-bottom : var ( - - border - thin ) solid var ( - - gray - mid ) ;
}
. code-block pre {
padding : 20 px ;
font-family : var ( - - font - mono ) ;
font-size : 0.82 rem ;
line-height : 1.8 ;
overflow-x : auto ;
color : var ( - - off - white ) ;
}
. code-block pre . comment {
color : var ( - - gray - light ) ;
}
. code-block pre . cmd {
color : var ( - - neon - red ) ;
}
. btn-brutal {
display : inline-block ;
padding : 16 px 32 px ;
background : var ( - - neon - red ) ;
color : var ( - - white ) ;
font-family : var ( - - font - mono ) ;
font-size : 0.8 rem ;
font-weight : 700 ;
text-transform : uppercase ;
letter-spacing : 3 px ;
border : var ( - - border - thick ) solid var ( - - white ) ;
cursor : pointer ;
border-bottom : var ( - - border - thick ) solid var ( - - white ) ;
text-align : center ;
}
. btn-brutal : hover {
background : var ( - - white ) ;
color : var ( - - black ) ;
}
/* ========== FOOTER ========== */
footer {
background : var ( - - black ) ;
color : var ( - - white ) ;
padding : 0 ;
}
. footer-inner {
max-width : 1400 px ;
margin : 0 auto ;
display : grid ;
grid-template-columns : 1 fr 1 fr 1 fr ;
border-top : var ( - - border - thick ) solid var ( - - neon - red ) ;
}
. footer-col {
padding : 40 px 32 px ;
border-right : var ( - - border - thin ) solid var ( - - gray - mid ) ;
}
. footer-col : last-child {
border-right : none ;
}
. footer-col h4 {
font-size : 0.75 rem ;
text-transform : uppercase ;
letter-spacing : 3 px ;
margin-bottom : 20 px ;
color : var ( - - neon - red ) ;
font-weight : 700 ;
}
. footer-col p ,
. footer-col li {
font-size : 0.72 rem ;
line-height : 2 ;
color : var ( - - gray - light ) ;
}
. footer-col ul {
list-style : none ;
}
. footer-col a {
color : var ( - - gray - light ) ;
border-bottom : 1 px solid var ( - - gray - mid ) ;
}
. footer-col a : hover {
color : var ( - - white ) ;
background : var ( - - neon - red ) ;
}
. footer-bottom {
border-top : var ( - - border - thin ) solid var ( - - gray - mid ) ;
padding : 20 px 40 px ;
font-size : 0.65 rem ;
text-transform : uppercase ;
letter-spacing : 2 px ;
color : var ( - - gray - light ) ;
display : flex ;
justify-content : space-between ;
max-width : 1400 px ;
margin : 0 auto ;
}
/* ========== MARQUEE ========== */
. marquee-bar {
background : var ( - - neon - red ) ;
color : var ( - - white ) ;
padding : 10 px 0 ;
overflow : hidden ;
white-space : nowrap ;
font-size : 0.7 rem ;
text-transform : uppercase ;
letter-spacing : 4 px ;
font-weight : 700 ;
border-bottom : var ( - - border - thick ) solid var ( - - black ) ;
}
. marquee-content {
display : inline-block ;
animation : marquee 20 s linear infinite ;
}
@ keyframes marquee {
0 % { transform : translateX ( 0 ) ; }
100 % { transform : translateX ( -50 % ) ; }
}
/* ========== GLITCH EFFECT ========== */
. glitch {
position : relative ;
}
. glitch : hover :: before ,
. glitch : hover :: after {
content : attr ( data - text ) ;
position : absolute ;
top : 0 ;
left : 0 ;
width : 100 % ;
height : 100 % ;
}
. glitch : hover :: before {
color : var ( - - neon - red ) ;
z-index : -1 ;
animation : glitch-1 0.3 s steps ( 2 ) infinite ;
}
. glitch : hover :: after {
color : cyan ;
z-index : -2 ;
animation : glitch-2 0.3 s steps ( 2 ) infinite ;
}
@ keyframes glitch-1 {
0 % { clip-path : inset ( 20 % 0 60 % 0 ) ; transform : translate ( -3 px , 0 ) ; }
50 % { clip-path : inset ( 50 % 0 20 % 0 ) ; transform : translate ( 3 px , 0 ) ; }
100 % { clip-path : inset ( 10 % 0 70 % 0 ) ; transform : translate ( -2 px , 0 ) ; }
}
@ keyframes glitch-2 {
0 % { clip-path : inset ( 60 % 0 10 % 0 ) ; transform : translate ( 3 px , 0 ) ; }
50 % { clip-path : inset ( 20 % 0 50 % 0 ) ; transform : translate ( -3 px , 0 ) ; }
100 % { clip-path : inset ( 70 % 0 5 % 0 ) ; transform : translate ( 2 px , 0 ) ; }
}
/* ========== RESPONSIVE ========== */
@ media ( max-width : 1024px ) {
. features-grid {
grid-template-columns : repeat ( 2 , 1 fr ) ;
}
. feature-card : nth-child ( 3n ) {
border-right : var ( - - border - thin ) solid var ( - - black ) ;
}
. feature-card : nth-child ( 2n ) {
border-right : none ;
}
. feature-card : nth-child ( n + 4 ) {
border-bottom : var ( - - border - thin ) solid var ( - - black ) ;
}
. feature-card : nth-child ( n + 5 ) {
border-bottom : none ;
}
. workflow-steps {
grid-template-columns : repeat ( 2 , 1 fr ) ;
}
. workflow-step : nth-child ( 2 ) . arrow {
display : none ;
}
. workflow-step {
border-bottom : var ( - - border - thin ) solid var ( - - gray - mid ) ;
}
. tech-grid {
grid-template-columns : repeat ( 2 , 1 fr ) ;
}
. download-content {
grid-template-columns : 1 fr ;
}
. download-info {
border-right : none ;
border-bottom : var ( - - border - thick ) solid var ( - - white ) ;
}
. demo-body {
grid-template-columns : 1 fr ;
}
. demo-sidebar {
border-right : none ;
border-bottom : var ( - - border - thick ) solid var ( - - black ) ;
}
. demo-main {
grid-template-columns : 1 fr ;
}
. demo-panel {
border-right : none ;
border-bottom : var ( - - border - thin ) solid var ( - - black ) ;
}
. demo-panel-body {
min-height : 200 px ;
}
}
@ media ( max-width : 768px ) {
section {
padding : 60 px 20 px ;
}
. hero {
padding : 100 px 20 px 60 px ;
}
nav . nav-links {
display : none ;
}
. features-grid {
grid-template-columns : 1 fr ;
}
. feature-card {
border-right : none !important ;
border-bottom : var ( - - border - thin ) solid var ( - - black ) !important ;
}
. feature-card : last-child {
border-bottom : none !important ;
}
. workflow-steps {
grid-template-columns : 1 fr ;
}
. workflow-step {
border-right : none ;
}
. workflow-step . arrow {
display : none ;
}
. tech-grid {
grid-template-columns : 1 fr ;
}
. tech-item {
border-right : none !important ;
}
. footer-inner {
grid-template-columns : 1 fr ;
}
. footer-col {
border-right : none ;
border-bottom : var ( - - border - thin ) solid var ( - - gray - mid ) ;
}
. hero-stats {
flex-direction : column ;
}
. hero-stat {
border-right : none ;
border-bottom : var ( - - border - thin ) solid var ( - - gray - mid ) ;
}
. hero-stat : last-child {
border-bottom : none ;
}
}
/* ========== BLINK CURSOR ========== */
. cursor {
display : inline-block ;
width : 3 px ;
height : 1 em ;
background : var ( - - neon - red ) ;
margin-left : 4 px ;
vertical-align : text - bottom ;
animation : blink 0.7 s step-end infinite ;
}
@ keyframes blink {
0 % , 100 % { opacity : 1 ; }
50 % { opacity : 0 ; }
}
/* ========== SCROLL REVEAL ========== */
. reveal {
opacity : 0 ;
transform : translateY ( 30 px ) ;
}
. reveal . visible {
opacity : 1 ;
transform : translateY ( 0 ) ;
transition : opacity 0.1 s step-end , transform 0.1 s step-end ;
}
< / style >
< / head >
< body >
<!-- NAVIGATION -->
< nav >
< div class = "nav-inner" >
< a href = "#hero" class = "nav-brand" > < span > ■ < / span > DocuMentor< / a >
< ul class = "nav-links" >
< li > < a href = "#features" > Features< / a > < / li >
< li > < a href = "#workflow" > Workflow< / a > < / li >
< li > < a href = "#demo" > Demo< / a > < / li >
< li > < a href = "#tech" > Tech-Stack< / a > < / li >
< li > < a href = "#download" > Download< / a > < / li >
< / ul >
< / div >
< / nav >
<!-- HERO -->
< section class = "hero" id = "hero" >
< div class = "hero-content" >
< span class = "hero-label" > Desktop-Anwendung // PySide6 // Open Source< / span >
< h1 >
< span class = "glitch" data-text = "DOCU" > DOCU< / span > < span class = "red glitch" data-text = "MENTOR" > MENTOR< / span >
< / h1 >
< p class = "hero-tagline" >
XSL-Transformationen unter Kontrolle. Validieren. Vergleichen. Verifizieren.
Die Toolchain für Entwickler, die PDF-Dokumente aus XSL/XML erzeugen
und Änderungen lückenlos nachverfolgen muessen.< span class = "cursor" > < / span >
< / p >
< div class = "hero-stats" >
< div class = "hero-stat" >
< span class = "number" > 100+< / span >
< span class = "label" > XSL-Dateien< / span >
< / div >
< div class = "hero-stat" >
< span class = "number" > 3< / span >
< span class = "label" > PDF-Panels< / span >
< / div >
< div class = "hero-stat" >
< span class = "number" > BLAKE2B< / span >
< span class = "label" > Hash-Tracking< / span >
< / div >
< div class = "hero-stat" >
< span class = "number" > ∞ < / span >
< span class = "label" > Transformationen< / span >
< / div >
< / div >
< / div >
< / section >
<!-- MARQUEE -->
< div class = "marquee-bar" >
< div class = "marquee-content" >
SAXON • APACHE FOP • DIFF-PDF • POSTGRESQL • PYSIDE6 • BLAKE2B • XSL • XML • PDF •
SAXON • APACHE FOP • DIFF-PDF • POSTGRESQL • PYSIDE6 • BLAKE2B • XSL • XML • PDF •
SAXON • APACHE FOP • DIFF-PDF • POSTGRESQL • PYSIDE6 • BLAKE2B • XSL • XML • PDF •
SAXON • APACHE FOP • DIFF-PDF • POSTGRESQL • PYSIDE6 • BLAKE2B • XSL • XML • PDF •
< / div >
< / div >
<!-- FEATURES -->
< section class = "features" id = "features" >
< div class = "section-inner" >
< div class = "section-header reveal" >
< span class = "section-number" > 01 // Features< / span >
< h2 class = "section-title" > Was DocuMentor < span class = "muted" > leistet< / span > < / h2 >
< div class = "section-divider" > < / div >
< / div >
< div class = "features-grid reveal" >
< div class = "feature-card" >
< span class = "feature-icon" > ☰ < / span >
< span class = "feature-num" > Feature 01< / span >
< h3 > Baumstruktur< / h3 >
< p > Hierarchische Organisation von XSL-Transformationen. TreeNode, XslFile und XmlFile bilden eine übersichtliche Projektstruktur. Import- und Include-Abhängigkeiten auf einen Blick.< / p >
< / div >
< div class = "feature-card" >
< span class = "feature-icon" > ▦ < / span >
< span class = "feature-num" > Feature 02< / span >
< h3 > PDF-Diff< / h3 >
< p > Drei-Panel-Ansicht: Referenz, Diff und Neu. Visueller Vergleich mit Alpha-Blending. Änderungen in PDF-Dokumenten sofort erkennen — Pixel für Pixel.< / p >
< / div >
< div class = "feature-card" >
< span class = "feature-icon" > #_< / span >
< span class = "feature-num" > Feature 03< / span >
< h3 > Hash-Tracking< / h3 >
< p > BLAKE2B-Hashing zur Änderungsverfolgung von XML-Dateien. Automatische Berechnung beim Laden. 64-Zeichen-Hexdigest in project.yaml persistiert.< / p >
< / div >
< div class = "feature-card" >
< span class = "feature-icon" > ⇄ < / span >
< span class = "feature-num" > Feature 04< / span >
< h3 > Async-Verarbeitung< / h3 >
< p > Hintergrund-Threads für Hash-Berechnungen und Datenbank-Abfragen. Die UI bleibt reaktionsfähig — auch bei 100+ Dateien. Abbrechen-Dialog inklusive.< / p >
< / div >
< div class = "feature-card" >
< span class = "feature-icon" > ⎓ < / span >
< span class = "feature-num" > Feature 05< / span >
< h3 > PostgreSQL< / h3 >
< p > Datenbankintegration mit Polars und ConnectorX. SSL-Unterstützung. SQL-Abfragen direkt aus der Anwendung. Ergebnisse als DataFrames.< / p >
< / div >
< div class = "feature-card" >
< span class = "feature-icon" > ⚙ < / span >
< span class = "feature-num" > Feature 06< / span >
< h3 > Toolchain-Konfig< / h3 >
< p > Zentrale Verwaltung: Java VM, Saxon JAR, Apache FOP, diff-pdf. ID-basierte Referenzierung. Projekte koennen verschiedene Tool-Versionen verwenden.< / p >
< / div >
< / div >
< / div >
< / section >
<!-- WORKFLOW -->
< section class = "workflow" id = "workflow" >
< div class = "section-inner" >
< div class = "section-header reveal" >
< span class = "section-number" > 02 // Workflow< / span >
< h2 class = "section-title" > Vier Schritte < span style = "color:var(--neon-red);" > zum Ergebnis< / span > < / h2 >
< div class = "section-divider" > < / div >
< / div >
< div class = "workflow-steps reveal" >
< div class = "workflow-step" >
< span class = "step-num" > 01< / span >
< h3 > XSL bearbeiten< / h3 >
< p > Änderungen an den XSL-Dateien durchführen. Import- und Include-Verknüpfungen beachten — eine Änderung kann viele Dokumente betreffen.< / p >
< span class = "arrow" > ▶ < / span >
< / div >
< div class = "workflow-step" >
< span class = "step-num" > 02< / span >
< h3 > Transformation starten< / h3 >
< p > Saxon führt die XSLT-Transformation durch. Apache FOP erzeugt die PDF-Ausgabe. Alles konfigurierbar über die Toolchain.< / p >
< span class = "arrow" > ▶ < / span >
< / div >
< div class = "workflow-step" >
< span class = "step-num" > 03< / span >
< h3 > PDF-Diff begutachten< / h3 >
< p > Die Drei-Panel-Ansicht zeigt Referenz, Differenz und neues Dokument. diff-pdf markiert alle Änderungen visuell.< / p >
< span class = "arrow" > ▶ < / span >
< / div >
< div class = "workflow-step" >
< span class = "step-num" > 04< / span >
< h3 > Ergebnis verifizieren< / h3 >
< p > Wurden die richtigen PDFs geändert? Entsprechen die Änderungen den Erwartungen? Bei Bedarf: zurück zu Schritt 1.< / p >
< / div >
< / div >
< / div >
< / section >
<!-- DEMO / SCREENSHOT -->
< section class = "demo" id = "demo" >
< div class = "section-inner" >
< div class = "section-header reveal" >
< span class = "section-number" > 03 // Oberfläche< / span >
< h2 class = "section-title" > Die Anwendung < span class = "muted" > im Einsatz< / span > < / h2 >
< div class = "section-divider" > < / div >
< / div >
< div class = "demo-mockup reveal" >
< div class = "demo-titlebar" >
< div class = "demo-dots" >
< div class = "demo-dot red" > < / div >
< div class = "demo-dot" > < / div >
< div class = "demo-dot" > < / div >
< / div >
< span > DocuMentor v1.0 — Projekt: Pruefungsdokumente< / span >
< span style = "color:var(--gray-light);" > ■ PySide6< / span >
< / div >
< div class = "demo-body" >
< div class = "demo-sidebar" >
< div class = "demo-tree-item" > < span class = "icon" > ▼ < / span > < strong > Urkunden< / strong > < / div >
< div class = "demo-tree-item indent-1" > < span class = "icon" > ▼ < / span > bachelor_urkunde.xsl< / div >
< div class = "demo-tree-item indent-2" > < span class = "icon" > ● < / span > student_01.xml< / div >
< div class = "demo-tree-item indent-2 active" > < span class = "icon" > ● < / span > student_02.xml< / div >
< div class = "demo-tree-item indent-2" > < span class = "icon" > ● < / span > student_03.xml< / div >
< div class = "demo-tree-item indent-1" > < span class = "icon" > ▶ < / span > master_urkunde.xsl< / div >
< div class = "demo-tree-item" > < span class = "icon" > ▼ < / span > < strong > Zeugnisse< / strong > < / div >
< div class = "demo-tree-item indent-1" > < span class = "icon" > ▶ < / span > zeugnis_ba.xsl< / div >
< div class = "demo-tree-item indent-1" > < span class = "icon" > ▶ < / span > zeugnis_ma.xsl< / div >
< div class = "demo-tree-item" > < span class = "icon" > ▶ < / span > < strong > Bescheide< / strong > < / div >
< / div >
< div class = "demo-main" >
< div class = "demo-panel" >
< div class = "demo-panel-header" > Referenz-PDF< / div >
< div class = "demo-panel-body" >
< div class = "demo-pdf-placeholder" >
< span class = "pdf-icon" > ◼ < / span >
Referenz
< / div >
< / div >
< / div >
< div class = "demo-panel diff" >
< div class = "demo-panel-header" > ■ Diff-Ansicht< / div >
< div class = "demo-panel-body" >
< div class = "demo-pdf-placeholder" >
< span class = "pdf-icon" > ◼ < / span >
Differenz
< / div >
< / div >
< / div >
< div class = "demo-panel" >
< div class = "demo-panel-header" > Neues PDF< / div >
< div class = "demo-panel-body" >
< div class = "demo-pdf-placeholder" >
< span class = "pdf-icon" > ◼ < / span >
Neu generiert
< / div >
< / div >
< / div >
< / div >
< / div >
< div class = "demo-statusbar" >
< span > student_02.xml — BLAKE2B: < span style = "color:var(--neon-red);" > a3f7c9...< / span > < / span >
< span class = "status-ok" > ■ Transformation abgeschlossen< / span >
< / div >
< / div >
< / div >
< / section >
<!-- TECH STACK -->
< section class = "tech" id = "tech" >
< div class = "section-inner" >
< div class = "section-header reveal" >
< span class = "section-number" > 04 // Tech-Stack< / span >
< h2 class = "section-title" > Gebaut mit < span class = "muted" > roher Kraft< / span > < / h2 >
< div class = "section-divider" > < / div >
< / div >
< div class = "tech-grid reveal" >
< div class = "tech-item" >
< span class = "tech-icon" > ◆ < / span >
< h4 > Python< / h4 >
< p > Kern-Sprache< / p >
< / div >
< div class = "tech-item" >
< span class = "tech-icon" > ▣ < / span >
< h4 > PySide6< / h4 >
< p > Qt-GUI-Framework< / p >
< / div >
< div class = "tech-item" >
< span class = "tech-icon" > ♦ < / span >
< h4 > Saxon< / h4 >
< p > XSLT-Prozessor< / p >
< / div >
< div class = "tech-item" >
< span class = "tech-icon" > ▮ < / span >
< h4 > Apache FOP< / h4 >
< p > PDF-Erzeugung< / p >
< / div >
< div class = "tech-item" >
< span class = "tech-icon" > ▬ < / span >
< h4 > diff-pdf< / h4 >
< p > PDF-Vergleich< / p >
< / div >
< div class = "tech-item" >
< span class = "tech-icon" > ⎓ < / span >
< h4 > PostgreSQL< / h4 >
< p > Datenbank< / p >
< / div >
< div class = "tech-item" >
< span class = "tech-icon" > ☷ < / span >
< h4 > Polars< / h4 >
< p > DataFrames< / p >
< / div >
< div class = "tech-item" >
< span class = "tech-icon" > ⚙ < / span >
< h4 > Pydantic< / h4 >
< p > Konfiguration< / p >
< / div >
< / div >
< / div >
< / section >
<!-- DOWNLOAD -->
< section class = "download" id = "download" >
< div class = "section-inner" >
< div class = "section-header reveal" >
< span class = "section-number" > 05 // Loslegen< / span >
< h2 class = "section-title" > Jetzt < span style = "color:var(--neon-red);" > installieren< / span > < / h2 >
< div class = "section-divider" > < / div >
< / div >
< div class = "download-content reveal" >
< div class = "download-info" >
< h3 > Voraussetzungen< / h3 >
< p > DocuMentor läuft auf Linux, Windows und macOS. Die Konfiguration wird plattformspezifisch gespeichert.< / p >
< ul >
< li > < span class = "check" > [x]< / span > Python 3.13+< / li >
< li > < span class = "check" > [x]< / span > Java VM (für Saxon)< / li >
< li > < span class = "check" > [x]< / span > Saxon HE/PE/EE JAR< / li >
< li > < span class = "check" > [x]< / span > Apache FOP< / li >
< li > < span class = "check" > [x]< / span > diff-pdf< / li >
< li > < span class = "check" > [x]< / span > PostgreSQL (optional)< / li >
< / ul >
< a href = "#" class = "btn-brutal" > Dokumentation< / a >
< / div >
< div class = "download-code" >
< div class = "code-block" >
< div class = "code-block-header" > Terminal< / div >
< pre > < span class = "comment" > # Repository klonen< / span >
< span class = "cmd" > $< / span > git clone https://github.com/user/xsl-validator.git
< span class = "cmd" > $< / span > cd xsl-validator
< span class = "comment" > # Abhängigkeiten installieren< / span >
< span class = "cmd" > $< / span > uv sync
< span class = "comment" > # Anwendung starten< / span >
< span class = "cmd" > $< / span > uv run python src/main.py< / pre >
< / div >
< div class = "code-block" >
< div class = "code-block-header" > Linting< / div >
< pre > < span class = "cmd" > $< / span > uv run ruff check
< span class = "cmd" > $< / span > uv run ruff format< / pre >
< / div >
< / div >
< / div >
< / div >
< / section >
<!-- FOOTER -->
< footer >
< div class = "footer-inner" >
< div class = "footer-col" >
< h4 > DocuMentor< / h4 >
< p > Desktop-Anwendung zur Verwaltung und Validierung von XSL-Transformationen. Entwickelt für die kontinuierliche Weiterentwicklung von PDF-Dokumenten in Flexnow.< / p >
< / div >
< div class = "footer-col" >
< h4 > Links< / h4 >
< ul >
< li > < a href = "#features" > Features< / a > < / li >
< li > < a href = "#workflow" > Workflow< / a > < / li >
< li > < a href = "#demo" > Oberfläche< / a > < / li >
< li > < a href = "#tech" > Tech-Stack< / a > < / li >
< li > < a href = "#download" > Download< / a > < / li >
< / ul >
< / div >
< div class = "footer-col" >
< h4 > Tech< / h4 >
< ul >
< li > PySide6 / Qt< / li >
< li > Saxon XSLT< / li >
< li > Apache FOP< / li >
< li > diff-pdf< / li >
< li > PostgreSQL / Polars< / li >
< / ul >
< / div >
< / div >
< div class = "footer-bottom" >
< span > © 2026 DocuMentor< / span >
< span > Gebaut mit roher Kraft.< / span >
< / div >
< / footer >
< script >
// Brutalist scroll reveal — abrupt, no easing
document . addEventListener ( 'DOMContentLoaded' , ( ) => {
const reveals = document . querySelectorAll ( '.reveal' ) ;
const observer = new IntersectionObserver ( ( entries ) => {
entries . forEach ( entry => {
if ( entry . isIntersecting ) {
entry . target . classList . add ( 'visible' ) ;
observer . unobserve ( entry . target ) ;
}
} ) ;
} , {
threshold : 0.15
} ) ;
reveals . forEach ( el => observer . observe ( el ) ) ;
} ) ;
// Nav active state
document . addEventListener ( 'scroll' , ( ) => {
const sections = document . querySelectorAll ( 'section[id]' ) ;
const links = document . querySelectorAll ( '.nav-links a' ) ;
let current = '' ;
sections . forEach ( section => {
const top = section . offsetTop - 80 ;
if ( window . scrollY >= top ) {
current = section . getAttribute ( 'id' ) ;
}
} ) ;
links . forEach ( link => {
link . style . background = '' ;
link . style . color = '' ;
if ( link . getAttribute ( 'href' ) === '#' + current ) {
link . style . background = 'var(--neon-red)' ;
link . style . color = 'var(--white)' ;
}
} ) ;
} ) ;
< / script >
< / body >
< / html >