/* ============================================================
   digitalantrieb / 03 - LAYOUT
   Editorial-Raster, Antriebsachse, Buttons, Reveal-Primitive.
   ============================================================ */

.shell {
  position: relative;
  background: var(--stage);
  color: var(--on-stage);
  transition: background-color 1s var(--e-in-out), color 1s var(--e-in-out);
}

.section {
  position: relative;
  padding-block: var(--sec-y);
  padding-inline: var(--gutter);
  background: var(--stage);
  color: var(--on-stage);
  transition: background-color 0.9s var(--e-in-out), color 0.9s var(--e-in-out);
}
.section--tall { padding-block: var(--sec-y-lg); }
.section--flush { padding-inline: 0; }
.section--edge { padding-block: 0; }

.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
}
.wrap--rail { padding-left: var(--rail); }

/* 12 Spalten. Das Raster ist die Regel, von der wir bewusst abweichen. */
.grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: clamp(1rem, 2vw, 2rem);
}

/* ------------------------------------------------------------
   ANTRIEBSACHSE
   Die Achse des Logos, verlaengert durch das ganze Dokument.
   Zugleich Fortschrittsanzeige. Fuer Screenreader unsichtbar.
   ------------------------------------------------------------ */
.axis {
  position: fixed;
  top: 0;

  /* Die Achse SOLL der verlaengerte Schaft des Logos sein -
     stand aber 12 Pixel daneben. Jetzt wird die Lage gerechnet
     statt geschaetzt:

       linker Rand des Zeichens  = --gutter
       Schaft im Zeichen         = 15 von 32 Einheiten Breite
       Breite des Zeichens       = --mark-breite

     Damit wandert die Achse automatisch mit, wenn das Zeichen
     spaeter wieder eine andere Groesse bekommt. */
  left: calc(var(--gutter) + var(--mark-breite) * 15 / 32 - var(--hair) / 2);
  width: var(--hair);
  height: 100dvh;
  z-index: var(--z-rail);
  pointer-events: none;
  /* Neutrales Grau, damit die Spur auf heller und dunkler
     Buehne gleich gut liegt und kein JS sie nachfaerben muss. */
  background: rgba(128, 128, 128, 0.42);
  opacity: 0;
  transition: opacity 0.8s var(--e-out);
}
.axis::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  height: 100%;
  background: var(--signal);
  transform-origin: top center;
  transform: scaleY(var(--progress));
}
/* Der Kolben. Sitzt am Fortschrittspunkt. */
.axis::after {
  content: "";
  position: absolute;
  left: 50%;
  top: calc(var(--progress) * 100%);
  width: 7px;
  height: 7px;
  margin-left: -3px;
  margin-top: -3px;
  background: var(--signal);
  transform: rotate(45deg) scale(var(--piston, 1));
  transition: transform 0.3s var(--e-out);
}
html[data-motion="off"] .axis { opacity: 1; }

@media (max-width: 900px) { .axis { display: none; } }

/* ------------------------------------------------------------
   UEBERGANGSFLAECHE
   Faehrt beim Sprung aus dem Menue ueber den Bildschirm und
   verdeckt den Positionswechsel.
   ------------------------------------------------------------ */
.wipe {
  position: fixed;
  inset: 0;
  z-index: 65;
  background: var(--signal);
  transform: scaleY(0);
  transform-origin: bottom center;
  pointer-events: none;
}

/* ------------------------------------------------------------
   SEKTIONS-MARKER
   Ersetzt die uebliche Eyebrow. Haengt an der Achse, nicht
   ueber der Headline.
   ------------------------------------------------------------ */
.marker {
  position: absolute;
  /* Rechts neben der Achse, damit sich Linie und Schrift
     nicht ins Gehege kommen. */
  left: calc(var(--gutter) + 1.9rem);
  top: var(--sec-y);
  display: flex;
  align-items: center;
  gap: 0.7rem;
  writing-mode: vertical-rl;
  font-family: var(--font-mono);
  font-size: var(--t-meta);
  letter-spacing: var(--track-meta);
  text-transform: uppercase;
  color: var(--on-stage-2);
}
.marker b { color: var(--signal); font-weight: 500; }
@media (max-width: 900px) {
  .marker { position: static; writing-mode: horizontal-tb; margin-bottom: var(--stack-3); }
}

/* ------------------------------------------------------------
   BUTTONS
   Ein System: rechteckig, Hairline, Fuellung faehrt von der
   Cursorseite ein. Der Pfeil bewegt sich mit.
   ------------------------------------------------------------ */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 1.1rem;
  padding: 1.15rem 1.6rem;
  border: var(--hair) solid currentColor;
  border-radius: var(--r-0);
  font-family: var(--font-mono);
  font-size: var(--t-sm);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  isolation: isolate;
  transition: color var(--d-l3) var(--e-out), transform 0.14s var(--e-out);
}
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--signal);
  transform: scaleY(0);
  transform-origin: bottom center;
  transition: transform 0.42s var(--e-out);
}
.btn__arrow {
  display: block;
  width: 1.1em;
  transition: transform 0.42s var(--e-out);
}
.btn:active { transform: scale(0.975); }

