/* ==========================================================================
   NUIT NOIRE INTERNATIONAL — base.css
   Reset, Grundtypografie, Atmosphäre (Korn / Halo), Container, Reveal-Utilities.
   Setzt tokens.css voraus.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Reset — modern, minimal
   -------------------------------------------------------------------------- */

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

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  -moz-tab-size: 4;
  tab-size: 4;
  color-scheme: dark;
  scroll-behavior: smooth;
  scroll-padding-top: var(--nni-sp-8);

  /* Der Seitenhintergrund liegt bewusst auf <html>, damit der .nni-halo
     (z-index -1) über der Fläche und unter dem Inhalt liegen kann. */
  background-color: var(--nni-black);
}

body {
  min-height: 100vh;
  min-height: 100svh;
  background-color: transparent;
  color: var(--nni-cream-soft);

  font-family: var(--nni-sans);
  font-weight: 300;
  font-size: var(--nni-fs-base);
  line-height: var(--nni-lh-body);
  letter-spacing: var(--nni-ls-body);
  font-synthesis-weight: none;

  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

img, svg, video, canvas, picture {
  display: block;
  max-width: 100%;
}

img, video { height: auto; }

input, button, textarea, select {
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
}

button { cursor: pointer; }

table {
  border-collapse: collapse;
  width: 100%;
}

hr {
  border: 0;
  height: var(--nni-hair);
  background: var(--nni-line-soft);
}

[hidden] { display: none !important; }

/* Feine Scrollbars, passend zur Schwärze. */
html {
  scrollbar-width: thin;
  scrollbar-color: var(--nni-line) var(--nni-black);
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--nni-black); }
::-webkit-scrollbar-thumb {
  background: var(--nni-line);
  border: 3px solid var(--nni-black);
}
::-webkit-scrollbar-thumb:hover { background: var(--nni-faint); }

/* --------------------------------------------------------------------------
   2. Typografie-Defaults
   -------------------------------------------------------------------------- */

h1, h2, h3, h4, h5, h6 {
  font-family: var(--nni-serif);
  font-weight: 300;
  color: var(--nni-cream);
  letter-spacing: var(--nni-ls-display);
  line-height: var(--nni-lh-tight);
  text-wrap: balance;
}

h1 { font-size: var(--nni-fs-4xl); line-height: var(--nni-lh-display); }
h2 { font-size: var(--nni-fs-3xl); line-height: 1.02; }
h3 { font-size: var(--nni-fs-2xl); }
h4 { font-size: var(--nni-fs-xl); }
h5 { font-size: var(--nni-fs-lg); }
h6 {
  font-family: var(--nni-sans);
  font-size: var(--nni-fs-xs);
  font-weight: 300;
  text-transform: uppercase;
  letter-spacing: var(--nni-ls-fine);
  color: var(--nni-muted);
}

p { text-wrap: pretty; }

strong, b { font-weight: 400; }

em, i { font-style: italic; }

small { font-size: var(--nni-fs-xs); }

a {
  color: var(--nni-cream);
  text-decoration: none;
  text-underline-offset: .3em;
  text-decoration-thickness: var(--nni-hair);
}

/* Fließtext-Links im privaten Bereich tragen eine leise Unterlinie.
   :where() hält die Spezifität bei 0 — jede spätere Regel gewinnt. */
:where(.nni-main) :where(p, li, blockquote, dd) a {
  text-decoration: underline;
  text-decoration-color: var(--nni-line);
  transition: text-decoration-color var(--nni-t-fast) var(--nni-ease-soft),
              color var(--nni-t-fast) var(--nni-ease-soft);
}

ul, ol {
  padding-left: 1.15em;
}

li { margin-block: .35em; }

li::marker {
  color: var(--nni-faint);
  font-size: .8em;
}

nav ul, nav ol {
  list-style: none;
  padding-left: 0;
}

dl, dd { margin: 0; }

blockquote { margin: 0; }

figure { margin: 0; }

::selection {
  background: var(--nni-cream);
  color: var(--nni-black);
}

/* --------------------------------------------------------------------------
   3. Fokus
   -------------------------------------------------------------------------- */

:focus { outline: none; }

