/*---------------------------------------------------------------------*/
/*
  Stil ausschliesslich fuer portfolio.html.

  index.css bleibt unangetastet - die vier bestehenden Seiten sollen von
  dieser Seite nichts merken. portfolio.html laedt index.css UND diese Datei,
  erbt also alles (Karten, Navbar, Go-to-Top, Netz-Canvas) und legt hier nur
  das Portfolio-Eigene obendrauf.

  Harte Regel fuer alles hier drin: Farben NUR aus den Variablen, die
  index.js setzt (--linkc, --backg) bzw. die in index.css stehen (--them,
  --hovg). Eine einzige fest eingetragene Farbe, und der individuelle Modus
  faerbt diese Seite nicht mehr mit.

  Reihenfolge im <head>: index.css, dann Bootstrap, dann diese Datei. Sie
  laedt also NACH Bootstrap und braucht die doppelten Selektoren nicht, mit
  denen sich index.css gegen Bootstrap wehren muss.
*/

/*---------------------------------------------------------------------*/
/* Grundgeruest */

/* Nur diese Seite hat einen Sprungpfeil im Kopfbereich. Die Regel steht
   deshalb hier und nicht in index.css - die anderen Seiten sollen weiter
   hart springen. */
html {
    scroll-behavior: smooth;
}

/* Die Seite arbeitet mit viel Luft. Der Wert steht einmal hier, damit
   Abstaende zwischen Kopfbereich und Bloecken nicht auseinanderlaufen.
   --tiefe ist der Ausschlag des Parallax-Effekts; auf schmalen Schirmen
   weiter unten kleiner. */
.portfolio {
    --luft: clamp(4rem, 10vw, 9rem);
    --tiefe: 70px;

    /* Tempo beim Ueberfahren. Steht einmal hier, weil vier verschiedene
       Dinge gleich schnell reagieren sollen: die Pillen oben, die Knoepfe,
       der Pfeil und die grossen Symbolkacheln.
       Jede :active-Regel setzt --tempo fuer sich selbst kurz herunter - ein
       Klick soll sofort quittiert werden und nicht traege nachgeben. Ueber
       eine Variable statt ueber ein zweites transition, weil die
       Einblende-Regeln weiter unten spezifischer sind und ein transition auf
       :active schlicht verlieren wuerde. */
    --tempo: 0.45s;
}

/*---------------------------------------------------------------------*/
/* Scroll-Fortschritt am oberen Rand.
   scaleX statt width: das laeuft im Compositor und zwingt den Browser nicht
   bei jedem Scroll-Pixel zu einem neuen Layout. */
.fortschritt {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 3px;
    z-index: 100;
    pointer-events: none;
}

.fortschritt span {
    display: block;
    width: 100%;
    height: 100%;
    background: var(--linkc);
    opacity: 0.5;
    transform: scaleX(var(--fortschritt, 0));
    transform-origin: left center;
}

/* Bootstrap-Container waeren hier zu schmal fuer die zweispaltigen Bloecke. */
.portfolio .huelle {
    width: min(1140px, 92vw);
    margin-inline: auto;
}

/*---------------------------------------------------------------------*/
/* Kopfbereich (Hero) */

/* --weg zaehlt beim Runterscrollen von 0 auf 1 hoch (gesetzt von
   portfolio.js). Der Kopfbereich blendet dabei aus und wandert leicht nach
   oben, statt einfach aus dem Bild zu rutschen. translate veraendert das
   Layout nicht - darunter bleibt alles, wo es ist.
   Die Opacity liegt hier auf dem <section>, nicht auf .kopf-inhalt: dessen
   Opacity gehoert schon der Einblend-Animation. */
.kopfbereich {
    min-height: 100svh;
    display: flex;
    justify-content: center;
    align-items: center;
    padding: var(--luft) 0 6rem;
    opacity: calc(1 - var(--weg, 0));
    translate: 0 calc(var(--weg, 0) * -70px);
}

.kopf-inhalt {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
}