@media (hover: hover) and (pointer: fine) {
  .btn:hover { color: #fff; border-color: var(--signal); }
  .btn:hover::before { transform: scaleY(1); transform-origin: top center; }
  .btn:hover .btn__arrow { transform: translateX(0.35em); }
}
.btn:focus-visible { color: #fff; border-color: var(--signal); }
.btn:focus-visible::before { transform: scaleY(1); transform-origin: top center; }

.btn--solid { background: var(--signal); border-color: var(--signal); color: #fff; }
.btn--solid::before { background: var(--ink); }
.btn--xl {
  padding: clamp(1.4rem, 2.6vw, 2.4rem) clamp(2rem, 4vw, 3.4rem);
  font-size: clamp(0.8rem, 1.1vw, 1rem);
  gap: 2rem;
}

/* Unterstrichener Textlink, der von links neu gezeichnet wird */
.ulink {
  position: relative;
  display: inline-block;
  padding-bottom: 2px;
}
.ulink::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: var(--hair);
  background: currentColor;
  transform: scaleX(1);
  transform-origin: right center;
  transition: transform 0.42s var(--e-out);
}
@media (hover: hover) and (pointer: fine) {
  .ulink:hover::after { transform: scaleX(0); transform-origin: right center; }
}

/* ------------------------------------------------------------
   REVEAL-PRIMITIVE
   Nur aktiv, wenn Motion laeuft. Sonst steht alles sichtbar da.
   ------------------------------------------------------------ */
html[data-motion="on"] [data-reveal="up"]   { opacity: 0; transform: translate3d(0, 2.6rem, 0); }
html[data-motion="on"] [data-reveal="left"] { opacity: 0; transform: translate3d(-4rem, 0, 0); }
html[data-motion="on"] [data-reveal="right"]{ opacity: 0; transform: translate3d(4rem, 0, 0); }
html[data-motion="on"] [data-reveal="mask"] { clip-path: inset(100% 0 0 0); }
html[data-motion="on"] [data-reveal="wipe"] { clip-path: inset(0 100% 0 0); }
html[data-motion="on"] [data-reveal="scale"]{ opacity: 0; transform: scale(1.08); }

/* Zeilenweiser Text-Reveal
   Die Maske schneidet auch seitlich. Passt eine Zeile nicht in
   ihren Container, wuerde sie stumm abgeschnitten statt
   umzubrechen. break-word ist die Notbremse dagegen; die
   Groessen sind so gewaehlt, dass sie nicht greifen muss. */
/* Oben Platz fuer Umlautpunkte und Akzente, unten fuer
   Unterlaengen. Bei einer Zeilenhoehe unter 1 ragen beide aus
   dem Zeilenkasten heraus und wuerden sonst abgeschnitten.
   Die negativen Aussenabstaende halten den Satzrhythmus. */
.line-mask {
  display: block;
  overflow: hidden;
  padding-top: 0.22em;
  margin-top: -0.22em;
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}
/* ------------------------------------------------------------
   WIE WEIT DER TEXT UNTER DIE MASKE MUSS

   Hier steckte ein Fehler, den der frueher vorgeschaltete
   Ladebildschirm verdeckt hat: Der Versatz stand auf 105 Prozent.

   Prozent beziehen sich aber auf die Hoehe des VERSCHOBENEN
   Elements, also auf die Zeilenhoehe. Die Maske darueber ist
   durch padding-top und padding-bottom hoeher als diese Zeile:
   bei der Schlagzeile 217 statt 155 Pixel. 105 Prozent von 155
   sind 163 - und damit blieben rund 14 Pixel sichtbar. Genau
   das waren die weissen Striche ueber dem Foto, die Oberkanten
   der Buchstaben.

   Der Wert deckt jetzt die Zeile plus beide Polsterungen ab,
   mit etwas Zugabe. Er steht als Variable, damit CSS und
   Skripte nicht auseinanderlaufen koennen.
   ------------------------------------------------------------ */
:root { --verdeckt: calc(100% + 0.5em); }

.line-mask > span { display: block; overflow-wrap: break-word; }
html[data-motion="on"] .line-mask > span { transform: translate3d(0, var(--verdeckt), 0); }

/* Wortweiser Reveal */
.word {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  padding-top: 0.22em;
  margin-top: -0.22em;
  padding-bottom: 0.12em;
  margin-bottom: -0.12em;
}
.word > i { display: inline-block; font-style: inherit; }
html[data-motion="on"] .word > i { transform: translate3d(0, var(--verdeckt), 0); }

/* Sobald das Intro durch ist, gilt der Ausgangszustand fuer den
   Hero nicht mehr. Selbst wenn eine Animation ihre Inline-Werte
   verliert, bleibt die Headline dann sichtbar. */
html.is-ready .hero__title .word > i,
html.is-ready .hero__title .line-mask > span { transform: none; }

/* Momentum: die Seite reagiert auf die Wucht des Scrollens */
.drive { will-change: transform; }

/* Hilfsklassen */
.sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.rule { height: var(--hair); background: var(--rule); border: 0; width: 100%; }