:focus-visible {
  outline: var(--nni-hair) solid var(--nni-cream);
  outline-offset: 3px;
}

:focus:not(:focus-visible) { outline: none; }

/* --------------------------------------------------------------------------
   4. Atmosphäre — Korn und Licht
   -------------------------------------------------------------------------- */

.nni-grain {
  position: fixed;
  inset: 0;
  z-index: var(--nni-z-grain);
  pointer-events: none;
  opacity: .035;
  mix-blend-mode: soft-light;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.92' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  background-repeat: repeat;
  background-size: 180px 180px;
}

.nni-halo {
  position: fixed;
  inset: -10%;
  z-index: var(--nni-z-below);
  pointer-events: none;
  background:
    radial-gradient(46% 34% at 50% 16%, rgba(232, 224, 213, .055), rgba(232, 224, 213, .018) 44%, transparent 72%),
    radial-gradient(70% 50% at 50% 108%, rgba(140, 122, 91, .05), transparent 66%);
  animation: nni-breathe 34s var(--nni-ease-soft) infinite alternate;
}

@keyframes nni-breathe {
  from { transform: translate3d(0, 0, 0) scale(1); opacity: .9; }
  to   { transform: translate3d(0, -1.4%, 0) scale(1.06); opacity: 1; }
}

/* --------------------------------------------------------------------------
   5. Skip-Link
   -------------------------------------------------------------------------- */

.nni-skip {
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: var(--nni-z-skip);
  padding: .85rem 1.35rem;
  background: var(--nni-ink);
  border: var(--nni-hair) solid var(--nni-line);
  color: var(--nni-cream);
  font-size: var(--nni-fs-xs);
  text-transform: uppercase;
  letter-spacing: var(--nni-ls-ui);
  text-decoration: none;
  transform: translateY(-180%);
  transition: transform var(--nni-t-fast) var(--nni-ease);
}

.nni-skip:focus { transform: translateY(0); }

/* --------------------------------------------------------------------------
   6. Container
   -------------------------------------------------------------------------- */

.nni-wrap {
  width: 100%;
  max-width: var(--nni-max);
  margin-inline: auto;
  padding-inline: var(--nni-gutter);
}

/* --------------------------------------------------------------------------
   7. Reveal-Utilities
   .nni-rise   — feiner Auftritt innerhalb einer Szene (Gate-Akte)
   .nni-reveal — Scroll-Reveal, JS setzt .is-in
   data-d="1..9" staffelt um je 90ms
   -------------------------------------------------------------------------- */

/* ---------------------------------------------------------------------------
   Einblenden beim Scrollen — AUSDRÜCKLICH als Zugabe, nie als Voraussetzung.

   Vorher stand hier unbedingt opacity: 0. Griff das Skript nicht (Safari,
   blockiertes JavaScript, langsame Verbindung, fehlgeschlagener Beobachter),
   war die ganze Seite unsichtbar — sie sah aus, als fehle sie. Deshalb wird
   jetzt nur verborgen, was das Skript auch wieder einblenden kann: die Klasse
   nni-js setzt site.js als allererste Handlung.
   ------------------------------------------------------------------------ */

.nni-rise,
.nni-reveal {
  opacity: 1;
  transform: none;
}

.nni-js .nni-rise,
.nni-js .nni-reveal {
  opacity: 0;
  transform: translateY(22px);
  transition:
    opacity var(--nni-t-slow) var(--nni-ease),
    transform var(--nni-t-slow) var(--nni-ease);
}

/*
 * KEIN will-change hier — das hat echten Schaden angerichtet.
 *
 * Vorher stand im verborgenen Zustand `will-change: opacity, transform` und
 * im eingeblendeten `will-change: auto`. Der Wert kippt damit genau in dem
 * Augenblick, in dem die Ueberblendung anlaeuft: die Klasse is-in setzt
 * beides zugleich. Chromium legt fuer will-change eine eigene Ebene an und
 * nimmt sie im selben Zug wieder weg — die Ueberblendung startet, meldet
 * sich als "running" und schreibt ihr Ergebnis nie zurueck.
 *
 * Gemessen auf /selection/: alle zehn Karten trugen is-in und standen nach
 * vier Sekunden weiterhin auf Deckkraft 0. Die Seite war leer. Schaltet man
 * die Ueberblendung ab, liefert dieselbe Kaskade sofort 1 — die Regeln waren
 * also nie das Problem, nur der Wechsel von will-change.
 *
 * will-change gehoert ohnehin nicht auf Dutzende Karten gleichzeitig; es ist
 * ein Versprechen an den Browser, keine Beschleunigung.
 */