/* Titel und Namensbegruessung stehen auf einer gemeinsamen Grundlinie:
   klein "Moin Hendrik -", gross "IT Wolf". Auf schmalen Schirmen bricht die
   Begruessung von allein in die Zeile darueber. */
.kopf-titel {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: center;
    gap: 0.2em 0.5em;
    margin: 0;
    font-size: clamp(3.2rem, 13vw, 8.5rem);
    font-weight: 800;
    line-height: 0.95;
    letter-spacing: -0.03em;
    color: var(--linkc);
}

/* index.js schreibt die Begruessung in #headline - ohne gesetzten Namen
   bleibt das Element leer und wuerde sonst nur die Luecke aufziehen. */
.kopf-titel #headline {
    font-size: clamp(1rem, 2.6vw, 1.5rem);
    font-weight: 500;
    letter-spacing: 0;
    opacity: 0.65;
}

.kopf-titel #headline:empty {
    display: none;
}

/* Duenner Strich unter dem Titel - trennt Name und Projektliste, ohne eine
   Farbe zu erfinden. */
.kopf-strich {
    width: 64px;
    height: 2px;
    margin: 2.5rem auto 0;
    border-radius: 2px;
    background: color-mix(in srgb, var(--linkc) 35%, transparent);
}

/*---------------------------------------------------------------------*/
/* Projektliste im Kopfbereich (Sprungmarken) */

.projektliste {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.7rem;
    margin-top: 2.5rem;
    max-width: 760px;
}

.projektpille {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    padding: 10px 20px;
    border-radius: 999px;
    background: var(--them);
    color: var(--linkc);
    font-size: 0.95rem;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color var(--tempo) ease, transform var(--tempo) ease;
}

.projektpille:hover {
    background: var(--hovg);
    color: var(--linkc);
    transform: scale(1.06);
}

.projektpille:active {
    --tempo: 0.2s;
    transform: scale(0.94);
}

/* Das gerade sichtbare Projekt. Faellt beim Runterscrollen nicht auf - der
   Kopfbereich ist dann weg - hilft aber beim Zurueckscrollen. */
.projektpille.aktiv {
    background: var(--hovg);
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--linkc) 30%, transparent);
}

.projektpille svg {
    flex: 0 0 auto;
    opacity: 0.75;
}

/*---------------------------------------------------------------------*/
/* Pfeil nach unten */

.scrollpfeil {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    margin-top: 3.5rem;
    border-radius: 999px;
    color: var(--linkc);
    background: var(--them);
    transition: background-color var(--tempo) ease, transform var(--tempo) ease;
    animation: sanftHuepfen 2.4s ease-in-out infinite;
}

.scrollpfeil:hover {
    background: var(--hovg);
    transform: scale(1.1);
    cursor: pointer;
}

.scrollpfeil:active {
    --tempo: 0.2s;
    transform: scale(0.9);
}

@keyframes sanftHuepfen {
    0%, 100% { translate: 0 0; }
    50%      { translate: 0 8px; }
}

/*---------------------------------------------------------------------*/
/* Projektbloecke */

.projektblock {
    position: relative;
    overflow: hidden;
    padding: var(--luft) 0;
}

/* Grosse Ziffer im Hintergrund. Steht bewusst VOR dem Inhalt im HTML und
   bekommt kein z-index: so malt der Browser sie von allein darunter. Ein
   negatives z-index waere hier gefaehrlich - auf dieser Hoehe liegt schon
   das Netz-Canvas (#backgroundCanvas, z-index -1). */
/* --p setzt portfolio.js je Block auf -1 (Block noch unten) bis +1 (Block
   schon oben). Die Ziffer wandert dadurch gegenlaeufig zum Scrollen und
   liegt scheinbar tiefer als der Text.
   Zentriert wird ueber transform, verschoben ueber die eigenstaendige
   translate-Eigenschaft - die beiden ueberschreiben sich nicht, der Browser
   rechnet erst translate, dann transform. */
