/* Home page only (index.html and its locale copies), loaded after styles.css.
   Own file because styles.css has almost no room left in the asset budget of the Connect pages
   (scripts/check-asset-budget.mjs), while the home page has ample headroom. Same reason as trust.css. */

/* Platform: the headline, then three tiles, one per side (Tobi 19.10.2026: "den Platform-Text nach dem Scrollen
   mittig, der fährt dann zurück, und dann kommen die Kacheln"; Revision 6x: the tiles move with the scroll). Each tile
   is one link to its /platform page: the role photo full bleed on an opaque #0a0a0a carrier (radius 14, no edge), its
   foot fading dark, with the role name, "Platform for brands" and the arrow plate (CORE-748, below). The hover flip to
   an app list was removed on 22.10.2026 (Tobi: "das Umdrehen passt hier nicht mehr"); hover now lifts the card and
   brings the photo a little closer. Tiles are 3:4 and sized so heading and row stay inside one screen with at least
   32px below. Static (below 900px, reduced motion, no JS): the head at chapter size, the row under it (one column
   below 761px). ≥900px with motion (scene.js mountPlatformTiles on pinScrub, 1.44 screens, lerp .14): the section
   pins, the headline draws back, the stack comes in as ONE object (the row is the hull) and the tiles fan out to
   their columns and stand side by side. */