.nni-rise.is-in,
.nni-reveal.is-in,
.nni-js .nni-rise.is-in,
.nni-js .nni-reveal.is-in {
  opacity: 1;
  transform: none;
}

.nni-rise[data-d="1"],  .nni-reveal[data-d="1"]  { transition-delay: calc(1 * var(--nni-stagger)); }
.nni-rise[data-d="2"],  .nni-reveal[data-d="2"]  { transition-delay: calc(2 * var(--nni-stagger)); }
.nni-rise[data-d="3"],  .nni-reveal[data-d="3"]  { transition-delay: calc(3 * var(--nni-stagger)); }
.nni-rise[data-d="4"],  .nni-reveal[data-d="4"]  { transition-delay: calc(4 * var(--nni-stagger)); }
.nni-rise[data-d="5"],  .nni-reveal[data-d="5"]  { transition-delay: calc(5 * var(--nni-stagger)); }
.nni-rise[data-d="6"],  .nni-reveal[data-d="6"]  { transition-delay: calc(6 * var(--nni-stagger)); }
.nni-rise[data-d="7"],  .nni-reveal[data-d="7"]  { transition-delay: calc(7 * var(--nni-stagger)); }
.nni-rise[data-d="8"],  .nni-reveal[data-d="8"]  { transition-delay: calc(8 * var(--nni-stagger)); }
.nni-rise[data-d="9"],  .nni-reveal[data-d="9"]  { transition-delay: calc(9 * var(--nni-stagger)); }

/* Sicherheitsnetz: ohne JavaScript ist alles sofort sichtbar. */
@media (scripting: none) {
  .nni-rise,
  .nni-reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

.no-js .nni-rise,
.no-js .nni-reveal {
  opacity: 1;
  transform: none;
  transition: none;
}

/* --------------------------------------------------------------------------
   8. Reduzierte Bewegung — neutralisiert alles
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {

  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  .nni-halo { animation: none !important; }

  .nni-rise,
  .nni-reveal,
  .nni-rise.is-in,
  .nni-reveal.is-in {
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ---------------------------------------------------------------------------
   Laufweite — der letzte Boden, damit keine Zeile zu breit läuft
   ------------------------------------------------------------------------

   Die Laufweite wird an vielen Stellen einzeln gesetzt (components.css,
   private.css, profile-page.css). Wo eine Stelle vergessen wurde, lief der
   Text über die ganze Spalte: am Schreibtisch gemessen 137 Zeichen je Zeile
   auf der Concierge-Seite und in der Etappenliste einer Reise — beinahe das
   Doppelte dessen, was ein Auge ohne Verlust zurückverfolgt.

   Diese Regel greift zuletzt und nur nach oben. Sie überschreibt keine
   engere Vorgabe, weil `max-width` bereits eine Obergrenze ist und die
   spezifischeren Regeln in den anderen Dateien gewinnen. Sie fängt nur ab,
   was sonst durchrutscht.

   54ch statt der 48ch aus --nni-max-text: Wer hier landet, hat keine eigene
   Vorgabe. Der etwas weitere Rahmen fällt in keinem Entwurf auf, verhindert
   aber die Katastrophe. */

.nni-prose,
.nni-lede,
.nni-stages__item,
.nni-stages__text,
.nni-psec__body > p,
.nni-main p:not([class]) {
	max-width: min(100%, 54ch);
}

/* Auf dem Telefon ist die Spalte ohnehin schmal; dort darf nichts künstlich
   enger werden, sonst entstehen Flatterränder mit drei Wörtern je Zeile. */
@media (max-width: 47.999em) {
	.nni-prose,
	.nni-lede,
	.nni-stages__item,
	.nni-stages__text,
	.nni-psec__body > p,
	.nni-main p:not([class]) {
		max-width: 100%;
	}
}