.blocknummer {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    translate: 0 calc(var(--p, 0) * var(--tiefe) * -1);
    font-size: clamp(11rem, 32vw, 26rem);
    font-weight: 800;
    line-height: 1;
    letter-spacing: -0.05em;
    color: var(--linkc);
    opacity: 0.05;
    pointer-events: none;
    user-select: none;
}

.projekt-inhalt {
    position: relative;
    display: flex;
    align-items: center;
    gap: clamp(2rem, 6vw, 5rem);
}

/* Jeder zweite Block spiegelt sich - das Auge bekommt beim Scrollen einen
   Rhythmus statt fünf gleicher Zeilen. */
.projektblock.gedreht .projekt-inhalt {
    flex-direction: row-reverse;
}

/*---------------------------------------------------------------------*/
/* Symbol links/rechts */

/* Zwei Ebenen: aussen der weiche Schein, innen die Kachel. Der Schein liegt
   auf einem eigenen Element statt auf ::before, damit hier ebenfalls kein
   negatives z-index noetig ist (siehe .blocknummer). */
.symbol-huelle {
    flex: 0 0 auto;
    padding: clamp(0.8rem, 2vw, 1.6rem);
    border-radius: 64px;
    background: radial-gradient(circle at 30% 25%,
                color-mix(in srgb, var(--linkc) 11%, transparent),
                transparent 70%);
}

/* Das Symbol wandert ebenfalls mit --p, aber schwaecher als die Ziffer -
   dadurch entstehen drei Ebenen: Ziffer (weit hinten), Symbol, Text.
   Kein transition auf translate: der Wert kommt pro Scroll-Frame neu, ein
   Uebergang wuerde nur hinterherhinken. */
/* Die Kachel ist selbst ein Link auf das Projekt - dasselbe Ziel wie der
   Knopf darunter, nur die groessere Trefferflaeche. */
.projekt-symbol {
    display: grid;
    place-items: center;
    width: clamp(130px, 20vw, 210px);
    aspect-ratio: 1;
    border-radius: 48px;
    background: var(--them);
    color: var(--linkc);
    text-decoration: none;
    translate: 0 calc(var(--p, 0) * var(--tiefe) * -0.32);
    transition: background-color var(--tempo) ease, transform var(--tempo) ease;
}

.projekt-symbol svg {
    width: 44%;
    height: 44%;
}

/* Der Block als Ganzes hebt die Kachel schon leicht an - so sieht man beim
   Ueberfahren, dass hier etwas zusammengehoert.

   Das :not(:hover) ist der Kern der Sache und darf nicht weg: ohne es hat
   dieser Selektor DREI Bestandteile (.projektblock, :hover, .projekt-symbol)
   und schlaegt damit .projekt-symbol:hover mit zweien - die Kachel bliebe
   auch beim direkten Ueberfahren auf 1.05 stehen. Weil der Block die volle
   Breite hat, waere sie da laengst gewachsen, und auf der Kachel selbst
   passierte gar nichts mehr. Genauso beim Klick.
   So gelesen: der Block hebt die Kachel nur an, solange der Zeiger NEBEN
   ihr steht - steht er drauf, gehoert sie den beiden Regeln darunter. */
.projektblock:hover .projekt-symbol:not(:hover) {
    background: var(--hovg);
    transform: scale(1.05);
}

/* Direkt auf der Kachel deutlicher, damit sie sich vom blossen Block-Hover
   abhebt und als anklickbar zu erkennen ist. */
.projekt-symbol:hover {
    background: var(--hovg);
    color: var(--linkc);
    transform: scale(1.11);
}

.projekt-symbol:active {
    --tempo: 0.2s;
    transform: scale(0.95);
}

/*---------------------------------------------------------------------*/
/* Textspalte */

.projekt-text {
    flex: 1 1 0;
    min-width: 0;
}

.projekt-nummer {
    margin: 0 0 0.9rem;
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: color-mix(in srgb, var(--linkc) 50%, transparent);
}

