/* =========================================================================
   HOME SECTIONS
   Everything the homepages need beyond main.css: the hero collage, the sticky
   feature canvas, and the feature scroll rail. One file rather than three so
   the browser spends one render-blocking round trip instead of three — the
   requests cost more than the ~13 KiB does.

   Shared by index.html, testlandingpage.html and the six localized homepages.
   The three banners below mark what used to be separate files; keep edits
   inside the right one so the sections stay findable.
   ========================================================================= */

/* ========== 1. HERO COLLAGE ========== */
/* =========================================================================
   HERO IMAGE COLLAGE
   Shared by index.html and testlandingpage.html. Markup lives in each page's
   hero (a .tlp-cover block inside .hero-mockup-column); the slot geometry and
   the rotation live in /js/hero-collage.js. Change --tlp-main-w here and
   SLOTS[0].w there together — they describe the same edge.
   ========================================================================= */

/* ===== HERO COLLAGE =====================================================
   Sits in the hero's right column opposite the copy, where index.html puts its
   mockup. Three different screenshots are on screen at once — one full-size
   card with the next two floating in front of it down the right side — and the
   whole stack rotates on a timer, so every feature comes through the big slot
   in turn. Slides are absolutely positioned into slots the JS assigns (see
   SLOTS in testlandingpage.html), so there's no scroll container to fight. */

/* Measured against the hero column rather than the viewport — nothing here is
   vw-based, because the column already narrows with the page. */
.tlp-cover {
  /* How much of the stage the main card takes. Everything that has to line up
     with its edges — the next arrow, the caption — reads this, and the stage
     ratio below is derived from it. Keep in step with SLOTS[0].w in
     testlandingpage.html. At 100% the main screenshot takes the whole column
     and the two small cards are pushed past its right edge, out of the stage
     entirely — see SLOTS for what that costs. */
  --tlp-main-w: 100%;
  position: relative;
  margin: 0;
  width: 100%;
  max-width: none;
}
.tlp-cover-stage {
  position: relative;
  width: 100%;
  /* The main card is the stage now, so the stage takes the screenshot ratio
     directly. (Their width/height attributes claim 1600x1000, but the real
     files run from 1.46 to 1.74, so 31/20 sits in the middle of that spread.)
     The small cards live outside this box and are not accounted for here —
     nothing on the way out to them clips, so they simply overhang. */
  aspect-ratio: 31 / 20;
}
/* left/top/width/height all come from the JS collage slots — a slide has no
   resting place of its own, only the slot it currently occupies. Sizing by box
   rather than by the image also keeps each card's bottom edge where the layout
   put it, instead of wherever that screenshot's own height happened to land. */
.tlp-cover-slide {
  position: absolute;
  /* Pre-JS state, and the reason it matters: with no geometry of their own all
     seven slides stacked at full size and full opacity, so the browser was free
     to choose any of them as the LCP element. It chose a lazy-loaded one, which
     Lighthouse flags — the worst case. Parking the deck on the first slide's
     footprint and holding the rest back makes LCP deterministic and lands it on
     the slide that actually carries loading="eager" fetchpriority="high".
     Every one of these is overridden inline the moment the script runs. */
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  /* Slots are applied as a transform, never as left/top/width/height. Animating
     those four is a layout change, so every rotation of the collage registered
     as a layout shift — and because .hero-aurora spans the whole hero at
     inset:-20%, it was the largest element in the shifted region and collected
     the blame for all of it. transform is composited and costs no layout. */
  transform-origin: 0 0;
  opacity: 0;
  box-sizing: border-box;
  border-radius: 0.85rem;
  overflow: hidden;
  background: #0d1117;
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 30px 70px rgba(2, 26, 20, 0.45);
  /* Cards travel between slots on every advance, so the box itself animates.
     The ease is a plain decelerate — they arrive and settle rather than
     overshoot, which at three-cards-at-once would read as noise. Keep the
     duration in step with ENTER_DELAY_MS in testlandingpage.html. */
  transition: transform 0.52s cubic-bezier(0.22, 0.61, 0.36, 1),
              opacity 0.42s ease;
  will-change: transform, opacity;
}
/* The one slide that shows before the script runs. Also the graceful no-JS
   state: a single static hero screenshot rather than seven stacked ones. */
.tlp-cover-slide:first-child { opacity: 1; z-index: 40; }

