/* Cockpit-Teaser hinter dem QR-Code im CAMPEXPO MAG.

   Look von jawigo.de: Farben nur über tokens.css, Schrift Open Sans. Beides liegt als unveränderte
   Kopie der Website im Teaser-Ordner, weil der Ordner auch für sich allein ausgeliefert wird.

   Keine Systemschrift: Open Sans steht vor dem Stapel aus --font-ui, der auf der Website unter
   Windows Segoe UI zeigt.

   Hochkant- oder Querfassung entscheidet allein das Fensterformat: (orientation: portrait).
   teaser.js fragt dieselbe Bedingung ab und setzt data-layout auf <html>.

   Eine Bewegungssprache: Auftritte, Abgänge und Pausen stehen in teaser.js, hier stehen nur die
   Ausgangswerte (opacity 0) und die Ausrichtung. Je Fassung eine Ausrichtung — quer mittig,
   hochkant linksbündig. Kein Element bringt eine eigene Kurve oder eine eigene Dauer mit. */

@font-face {
  font-family: "Open Sans";
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url("fonts/open-sans-latin.woff2") format("woff2");
}

*, *::before, *::after { box-sizing: border-box; }

/* Die sichtbare Fläche, nicht das Layout-Fenster. Safari am iPhone lässt das Layout-Fenster so hoch,
   als wären seine Leisten eingefahren; wer 100 % nimmt, reicht unter die Leiste und verliert unten ein
   Stück Bild. 100dvh folgt dem, was wirklich zu sehen ist, und wächst mit, sobald die Leiste
   verschwindet. Die Zeile mit % bleibt als Rückfall für Browser ohne dvh stehen — dort ändert sich
   nichts, weil es dort auch keine ein- und ausfahrenden Leisten gibt. */
html, body { height: 100%; height: 100dvh; }

body {
  margin: 0;
  overflow: hidden;
  background: var(--brand-black);
  color: var(--on-graphite-soft);
  font-family: "Open Sans", var(--font-ui);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}

[hidden] { display: none !important; }

/* Bühne mit den Szenen. Welche Szene zu sehen ist und wie weit ein Element aufgetreten ist, setzt
   teaser.js nach der Abspielzeit der Musik (data-start, data-end, data-in, data-out).

   Im Fenster steht immer nur eines: entweder eine Zeile oder eine Aufnahme, nie beides. Deshalb
   bekommt jedes von beiden das ganze Fenster, und die Aufnahme braucht keinen Schleier. */
.stage {
  position: fixed;
  inset: 0;
  height: 100%;
  height: 100dvh;
  overflow: hidden;
  background: var(--brand-black);
}
.scene { position: absolute; inset: 0; }

/* Alle Szenen teilen dieselbe Aufteilung: eine Spalte, quer mittig. Hochkant kippt das weiter
   unten auf linksbündig — je Fassung eine Ausrichtung. */
.scene-lines, .frame, .scene-devices {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0 8vw;
  text-align: center;
}

.line {
  margin: 0;
  position: relative;
  font-size: clamp(28px, 6.2vh, 76px);
  font-weight: 400;
  line-height: 1.18;
  letter-spacing: -.015em;
  color: var(--ink-on-brand);
  opacity: 0;
}
.line + .line { margin-top: .42em; }
.line-muted { color: var(--on-graphite-muted); }

/* Genau ein rotes Element im Bild. Es wandert vom Startknopf über „21:04" und die Staccato-Wörter
   durch die Geräte in den Satz; auf der Kamerafahrt trägt die App selbst das Rot, am Schluss das
   „c1:" der Wortmarke. Ausgezeichnet ist es in index.html. */
.accent { color: var(--brand-red); }
/* Das rote Wort bleibt beisammen: „An- und Abreisen" ist ein Wort mit Bindestrich-Ellipse. Hochkant
   bricht die Zeile davor um, nicht mittendrin — sonst steht am Zeilenende ein einzelnes rotes „An-".
   Die übrigen Akzente sind einzelne Wörter, für sie ändert sich nichts. */
.line .accent { white-space: nowrap; }