.projekt-titel {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.7rem;
    margin: 0 0 1.1rem;
    font-size: clamp(1.9rem, 5vw, 3.1rem);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -0.02em;
    color: var(--linkc);
}

/* Gleiche Marke wie die .beta-badge auf der Startseite, nur nicht absolut
   positioniert - hier sitzt sie im Textfluss neben der Ueberschrift. */
.neu-marke {
    padding: 2px 9px;
    border-radius: 999px;
    background: var(--them);
    color: var(--linkc);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.5px;
    white-space: nowrap;
}

.projekt-beschreibung {
    max-width: 56ch;
    margin: 0 0 1.6rem;
    font-size: clamp(1rem, 1.6vw, 1.12rem);
    line-height: 1.7;
    color: color-mix(in srgb, var(--linkc) 78%, transparent);
}

/*---------------------------------------------------------------------*/
/* Stichworte */

.stichworte {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0 0 2rem;
    padding: 0;
    list-style: none;
}

.stichworte li {
    padding: 5px 13px;
    border-radius: 999px;
    background: var(--them);
    color: color-mix(in srgb, var(--linkc) 80%, transparent);
    font-size: 0.86rem;
    white-space: nowrap;
}

/*---------------------------------------------------------------------*/
/* Knopf */

.projekt-knopf {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    padding: 13px 26px;
    border-radius: 999px;
    background: var(--them);
    color: var(--linkc);
    font-weight: 600;
    text-decoration: none;
    transition: background-color var(--tempo) ease, transform var(--tempo) ease;
}

.projekt-knopf:hover {
    background: var(--hovg);
    color: var(--linkc);
    transform: scale(1.05);
}

.projekt-knopf:active {
    --tempo: 0.2s;
    transform: scale(0.94);
}

/* Der Pfeil wandert beim Hover ein Stueck mit - im selben Tempo wie der
   Knopf waechst, sonst laufen die beiden Bewegungen auseinander. */
.projekt-knopf svg {
    transition: translate var(--tempo) ease;
}

.projekt-knopf:hover svg {
    translate: 4px 0;
}

/*---------------------------------------------------------------------*/
/* Abschluss unter dem letzten Projekt */

.ausklang {
    padding: var(--luft) 0 calc(var(--luft) / 1.5);
    text-align: center;
}

.ausklang p {
    max-width: 46ch;
    margin: 0 auto 2rem;
    font-size: clamp(1.05rem, 2vw, 1.25rem);
    line-height: 1.7;
    color: color-mix(in srgb, var(--linkc) 72%, transparent);
}

/*---------------------------------------------------------------------*/
/* Scroll-Animation
   Startzustand hier, Endzustand unter .sichtbar. portfolio.js haengt
   .sichtbar an, sobald ein Block in den Blick kommt.

   Wichtig: greift nur unter .js-an. Diese Klasse setzt portfolio.js ganz
   oben selbst - ohne JavaScript bleibt sie aus und die Seite ist einfach
   sofort vollstaendig da, statt unsichtbar zu bleiben. */

/* Der Abschnitt selbst blendet nur auf. Die Fahrt von unten machen die
   Zeilen darin (.stufen) - beides gleichzeitig waere die doppelte Strecke
   und wirkt traege. */
.js-an .enthuellen > * {
    opacity: 0;
    transition: opacity 0.7s ease;
}

.js-an .enthuellen.sichtbar > * {
    opacity: 1;
}

/* Die grosse Hintergrundziffer bleibt auch sichtbar sehr blass. */
.js-an .enthuellen.sichtbar > .blocknummer {
    opacity: 0.05;
}

/* Innerhalb eines Blocks laufen die Zeilen versetzt ein, 80 ms Abstand.
   .stufen sitzt immer auf einem NACHFAHREN von .enthuellen, nie auf
   demselben Element - sonst greift der Nachfahren-Selektor unten nicht.

   Die Hover-Eigenschaften stehen hier mit drin, obwohl sie mit dem Einfliegen
   nichts zu tun haben: Diese Regel ist spezifischer als .projekt-knopf oder
   .scrollpfeil und wuerde deren transition sonst komplett ersetzen - der
   Hover spraenge dann hart um, statt weich zu laufen.
   Die Staffelung laeuft ueber --einflug statt ueber transition-delay, weil
   ein Delay fuer ALLE Eigenschaften gilt: der Knopf haette sonst dauerhaft
   eine Verzoegerung von bis zu 400 ms, bevor er auf den Zeiger reagiert. */