/* The two tucked cards read as further away: a brighter rim so one dark
   screenshot separates from the dark one in front of it, and a tighter shadow
   so the main card keeps the depth. */
.tlp-cover-slide:not(.is-active) {
  border-color: rgba(255, 255, 255, 0.22);
  box-shadow: 0 14px 34px rgba(2, 26, 20, 0.5);
}
/* cover, not contain: the screenshots' real ratios run from 1.46 to 1.74
   against a card fixed at 31/20, so contain left a letterbox strip on most of
   them. Scaling up until the card is filled trades a little off the edges for
   a card that is always full, and object-position keeps the crop off the top
   where the app's toolbar and tabs live. */
.tlp-cover-slide img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}
/* Scrim for the caption and dots that ride on the card's bottom edge — see
   .tlp-cover-caption below for why they sit there rather than under the card. */
.tlp-cover-slide.is-active::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 5.5rem;
  background: linear-gradient(to top, rgba(2, 26, 20, 0.82), rgba(2, 26, 20, 0));
  pointer-events: none;
  z-index: 1;
}
/* The floating cards are clickable — they promote to the main card. Only a
   light tint on them: they're part of the collage rather than a dimmed queue,
   so it just keeps the main screenshot reading as the subject. */
.tlp-cover-slide:not(.is-active) { cursor: pointer; }
.tlp-cover-slide:not(.is-active)::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(3, 42, 32, 0.14);
}