/* Szene 2: Wort und Bild gehören zusammen, stehen aber nacheinander im Fenster, nie nebeneinander.
   Die Aufnahme bekommt darum das ganze Fenster: eingepasst (object-fit: contain), außen herum
   Markenschwarz. Je Fassung gibt es einen eigenen Zuschnitt (index.html), der quer breit und
   hochkant stehend ist — deshalb bleibt außen herum in beiden Fassungen wenig Schwarz. Über ihr liegt nichts — kein Schleier, keine Abdunklung, keine Weichzeichnung; sie
   steht so scharf da, wie die Datei hergibt. Den leichten Zug (Bilder fahren, kein Hub) setzt
   teaser.js auf das <img> selbst. */
.frame { position: absolute; inset: 0; }
.shot { position: absolute; inset: 0; margin: 0; opacity: 0; }
/* <picture> wählt nur die Datei aus und soll im Aufbau der Seite nicht mitzählen: display: contents
   nimmt seinen Kasten heraus, das <img> liegt damit unmittelbar in der Fläche. */
.shot picture { display: contents; }
.shot img { display: block; width: 100%; height: 100%; object-fit: contain; }

/* Szene 3: Geräte im Strichstil der Website. Die Symbole stehen als Vektorgrafik in index.html
   selbst und nicht in einer eigenen Datei, weil Safari fremde Dateien in <use> nicht lädt. */
.devices {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: clamp(20px, 5vw, 56px);
}
/* Symbol und Bezeichnung gehören zusammen: ein Kasten, eine Farbe, ein Auftritt. Die Farbe steht hier
   und wird vererbt — das Symbol zeichnet mit currentColor, die Bezeichnung schreibt damit. So wandert
   das Rot über das Paar und bleibt EIN Blickfang, auch für die Prüfung. */