.js-an .stufen > * {
    opacity: 0;
    translate: 0 26px;
    transition: opacity 0.6s ease var(--einflug, 0ms),
                translate 0.6s ease var(--einflug, 0ms),
                background-color var(--tempo) ease,
                transform var(--tempo) ease;
}

.js-an .sichtbar .stufen > * {
    opacity: 1;
    translate: 0 0;
}

.js-an .sichtbar .stufen > *:nth-child(1) { --einflug: 0ms; }
.js-an .sichtbar .stufen > *:nth-child(2) { --einflug: 80ms; }
.js-an .sichtbar .stufen > *:nth-child(3) { --einflug: 160ms; }
.js-an .sichtbar .stufen > *:nth-child(4) { --einflug: 240ms; }
.js-an .sichtbar .stufen > *:nth-child(5) { --einflug: 320ms; }
.js-an .sichtbar .stufen > *:nth-child(6) { --einflug: 400ms; }

/*---------------------------------------------------------------------*/
/* Einflug aus der Seite

   Das Symbol kommt von aussen herein und waechst dabei auf, der Text von der
   Gegenseite - bei jedem zweiten Block spiegelverkehrt. Die Kurve
   (0.16, 1, 0.3, 1) startet schnell und laeuft weich aus; ein lineares oder
   ease-Ende wirkt bei so langen Wegen zaeh. */

.js-an .projektblock .symbol-huelle {
    opacity: 0;
    translate: -70px 0;
    scale: 0.85;
    transition: opacity 0.8s ease,
                translate 0.9s cubic-bezier(0.16, 1, 0.3, 1),
                scale 0.9s cubic-bezier(0.16, 1, 0.3, 1);
}

.js-an .projektblock.gedreht .symbol-huelle {
    translate: 70px 0;
}

.js-an .projektblock.sichtbar .symbol-huelle {
    opacity: 1;
    translate: 0 0;
    scale: 1;
}

/* Die Textzeilen ueberschreiben nur die Richtung - Staffelung und Deckkraft
   kommen weiter von .stufen oben. Der Hover muss hier nochmal mit rein: die
   Regel ist wieder spezifischer als .projekt-knopf (siehe .stufen). */
.js-an .projektblock .projekt-text > * {
    translate: 34px 16px;
    transition: opacity 0.6s ease var(--einflug, 0ms),
                translate 0.7s cubic-bezier(0.16, 1, 0.3, 1) var(--einflug, 0ms),
                background-color var(--tempo) ease,
                transform var(--tempo) ease;
}

.js-an .projektblock.gedreht .projekt-text > * {
    translate: -34px 16px;
}

.js-an .projektblock.sichtbar .projekt-text > * {
    translate: 0 0;
}

/*---------------------------------------------------------------------*/
/* Kopfbereich: eigene Staffelung, weil die fuenf Pillen einzeln einfliegen
   sollen. Die Liste selbst ist Stufe 3 (160 ms), die Pillen setzen ab
   200 ms nach - und der Pfeil kommt ganz zum Schluss. */

/* Auch hier Einfliegen und Hover in einer Liste, sonst haetten die fuenf
   Pillen gar keinen weichen Uebergang beim Ueberfahren (siehe .stufen).
   Das Einfliegen benutzt die eigenstaendige scale-Eigenschaft, der Hover
   transform: scale() - zwei getrennte Eigenschaften, die sich deshalb nicht
   in die Quere kommen. */