.tlp-cover-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  /* Above the 40 the carousel JS puts on the active slide inline: the controls
     now sit over the card instead of beside it, so losing that race would hide
     them behind the screenshot. Same reason for the caption and dots below. */
  z-index: 50;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(255, 255, 255, 0.92);
  color: #047857;
  border: none;
  cursor: pointer;
  box-shadow: 0 8px 22px rgba(2, 26, 20, 0.28);
  transition: transform 0.2s ease, background 0.2s ease;
}
.tlp-cover-nav:hover { transform: translateY(-50%) scale(1.08); background: #ffffff; }
/* Both arrows ride the main card's own edges — the next one stops at its right
   edge rather than the stage's, so it stays off the small cards instead of
   hovering over the gap between them. */
.tlp-cover-nav.prev  { left: 0.75rem; }
.tlp-cover-nav.next  { left: calc(var(--tlp-main-w) - 3.5rem); }
@media (max-width: 720px) { .tlp-cover-nav { display: none; } }

/* Bottom-left cluster, caption over dots. Both stay inside the main card's 70%
   rather than taking the stage's far corners, where the tucked cards live. */
.tlp-cover-dots {
  position: absolute;
  left: 1.25rem;
  bottom: 1.1rem;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.tlp-cover-dot {
  width: 8px;
  height: 8px;
  padding: 0;
  border: none;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.4);
  cursor: pointer;
  transition: width 0.3s ease, background 0.3s ease;
}
.tlp-cover-dot:hover { background: rgba(255, 255, 255, 0.7); }
.tlp-cover-dot.is-active { width: 26px; background: #ffffff; }

/* Caption and dots ride on the main card instead of sitting under the collage.
   In the right-hand hero column the space below it falls inside
   .hero-section::before's white wedge (main.css), which swallowed both of them
   whole — they're white. On the card's scrim they read at every width. */
.tlp-cover-caption {
  position: absolute;
  left: 1.25rem;
  bottom: 2.75rem;
  z-index: 50;
  margin: 0;
  max-width: calc(var(--tlp-main-w) - 2.5rem);
  text-align: left;
  color: #ffffff;
  font-size: 0.9375rem;
  font-weight: 600;
  min-height: 1.4em;
  text-shadow: 0 1px 8px rgba(2, 26, 20, 0.9);
}

.tlp-cover-nav:focus-visible,
.tlp-cover-dot:focus-visible {
  outline: 2px solid #a7f3d0;
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .tlp-cover-slide { transition: opacity 0.01s linear; }
}

/* .hero-section is display:flex (main.css) and the grid is now its only
   in-flow child — the bg/aurora/waves layers are absolutely positioned, so
   they're out of flow. Pin it to the full row so the 5/7 split has the whole
   width to divide instead of shrinking to its own content. */
#hero.hero-section > .max-w-7xl { flex: 0 0 100%; width: 100%; }

/* Below the lg breakpoint the grid collapses to one column and the carousel
   stacks under the copy, so it needs the gap back. */
@media (max-width: 1023px) {
  .tlp-cover { margin-top: 2.25rem; }
}

/* Single-card mode — the only mode inside a half-width column. Nothing is
   peeking in from the sides, so the shadow comes down. */
.tlp-cover.is-single .tlp-cover-slide { box-shadow: 0 18px 40px rgba(2, 26, 20, 0.4); }

/* ========== 2. STICKY FEATURE CANVAS ========== */
/* =========================================================================
   STICKY FEATURE CANVAS
   Shared by index.html and testlandingpage.html. Every screenshot for the
   scroll-through feature section is stacked in the canvas at once and the
   active one is revealed by class — nothing swaps an <img> src, so a shot that
   is not cached yet cannot flash a gap mid-transition.
   ========================================================================= */

/* Sits inside the .feature-mockup > .mockup-content shell and cross-fades
   between screenshots as each .feature-scroll-item activates. */
.tlp-sticky-canvas {
  position: relative;
  aspect-ratio: 16 / 10;
  width: 100%;
  background: #0d1117;
  overflow: hidden;
}
.tlp-sticky-canvas img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  opacity: 0;
  transform: scale(1.012);
  transition: opacity 0.55s ease, transform 0.55s ease;
}
.tlp-sticky-canvas img.is-active { opacity: 1; transform: scale(1); }
@media (prefers-reduced-motion: reduce) {
  .tlp-sticky-canvas img { transition: opacity 0.01s linear; transform: none; }
}

/* ========== 3. FEATURE SCROLL RAIL ========== */
/* =========================================================================
   FEATURE SCROLL RAIL
   The progress line down the left of the scroll-through feature section,
   JetBrains-style. It behaves like the screenshot on the right rather than
   like the page: it sticks, so it holds still while you scroll, and it is a
   set height level with that screenshot.

   The track is divided into as many steps as there are stages. One step is lit
   at a time and it jumps down a step per stage — 1/5 at the first, 2/5 at the
   second, and so on to the bottom at the last — so the rail reads as position
   within the section, not as raw scroll offset.

   Overrides the fill-from-the-top rail in main.css. That file is shared with
   index_de / index_fr / index_ja / … which do not load this one, so they keep
   the original behaviour — link this plus /js/feature-scroll-rail.js on a page
   to opt it in.
   ========================================================================= */

/* main.css leaves this absolutely positioned down the whole section. It stays
   as the column the sticky track slides along, but stops drawing anything
   itself: the visible track is the sticky child, and overflow has to be let
   out or it would clip the child at the section's top edge and break sticky. */
.scroll-features-container .scroll-features-progress {
  background: none;
  overflow: visible;
}
.scroll-features-container .scroll-features-progress::after {
  content: none;
}

.scroll-features-container .feature-rail-track {
  position: sticky;
  /* Same offset .features-sticky-visual uses, so the rail holds at the same
     height on screen as the screenshot it belongs to. */
  top: max(60px, 50vh - 300px);
  display: block;
  width: 100%;
  /* Set by the JS to the mockup's measured height so the two stay level at any
     width; the fallback only matters if the mockup is missing. */
  height: var(--rail-track-h, 60vh);
  background: rgba(209, 213, 219, 0.45);
  border-radius: 10px;
}

/* The lit step. Height is one stage's share of the track and never changes;
   only its offset moves, which is what makes it read as stepping down. */
.scroll-features-container .feature-rail-track::after {
  content: "";
  position: absolute;
  left: 0;
  width: 100%;
  top: var(--rail-top, 0%);
  height: var(--rail-height, 100%);
  background: linear-gradient(180deg, #059669, #10b981, #34d399);
  box-shadow: 0 0 10px rgba(16, 185, 129, 0.5);
  border-radius: inherit;
  transition: top 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Below the breakpoint the visual stops being sticky (main.css) and the two
   columns stack, so a rail tracking a screenshot that is no longer beside the
   copy has nothing to say. main.css already hides it at 768px; this covers the
   tablet range where the layout has collapsed but the rail had not. */
@media (max-width: 1024px) {
  .scroll-features-container .scroll-features-progress { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .scroll-features-container .feature-rail-track::after { transition: none; }
}