.device {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  color: var(--on-graphite-soft);
  stroke: currentColor;
  opacity: 0;
}
.device-icon {
  width: clamp(38px, 8vh, 82px);
  height: clamp(38px, 8vh, 82px);
  fill: none;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* Klein und ruhig: Sie benennt das Symbol, sie tritt nicht gegen es an. */
.device-name {
  font-size: clamp(12px, 1.7vh, 16px);
  font-weight: 400;
  letter-spacing: .01em;
  white-space: nowrap;
}

/* Kamerafahrt: teaser.js zeichnet jedes Bild selbst in die Leinwand. Außerhalb der Aufnahme steht
   derselbe Markenschwarz wie hinter den Zeilen-Szenen. */
.scene-camera { background: var(--brand-black); }
.scene-camera canvas { position: absolute; inset: 0; display: block; width: 100%; height: 100%; opacity: 0; }

/* Szenen 6 bis 8: das Schlussbild. Es beginnt auf derselben Graphit-Fläche, auf der die
   Kamerafahrt endet, damit dort kein Schnitt zu sehen ist. Anders als die Szenen bleibt es in
   beiden Fassungen mittig: Es ist das Gegenstück zum Startbild, die beiden gehören zusammen. */
.scene-outro {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(18px, 4vh, 40px);
  padding: 24px;
  overflow: hidden;
  background: var(--graphite);
}
.outro-glow {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 120vmin;
  height: 120vmin;
  max-width: 1200px;
  max-height: 1200px;
  margin: -60vmin 0 0 -60vmin;
  opacity: 0;
  pointer-events: none;
}

/* Das Licht von Startbild und Schlussbild — beide tragen dasselbe, sonst sähen Anfang und Ende
   verschieden aus.

   Es ist eine Leinwand, keine CSS-Fläche: Über 540 px fallen zwischen Mitte und Rand nur rund 15
   Achtbit-Stufen an. Ein Verlauf kann dort gar nicht genug Zwischenwerte haben, und der Browser malt
   die fehlenden als Ringe. Deshalb rechnet teaser.js jeden Bildpunkt selbst und dithert ihn dabei
   (paintGlow) — Größe, Lage und Helligkeit bleiben, die Ringe verschwinden. */
.start-glow, .outro-glow { display: block; }

.outro-wordmark {
  position: relative;
  display: block;
  width: auto;
  height: clamp(52px, 12vh, 146px);
  opacity: 0;
}

.outro-year {
  position: relative;
  margin: 0;
  font-size: clamp(22px, 4.6vh, 54px);
  font-weight: 400;
  letter-spacing: .04em;
  color: var(--ink-on-brand);
  opacity: 0;
}

/* Zum Schluss: zurück an den Anfang, dazu die Rechtslinks wie auf dem Startbild. */
.outro-end {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(20px + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(14px, 3vh, 26px);
  opacity: 0;
}
.replay {
  padding: 6px 10px;
  border: 0;
  border-radius: var(--radius-btn);
  background: none;
  color: var(--on-graphite-soft);
  font: 400 16px/1 "Open Sans", var(--font-ui);
  text-decoration: underline;
  text-underline-offset: 5px;
  cursor: pointer;
}
.replay:hover { color: var(--ink-on-brand); }
.replay:focus-visible { outline: 3px solid var(--ink-on-brand); outline-offset: 3px; }

/* Startbild: Graphit mit dem Licht der Website (Kopf der Startseite, Fuß). Es geht in denselben
   0,3 s ab wie jedes andere Element — der erste Anker liegt bei 0,406 s. */
.start {
  position: fixed;
  inset: 0;
  height: 100%;
  height: 100dvh;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(36px, 7vh, 64px);
  padding: 24px;
  overflow: hidden;
  background: var(--graphite);
  transition: opacity .3s var(--ease-out), visibility 0s linear .3s;
}
.start.is-leaving { opacity: 0; visibility: hidden; }

/* Geordnetes Dithern über Startbild und Schlussbild. Die Leinwand rechnet den Verlauf zwar genau,
   aber die Deckkraft des Lichts wird beim Zusammensetzen erneut auf 8 Bit gerundet — und beim
   Aufblenden bleibt von einem Dithern in der Leinwand nichts übrig. Diese Fläche liegt darüber und
   ist von der Blende unabhängig: Sie hebt jeden Bildpunkt nach einem festen 8-×-8-Muster (Bayer) um
   0 bis gut eine Achtbit-Stufe an, bevor gerundet wird. Aus einer Ringkante wird damit ein Muster,
   das das Auge zu dem Zwischenwert mittelt, den 8 Bit nicht hergeben.

   Geordnet statt zufällig: Weißes Rauschen bräuchte für dieselbe Wirkung mehr Ausschlag und klumpt
   dabei sichtbar. Das Muster steht still, es flimmert also nichts, und es kostet eine Kachel von
   8 × 8 Punkten. Die Grafik steckt in dieser Datei, es wird keine Datei und kein fremder Host
   geladen. */
.start::after, .scene-outro::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' shape-rendering='crispEdges'%3E%3Crect x='0' y='0' width='1' height='1' fill='white' fill-opacity='.0078'/%3E%3Crect x='1' y='0' width='1' height='1' fill='white' fill-opacity='.5078'/%3E%3Crect x='2' y='0' width='1' height='1' fill='white' fill-opacity='.1328'/%3E%3Crect x='3' y='0' width='1' height='1' fill='white' fill-opacity='.6328'/%3E%3Crect x='4' y='0' width='1' height='1' fill='white' fill-opacity='.0391'/%3E%3Crect x='5' y='0' width='1' height='1' fill='white' fill-opacity='.5391'/%3E%3Crect x='6' y='0' width='1' height='1' fill='white' fill-opacity='.1641'/%3E%3Crect x='7' y='0' width='1' height='1' fill='white' fill-opacity='.6641'/%3E%3Crect x='0' y='1' width='1' height='1' fill='white' fill-opacity='.7578'/%3E%3Crect x='1' y='1' width='1' height='1' fill='white' fill-opacity='.2578'/%3E%3Crect x='2' y='1' width='1' height='1' fill='white' fill-opacity='.8828'/%3E%3Crect x='3' y='1' width='1' height='1' fill='white' fill-opacity='.3828'/%3E%3Crect x='4' y='1' width='1' height='1' fill='white' fill-opacity='.7891'/%3E%3Crect x='5' y='1' width='1' height='1' fill='white' fill-opacity='.2891'/%3E%3Crect x='6' y='1' width='1' height='1' fill='white' fill-opacity='.9141'/%3E%3Crect x='7' y='1' width='1' height='1' fill='white' fill-opacity='.4141'/%3E%3Crect x='0' y='2' width='1' height='1' fill='white' fill-opacity='.1953'/%3E%3Crect x='1' y='2' width='1' height='1' fill='white' fill-opacity='.6953'/%3E%3Crect x='2' y='2' width='1' height='1' fill='white' fill-opacity='.0703'/%3E%3Crect x='3' y='2' width='1' height='1' fill='white' fill-opacity='.5703'/%3E%3Crect x='4' y='2' width='1' height='1' fill='white' fill-opacity='.2266'/%3E%3Crect x='5' y='2' width='1' height='1' fill='white' fill-opacity='.7266'/%3E%3Crect x='6' y='2' width='1' height='1' fill='white' fill-opacity='.1016'/%3E%3Crect x='7' y='2' width='1' height='1' fill='white' fill-opacity='.6016'/%3E%3Crect x='0' y='3' width='1' height='1' fill='white' fill-opacity='.9453'/%3E%3Crect x='1' y='3' width='1' height='1' fill='white' fill-opacity='.4453'/%3E%3Crect x='2' y='3' width='1' height='1' fill='white' fill-opacity='.8203'/%3E%3Crect x='3' y='3' width='1' height='1' fill='white' fill-opacity='.3203'/%3E%3Crect x='4' y='3' width='1' height='1' fill='white' fill-opacity='.9766'/%3E%3Crect x='5' y='3' width='1' height='1' fill='white' fill-opacity='.4766'/%3E%3Crect x='6' y='3' width='1' height='1' fill='white' fill-opacity='.8516'/%3E%3Crect x='7' y='3' width='1' height='1' fill='white' fill-opacity='.3516'/%3E%3Crect x='0' y='4' width='1' height='1' fill='white' fill-opacity='.0547'/%3E%3Crect x='1' y='4' width='1' height='1' fill='white' fill-opacity='.5547'/%3E%3Crect x='2' y='4' width='1' height='1' fill='white' fill-opacity='.1797'/%3E%3Crect x='3' y='4' width='1' height='1' fill='white' fill-opacity='.6797'/%3E%3Crect x='4' y='4' width='1' height='1' fill='white' fill-opacity='.0234'/%3E%3Crect x='5' y='4' width='1' height='1' fill='white' fill-opacity='.5234'/%3E%3Crect x='6' y='4' width='1' height='1' fill='white' fill-opacity='.1484'/%3E%3Crect x='7' y='4' width='1' height='1' fill='white' fill-opacity='.6484'/%3E%3Crect x='0' y='5' width='1' height='1' fill='white' fill-opacity='.8047'/%3E%3Crect x='1' y='5' width='1' height='1' fill='white' fill-opacity='.3047'/%3E%3Crect x='2' y='5' width='1' height='1' fill='white' fill-opacity='.9297'/%3E%3Crect x='3' y='5' width='1' height='1' fill='white' fill-opacity='.4297'/%3E%3Crect x='4' y='5' width='1' height='1' fill='white' fill-opacity='.7734'/%3E%3Crect x='5' y='5' width='1' height='1' fill='white' fill-opacity='.2734'/%3E%3Crect x='6' y='5' width='1' height='1' fill='white' fill-opacity='.8984'/%3E%3Crect x='7' y='5' width='1' height='1' fill='white' fill-opacity='.3984'/%3E%3Crect x='0' y='6' width='1' height='1' fill='white' fill-opacity='.2422'/%3E%3Crect x='1' y='6' width='1' height='1' fill='white' fill-opacity='.7422'/%3E%3Crect x='2' y='6' width='1' height='1' fill='white' fill-opacity='.1172'/%3E%3Crect x='3' y='6' width='1' height='1' fill='white' fill-opacity='.6172'/%3E%3Crect x='4' y='6' width='1' height='1' fill='white' fill-opacity='.2109'/%3E%3Crect x='5' y='6' width='1' height='1' fill='white' fill-opacity='.7109'/%3E%3Crect x='6' y='6' width='1' height='1' fill='white' fill-opacity='.0859'/%3E%3Crect x='7' y='6' width='1' height='1' fill='white' fill-opacity='.5859'/%3E%3Crect x='0' y='7' width='1' height='1' fill='white' fill-opacity='.9922'/%3E%3Crect x='1' y='7' width='1' height='1' fill='white' fill-opacity='.4922'/%3E%3Crect x='2' y='7' width='1' height='1' fill='white' fill-opacity='.8672'/%3E%3Crect x='3' y='7' width='1' height='1' fill='white' fill-opacity='.3672'/%3E%3Crect x='4' y='7' width='1' height='1' fill='white' fill-opacity='.9609'/%3E%3Crect x='5' y='7' width='1' height='1' fill='white' fill-opacity='.4609'/%3E%3Crect x='6' y='7' width='1' height='1' fill='white' fill-opacity='.8359'/%3E%3Crect x='7' y='7' width='1' height='1' fill='white' fill-opacity='.3359'/%3E%3C/svg%3E");
  background-size: 8px 8px;
  image-rendering: pixelated;
  opacity: .009;
}

.start-glow {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 110vmin;
  height: 110vmin;
  max-width: 1100px;
  max-height: 1100px;
  transform: translate(-50%, -50%);
  pointer-events: none;
}

.start-wordmark {
  position: relative;
  display: block;
  width: auto;
  height: clamp(48px, 10vh, 120px);
}

.start-button {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  min-height: 56px;
  padding: 0 30px 0 26px;
  border: 0;
  border-radius: var(--radius-btn);
  background: var(--brand-red);
  color: var(--ink-on-brand);
  font: 600 18px/1 "Open Sans", var(--font-ui);
  letter-spacing: .01em;
  cursor: pointer;
  transition: background 150ms var(--ease-out);
}
.start-button:hover { background: var(--brand-red-hover); }
.start-button:focus-visible { outline: 3px solid var(--ink-on-brand); outline-offset: 3px; }
.start-button-icon { width: 16px; height: 16px; fill: currentColor; }
/* Sind die Bilder beim Tipp noch nicht da, wartet der Teaser auf sie (teaser.js). */
.start-button.is-waiting { background: var(--brand-red-hover); cursor: progress; }

/* Die Bitte, das Gerät zu drehen. Sie steht an der Stelle des Startknopfs und bleibt im Ton der
   Seite: Strichsymbol wie die Geräte in Szene 3, Text in der Schrift der Website, kein Kasten.
   Der Weg daneben ist absichtlich klein und grau — er soll da sein, nicht locken. */
.turn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  padding: 0 8vw;
  text-align: center;
}
.turn-icon {
  width: clamp(56px, 16vw, 88px);
  height: clamp(56px, 16vw, 88px);
  color: var(--on-graphite-soft);
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.turn-line {
  margin: 0;
  font-size: clamp(22px, 6vw, 30px);
  font-weight: 400;
  letter-spacing: -.01em;
  color: var(--ink-on-brand);
}
.turn-hint {
  margin: -8px 0 0;
  font-size: clamp(14px, 3.8vw, 17px);
  color: var(--on-graphite-muted);
}
.turn-anyway {
  margin-top: 10px;
  padding: 8px 12px;
  border: 0;
  border-radius: var(--radius-btn);
  background: none;
  color: var(--on-graphite-muted);
  font: 400 14px/1 "Open Sans", var(--font-ui);
  text-decoration: underline;
  text-underline-offset: 5px;
  cursor: pointer;
}
.turn-anyway:hover { color: var(--ink-on-brand); }
.turn-anyway:focus-visible { outline: 3px solid var(--ink-on-brand); outline-offset: 3px; }

.legal {
  margin: 0;
  display: flex;
  justify-content: center;
  gap: 24px;
  font-size: 13px;
}
.start .legal {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(20px + env(safe-area-inset-bottom));
}
.legal a { color: var(--on-graphite-muted); text-decoration: none; }
.legal a:hover { color: var(--ink-on-brand); }

@media (orientation: portrait) {
  .start-wordmark { width: min(72vw, 520px); height: auto; }
  .outro-wordmark { width: min(80vw, 600px); height: auto; }

  .scene-lines, .frame, .scene-devices {
    align-items: flex-start;
    padding: 0 9vw;
    text-align: left;
  }
  .line { font-size: 10.2vw; line-height: 1.12; text-wrap: balance; }
  .line + .line { margin-top: .5em; }

  /* Hochkant wird es eng: Vier Bezeichnungen nebeneinander brauchen mehr Platz als vier Symbole,
     deshalb ein kleinerer Abstand und etwas kleinere Symbole. Gemessen passen die vier Paare damit
     in eine Zeile, ohne dass etwas umbricht. */
  .devices { justify-content: flex-start; gap: min(3.4vw, 22px); }
  .device { gap: 8px; }
  .device-icon { width: min(12vw, 82px); height: min(12vw, 82px); }
  .device-name { font-size: max(11px, 2.9vw); }

  .outro-year { font-size: 7.4vw; }
}