.js-an .projektliste > * {
    opacity: 0;
    translate: 0 14px;
    scale: 0.94;
    transition: opacity 0.5s ease var(--einflug, 0ms),
                translate 0.5s cubic-bezier(0.16, 1, 0.3, 1) var(--einflug, 0ms),
                scale 0.5s cubic-bezier(0.16, 1, 0.3, 1) var(--einflug, 0ms),
                background-color var(--tempo) ease,
                transform var(--tempo) ease;
}

.js-an .sichtbar .projektliste > * {
    opacity: 1;
    translate: 0 0;
    scale: 1;
}

.js-an .sichtbar .projektliste > *:nth-child(1) { --einflug: 200ms; }
.js-an .sichtbar .projektliste > *:nth-child(2) { --einflug: 265ms; }
.js-an .sichtbar .projektliste > *:nth-child(3) { --einflug: 330ms; }
.js-an .sichtbar .projektliste > *:nth-child(4) { --einflug: 395ms; }
.js-an .sichtbar .projektliste > *:nth-child(5) { --einflug: 460ms; }
/* Die sechste Pille gibt es nur als Super-Admin. Ohne diese Zeile fiele sie
   auf --einflug: 0ms zurueck und floege als erste ein statt als letzte. */
.js-an .sichtbar .projektliste > *:nth-child(6) { --einflug: 525ms; }

.js-an .sichtbar .kopf-inhalt > .scrollpfeil { --einflug: 580ms; }

/*---------------------------------------------------------------------*/
/* Schmale Schirme */

@media (max-width: 767.98px) {
    .portfolio {
        /* Weniger Tiefe: auf kleinen Schirmen faellt ein grosser Versatz eher
           als Wackeln auf denn als Ebene. */
        --tiefe: 26px;
    }

    .projekt-inhalt,
    .projektblock.gedreht .projekt-inhalt {
        flex-direction: column;
        align-items: flex-start;
        text-align: left;
    }

    .symbol-huelle {
        align-self: center;
    }

    /* Gestapelt gibt es kein "aussen" mehr - Symbol und Text kommen beide
       von unten, sonst schoebe der Einflug die Seite in die Breite. */
    .js-an .projektblock .symbol-huelle,
    .js-an .projektblock.gedreht .symbol-huelle {
        translate: 0 34px;
    }

    .js-an .projektblock .projekt-text > *,
    .js-an .projektblock.gedreht .projekt-text > * {
        translate: 0 22px;
    }

    .js-an .projektblock.sichtbar .symbol-huelle,
    .js-an .projektblock.sichtbar .projekt-text > * {
        translate: 0 0;
    }

    .projektpille {
        font-size: 0.88rem;
        padding: 9px 16px;
    }

    .blocknummer {
        font-size: 40vw;
    }
}

/*---------------------------------------------------------------------*/
/* Wer im Betriebssystem weniger Bewegung eingestellt hat, bekommt alles
   sofort und ohne Fahrt zu sehen. portfolio.js setzt .sichtbar dann
   ebenfalls direkt, damit nichts unsichtbar haengen bleibt. */

@media (prefers-reduced-motion: reduce) {
    .js-an .enthuellen > *,
    .js-an .stufen > *,
    .js-an .projektliste > *,
    .js-an .projektblock .symbol-huelle,
    .js-an .projektblock.gedreht .symbol-huelle,
    .js-an .projektblock .projekt-text > *,
    .js-an .projektblock.gedreht .projekt-text > * {
        opacity: 1;
        translate: 0 0;
        scale: 1;
        transition: none;
        --einflug: 0ms;
    }

    .js-an .enthuellen > .blocknummer {
        opacity: 0.05;
    }

    /* Parallax und Ausblenden des Kopfbereichs setzt portfolio.js hier gar
       nicht erst - diese Regeln fangen nur den Fall ab, dass die Einstellung
       erst nach dem Laden umgestellt wird. */
    .blocknummer,
    .projekt-symbol {
        translate: 0 0;
    }

    .kopfbereich {
        opacity: 1;
        translate: 0 0;
    }

    .scrollpfeil {
        animation: none;
    }

    html {
        scroll-behavior: auto;
    }
}