.pf__head { margin-bottom: clamp(32px, 5vh, 56px); text-align: center; }
.pf__h { margin: 0 auto; font-size: clamp(32px, 3vw, 48px); max-width: 24ch; }
.wp-sides { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.wp-side { position: relative; display: block; aspect-ratio: 3 / 4; min-width: 0; border-radius: 14px;
  color: #f1f1f1; text-decoration: none; }
.wp-side:focus-visible { outline: 2.5px solid #fff; outline-offset: 3px; } /* DESIGN.md focus rule */
.wp-side__card { position: absolute; inset: 0; display: block; }
.wp-side__face { position: absolute; inset: 0; display: block; overflow: hidden; border-radius: 14px; background: #0a0a0a; /* opaque: nothing shows through a face */
  isolation: isolate; }
/* the front: the photo */
.wp-side__face--front img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.wp-side--brand .wp-side__face--front img { object-position: 50% 30%; }
.wp-side--showroom .wp-side__face--front img { object-position: 50% 70%; }
.wp-side--retailer .wp-side__face--front img { object-position: 50% 45%; }
.wp-side__face--front::after { content: ""; position: absolute; inset: 0; pointer-events: none; /* the foot fades into the night ground */
  background: linear-gradient(to bottom, rgba(10,10,10,0) 50%, rgba(10,10,10,.55) 74%, rgba(10,10,10,.92) 100%); }
.wp-side__foot { position: absolute; inset: auto 0 0 0; z-index: 1; display: flex; align-items: center; gap: 12px; padding: 0 20px 18px; }
.wp-side__foot .wp-side__role { font-size: clamp(22px, 1.9vw, 30px); letter-spacing: -0.02em; }
.wp-side__foot .wp-side__go { font-size: 13px; }
/* the back: a head row and the list */
.wp-side__names { display: grid; gap: 3px; min-width: 0; }
.wp-side__role { font-size: 17px; font-weight: 600; letter-spacing: -0.015em; line-height: 1.1; color: #f1f1f1; }
.wp-side__go { font-size: 12px; font-weight: 500; line-height: 1.35; color: rgba(241,241,241,.6); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 760px) {
  .wp-sides { grid-template-columns: minmax(0, 1fr); max-width: 500px; }
}
.pf.is-pinned { height: var(--pin-h, auto); padding: 0; }
.pf.is-pinned .pf__sticky { position: sticky; top: 0; height: 100vh; height: 100svh; overflow: hidden; }
.pf.is-pinned .pf__head { position: absolute; left: 0; right: 0; top: 50%; margin: 0 auto; transform: translate3d(0, -50%, 0); }
.pf.is-pinned .pf__h { font-size: clamp(44px, 5.2vw, 76px); max-width: 18ch; transform-origin: 50% 0; will-change: transform;
  opacity: min(var(--pi, 1), var(--sg, 1)); /* --pi: hand-off from the statement, at 80-94 % of its pin, out of opacity 0, +32px and 8px blur (the mirror of the sentence leaving); --sg (scene.js mountStatement): never sharper than the sentence is gone */
  filter: blur(calc((1 - min(var(--pi, 1), var(--sg, 1))) * 8px));
  transform: translate3d(0, calc(var(--k, 0) * var(--pf-y, 0px) + (1 - var(--pi, 1)) * 32px), 0) scale(calc(1 - var(--k, 0) * (1 - var(--pf-s, 1)))); }
.pf.is-pinned .wp-sides { position: absolute; left: 0; right: 0; top: var(--pf-top, 240px); width: var(--pf-w, 1080px); max-width: none; margin: 0 auto; padding: 0; }
.pf.is-pinned .wp-side { will-change: transform, opacity; } /* each tile glides in from the right on its own (22.10.2026, no stack) */
/* 21.10.2026, QA: on tablet widths the long French role line ("Plateforme pour les showrooms") lost its last letter */
@media (max-width: 1100px) { .wp-side__go { white-space: normal; } }


/* 21.10.2026 (CORE-748, Tobi: "auch bei großen Bildschirmen immer zweizeilig"): the hero entrance rule in styles.css sets the lines
   inline-block and beat the ≥1024px block rule, so from ~1800px both lines stood in ONE row. Here each line is its
   own block again (all languages, the lowered DE box included) and never breaks inside. */
@media (min-width: 1024px) {
  .hero--converge .hero__title, :lang(de) .hero--converge .hero__title { max-width: none; }
  .js-loaded .hero--converge .hero__title .hero__line, .hero--converge .hero__title .hero__line { display: block; white-space: nowrap; }
  /* the French first line is the longest (≈15.3em): 5.7vw keeps it inside the 24px gutters from 1024px on */
  :lang(fr) .hero--converge .hero__title { font-size: min(clamp(52px, 6.4vw, 102px), 5.7vw); }
}

/* The tiles read as links (CORE-748, Tobi 21.10.2026: "nicht ganz verständlich, dass man auf die drei Karten klicken
   kann … mit Pfeil und Animation, leichter Float, perfekt, am Rand nichts durchschimmern, ein wenig Schatten").
   - Arrow: since 22.10.2026 a small text arrow after "Platform for …" (Tobi: the round plates did not fit), sliding 4px on hover. Earlier: a round plate, two arrow
     layers in its background: on hover/focus the plate fills light, the light arrow leaves to the right and the dark
     one comes in from the left (background-position only, no layout). At rest the front arrow nudges out and back
     once every 4.2s, the three tiles staggered.
   - Float: each tile drifts 6px on the `translate` property (6s, staggered), which composes with the inline
     `transform` scene.js writes on .wp-side, so the pinned fan-out is untouched. Hover/focus lifts the card 6px and
     deepens its ground shadow (on .wp-side__card).
   - Edges: the photo overdraws the face by 1px so no plate hairline shows when the tile is scaled.
   Reduced motion: no float, no nudge, no lift; the plate still fills on hover. */
.wp-side__face--front img { inset: -1px; width: calc(100% + 2px); height: calc(100% + 2px); transition: transform .7s var(--ease); }
@media (hover: hover) and (prefers-reduced-motion: no-preference) { :root:not(.is-scrolling) .wp-side:hover .wp-side__face--front img { transform: scale(1.04); } } /* no flip any more (Tobi 22.10.2026): hover lifts the card and brings the photo a little closer */
.wp-side__card { border-radius: 14px;
  box-shadow: 0 1px 2px rgba(16,16,16,.06), 0 16px 34px -16px rgba(16,16,16,.32);
  transition: box-shadow .45s var(--ease), translate .45s var(--ease); }
.wp-side__foot .wp-side__go { overflow: visible; color: rgba(241,241,241,.82); }
.wp-side__foot .wp-side__go::after { content: ""; display: inline-block; width: 13px; height: 13px; margin-left: 6px; vertical-align: -2px;
  background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3Cpath d='m13 6 6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3Cpath d='m13 6 6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform .25s var(--ease); }
@media (hover: hover) { :root:not(.is-scrolling) .wp-side:hover .wp-side__go::after { transform: translateX(4px); } }
.wp-side:focus-visible .wp-side__go::after { transform: translateX(4px); }
@keyframes wp-float { 0%, 100% { translate: 0 0; } 50% { translate: 0 -6px; } }
/* the float only with a mouse or touchpad (Tobi 22.10.2026: "auf Mobil den Float weglassen, das wäre zu viel") */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .wp-side { animation: wp-float 6s ease-in-out infinite; }
  .wp-side--showroom { animation-delay: -2s; }
  .wp-side--retailer { animation-delay: -4s; }
}
@media (prefers-reduced-motion: no-preference) {
  .wp-side:focus-visible .wp-side__card { translate: 0 -6px; }
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) { :root:not(.is-scrolling) .wp-side:hover .wp-side__card { translate: 0 -6px; } }
.wp-side:focus-visible .wp-side__card { box-shadow: 0 2px 4px rgba(16,16,16,.06), 0 30px 56px -22px rgba(16,16,16,.40); }
@media (hover: hover) { :root:not(.is-scrolling) .wp-side:hover .wp-side__card { box-shadow: 0 2px 4px rgba(16,16,16,.06), 0 30px 56px -22px rgba(16,16,16,.40); } }

/* Hero sub-line (CORE-748, Tobi 21.10.2026: "liest sich noch etwas schwer … muss wirklich perfekt sein"): two short
   lines broken by hand at the sentence edge, a step larger and brighter than the 17px / .62 of
   styles.css so it holds against the film and the 102px title, regular weight. Each sentence is its own
   block (.hero__sub-s, not a <br>: Chrome balances only the first run after a forced break), so on phones, in a
   narrow box, each sentence balances on its own into two even lines (Tobi: three uneven lines looked off). */
.hero__sub-s { display: block; text-wrap: balance; }
.hero--converge .hero__sub { max-width: none; font-size: clamp(17px, 1.3vw, 20px); font-weight: 400; line-height: 1.5;
  letter-spacing: -0.005em; color: rgba(241,241,241,.8); }
@media (max-width: 600px) {
  .hero--converge .hero__sub { max-width: 17em; font-size: 16px; } /* each sentence balances into even lines (two each; a short one, as in ES, stays one) */
}

/* The full stop after the key line blinks like a text cursor (CORE-748, Tobi 21.10.2026: "der Punkt hinter works
   together … blinkt, wie wenn man das auf der Tastatur hat"). It is generated, not in the copy: app.js rebuilds the
   lines from their text for the word entrance, so a span around the dot would not survive. With the split it hangs
   on the last word's inner box (rises with it, never wraps alone onto a phone line); without JS or under reduced
   motion (no split) it sits after the line and stays still. Blink: calm (Tobi: "zu schnell, ruhig, dezent"), a soft fade to .15 and back on a 2.4s beat, from 1.3s on. */
.hero--converge .hero__title:not(.has-words) .hero__line--key::after,
.hero--converge .hero__title.has-words .hero__line--key .hero__w:last-child .hero__wi::after { content: "."; }
@keyframes hero-dot-blink { 0%, 40% { opacity: 1; } 55%, 85% { opacity: .15; } 100% { opacity: 1; } }
@media (prefers-reduced-motion: no-preference) {
  .hero--converge .hero__title.has-words .hero__line--key .hero__w:last-child .hero__wi::after {
    animation: hero-dot-blink 2.4s ease-in-out 1.3s infinite; }
}

/* Hero film rim (CORE-748, Tobi 21.10.2026: "beim Scroll kommt an den Rändern so ein weißer Pixelstreifen"): while
   scrolling the film blurs up to 12px (phones 8px), but its scale(1.04) left only ~10px of overscan on a phone, so
   the blur pulled transparent samples in at the edges and a light rim showed. The film now overhangs 48px on every
   side (more than 3x the largest blur); .hero__bg's overflow clips it. */
.hero__bg-vid { position: absolute; left: -48px; top: -48px; width: calc(100% + 96px); height: calc(100% + 96px); }

/* The Platform headline carries the Core lockup (Tobi 22.10.2026: "das Core-Logo, dann connects all three sides, damit
   die Story besser passt"): the lockup sits on its own line above the sentence and scales with the h2, so it draws back
   with it under the bar. Mark full ink, word in the muted grey (DESIGN.md lockup rule). */
/* Same lockup as the mega menu on light (Tobi 22.10.2026: "die müssen immer gleich sein mit dem rest"): word in ink at
   .62, mark full ink, mark height = 1.067 × word, 700. Scaled to ~0.8 of the sentence (Tobi: "das Logo ist etwas klein") and set apart by half a line. */
.pf__lockup { display: flex; justify-content: center; align-items: center; gap: .2em; margin: 0 auto 1em; --lockup-word: .78em; color: rgba(13, 13, 13, .62); }
.pf__lockup .studio-badge__mark { height: 1.067em; filter: brightness(0); }
.pf__line { display: grid; }
.pf__line > * { grid-area: 1 / 1; }
/* The typed line (scene.js mountPlatformTiles, Tobi 22.10.2026): the typed part grows from the centre over a hidden
   copy of the whole line, which keeps its size (no shift); the caret blinks while typing and fades once the line stands. */
.pf__rest { visibility: hidden; }
.pf__caret { display: inline-block; width: 2px; height: .82em; margin: 0 -2px 0 0; vertical-align: -.06em; background: currentColor;
  animation: pf-caret 1s steps(1) infinite; transition: opacity .5s var(--ease) .6s; }
.pf__line.is-typed .pf__caret { animation: none; opacity: 0; }
@keyframes pf-caret { 50% { opacity: 0; } }


/* Studio chapter, phone strip (CORE-748, 22.10.2026, Tobi: "die Studio-Mockups perfekt und in den Space passen"):
   below 900px the newsletter stage set its three mails side by side at about 105px each (too small to read) and
   stood 70-150px shorter than the website stages, an empty band under it. Now the mails fan like the pinned track
   (middle one on top and set 12% lower so the outer mastheads stay readable, the outer two turned ±2°), each 40% of
   the stage with 10% overlap, centred in the stage's height; only the overlapping ones carry the ground shadow.
   Studio rules: styles.css "Studio:". */
@media (max-width: 899px) {
  .sx:not(.is-pinned) .sx__stage--mail { align-items: center; }
  .sx:not(.is-pinned) .sx__stage--mail .sx__comp { justify-content: center; align-items: center; gap: 0; }
  .sx:not(.is-pinned) .sx__stage--mail .sx__mock { flex: none; width: 40%; }
  .sx:not(.is-pinned) .sx__stage--mail .sx__mock--m1 { rotate: -2deg; }
  .sx:not(.is-pinned) .sx__stage--mail .sx__mock--m2 { z-index: 2; margin: 12% -10% 0; }
  .sx:not(.is-pinned) .sx__stage--mail .sx__mock--m3 { rotate: 2deg; }
  .sx:not(.is-pinned) .sx__stage--mail :is(.sx__mock--m2, .sx__mock--m3) .st-mock__img { box-shadow: 0 24px 48px -24px rgba(0,0,0,.85); }
}

/* Statement → Platform on phones and tablets (Tobi 22.10.2026: ~390px of empty grey before "Core connects"): the
   statement stays one full screen (it is the curtain over the sticky hero), but its sentence sits at the bottom of it,
   so the gap to the Core headline is 32px plus the Platform section's own top padding. The desktop pin is untouched. */
@media (max-width: 1000px) {
  .home-statement:not(.is-scrub) .home-statement__pin { align-items: flex-end; padding-bottom: 32px; }
}

/* Founders story (Tobi, 22.10.2026: "wirkt noch etwas out of place, ggf. eine leichte Kachel dahinter"): one quiet
   plate like .cn-intro, a small ∞ on top instead of the large dim loop mark, and a text link to About. Home only;
   the markup sits outside footer:shared, so the other pages never had it. */
.footer__founders { max-width: 680px; margin: 8px auto 56px; padding: clamp(32px, 5vw, 56px) clamp(22px, 5vw, 64px);
  border-radius: 20px; background: rgba(241,241,241,.05); text-align: center; }
.footer__founders-mark { display: block; width: 46px; height: auto; margin: 0 auto 24px; fill: rgba(241,241,241,.3); }
.footer__founders-quote { margin: 0 auto 14px; max-width: 26ch; font-size: clamp(19px, 2.1vw, 24px); font-weight: 600; letter-spacing: -0.015em;
  line-height: 1.3; color: var(--ink); text-wrap: balance; }
.footer__founders-text { margin: 0 auto; max-width: 54ch; font-size: 15px; line-height: 1.65; color: var(--muted); text-wrap: pretty; }
.footer__founders-link { display: inline-block; margin-top: 22px; font-size: 14px; font-weight: 600; color: var(--ink);
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; }
