/*
 * Public editorial: the sticky card deck (StackDeck, src/components/common/;
 * the homepage paths, /irankiai tools and /klientams services). Split out of
 * public-editorial-motion.css at the 400-line limit (2026-09-03), together
 * with the runway + recede rules at the end of this file.
 *
 * Cards stack through position: sticky, which only works while no ancestor
 * has overflow: hidden (body uses overflow-x: clip on purpose). Pure
 * transform/opacity, never pointer-driven, switched off under
 * prefers-reduced-motion. No backdrop-filter, no filter: blur(), no
 * will-change. Loaded by PublicLayout for every public route.
 */

/* ---------- Stack deck (sticky stacking cards) ---------- */

/* Tokens fall back to the brand palette so the deck reads the same outside
   .home-editorial (the --home-* variables are scoped to the homepage). */
.stack-deck {
  --stack-deck-ink: var(--home-ink, #15231d);
  --stack-deck-paper: var(--home-white, #fffef9);
  --stack-deck-muted: var(--home-muted, #667068);
  --stack-deck-apple: var(--home-apple, #4cae50);
  --stack-deck-signal: var(--home-signal, #d4473d);
  --stack-deck-blue: var(--home-blue, #5370ff);
  --stack-deck-yellow: var(--home-yellow, #efb936);
  --stack-deck-gap: 1.25rem;
  display: grid;
  /* No grid gap: the runway between two cards carries the gap as its
     margin, so the runway itself never shows as space (see below). */
  gap: 0;
  margin-bottom: clamp(3rem, 6vw, 5rem);
}

.stack-deck__card {
  position: sticky;
  top: calc(6.5rem + var(--i, 0) * 1.1rem);
  display: grid;
  min-height: 17rem;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: 1.5rem clamp(1.5rem, 4vw, 4rem);
  padding: clamp(1.5rem, 3vw, 2.5rem);
  border: 1px solid rgba(21, 35, 29, 0.16);
  border-top: 7px solid var(--deck-color, var(--stack-deck-apple));
  border-radius: 1.25rem;
  background: var(--stack-deck-paper);
  box-shadow: 0 -18px 48px -34px rgba(21, 35, 29, 0.6);
}

.stack-deck__card--course {
  --deck-color: var(--stack-deck-apple);
}

.stack-deck__card--workshop {
  --deck-color: var(--stack-deck-signal);
}

.stack-deck__card--tool {
  --deck-color: var(--stack-deck-blue);
}

.stack-deck__card--consultation {
  --deck-color: var(--stack-deck-yellow);
}

.stack-deck__card h3 {
  margin-top: 0.75rem;
  font-size: clamp(1.9rem, 3.2vw, 3rem);
  font-weight: 760;
  letter-spacing: -0.05em;
  line-height: 0.98;
}

/* Mark and link mirror the homepage .home-mono-label / .home-text-link, whose
   rules live in a homepage-only sheet; the deck is shared, so it carries its
   own copies. */
.stack-deck__mark {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-family: 'Fira Code', monospace;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  line-height: 1.5;
  text-transform: uppercase;
}

.stack-deck__mark svg {
  width: 1rem;
  height: 1rem;
}

.stack-deck__body {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 1.5rem;
}

/* Two class selectors on purpose: the homepage sheet's `.home-editorial p`
   can load after this shared sheet, and equal specificity would let it win. */
.stack-deck__card .stack-deck__body > p {
  max-width: 34rem;
  color: var(--stack-deck-muted);
  font-size: 1rem;
  line-height: 1.65;
}

/* Feature list of a service card (/klientams). */
.stack-deck__list {
  display: grid;
  gap: 0.55rem;
}

.stack-deck__list li {
  display: flex;
  gap: 0.6rem;
  color: var(--stack-deck-ink);
  font-size: 0.86rem;
  line-height: 1.5;
}

.stack-deck__list li svg {
  width: 1rem;
  height: 1rem;
  flex: none;
  margin-top: 0.2rem;
  color: var(--deck-color, var(--stack-deck-apple));
}

/* A card holding keyboard focus rises above the cards stacked over it. */
.stack-deck__card:focus-within {
  z-index: 10;
}

/* Tap target: the text link keeps its look but gets a 44 px hit area. */
.stack-deck__link {
  display: inline-flex;
  min-height: 2.75rem;
  align-items: center;
  gap: 0.5rem;
  width: fit-content;
  padding-block: 0.6rem;
  color: var(--stack-deck-ink);
  font-size: 0.84rem;
  font-weight: 750;
  text-decoration: underline;
  text-decoration-color: var(--stack-deck-apple);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.3rem;
}

.stack-deck__link svg {
  width: 1rem;
  height: 1rem;
  transition: transform 180ms ease;
}

.stack-deck__link:hover svg {
  transform: translateX(3px);
}

.stack-deck__link:focus-visible {
  outline: 3px solid var(--stack-deck-blue);
  outline-offset: 4px;
}

/* Bare deck: the card is only a sticky frame, the child (ToolCard) is the
   visible card, so nothing is drawn twice. */
.stack-deck--bare .stack-deck__card {
  display: block;
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}

.stack-deck__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
  color: var(--stack-deck-ink);
  font-family: 'Fira Code', monospace;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

@media (max-width: 1023px) {
  .stack-deck__card {
    grid-template-columns: 1fr;
    min-height: 15rem;
    top: calc(5.5rem + var(--i, 0) * 0.9rem);
  }
}

@media (max-width: 639px) {
  .stack-deck {
    --stack-deck-gap: 0.9rem;
  }

  .stack-deck__card {
    padding: 1.25rem;
    border-radius: 0.85rem;
  }

  .stack-deck__card h3 {
    font-size: clamp(1.7rem, 9vw, 2.4rem);
  }
}

/* ---------- Runway + recede (2026-09-03) ---------- */

/* An empty runway block follows every card but the last. It is the
   scroll-timeline subject for the recede of the card before it and it carries
   the gap between two cards (1px of its own height + margin = the gap). It is
   deliberately NOT taller: a taller runway would HOLD the pinned card longer,
   but the height is visible page space between the cards while nothing is
   pinned yet (50vh, 22vh and 6vh were all tried; the owner wants no visible
   gap and stacking to start immediately, 2026-09-03). The 1px matters: a
   0-height subject made Chrome jump the animation instead of easing it. It
   must be a sibling, never a wrapper: a sticky card is confined to its parent
   box, so wrapping it would push it out the moment its wrapper ends (verified
   in the browser, the deck stopped stacking). */
.stack-deck__runway {
  height: 1px;
  margin-bottom: calc(var(--stack-deck-gap) - 1px);
}

/* While the next card climbs, the covered one recedes (scale + opacity
   only), driven by scroll position, never by time. The runway after card i is
   the timeline subject (the card itself is sticky, so its own view timeline
   would freeze while pinned); StackDeck names it per index in --deck-timeline
   and lifts the names onto the deck through --deck-timelines, because a named
   timeline is only visible to descendants unless timeline-scope hoists it.
   The runway is ~0 high, so cover percentages are viewport fractions: 45% =
   the next card is ~55% down the viewport (a card seen for the first time is
   never already faded), 88% = it is ~110px from the top, i.e. it has just
   pinned). The @supports guard matters: without scroll-driven animations the
   keyframes would run as a 0 s time animation and freeze every card in its
   receded state. */
@supports (animation-timeline: view()) {
  .stack-deck {
    timeline-scope: var(--deck-timelines);
  }

  .stack-deck__runway {
    view-timeline-name: var(--deck-timeline);
  }

  .stack-deck__card:not(:last-child) {
    transform-origin: 50% 0;
    animation: stack-deck-recede linear both;
    animation-timeline: var(--deck-timeline);
    animation-range: cover 45% cover 88%;
  }

  /* The dimming is a paper veil ON the card, not opacity on the card: a
     translucent card would let the card stacked beneath it bleed through
     (its heading showed inside the next one in the browser). */
  .stack-deck__card:not(:last-child)::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: var(--stack-deck-paper);
    opacity: 0;
    pointer-events: none;
    animation: stack-deck-veil linear both;
    animation-timeline: var(--deck-timeline);
    animation-range: cover 45% cover 88%;
  }

  .stack-deck--bare .stack-deck__card:not(:last-child)::after {
    border-radius: 0.75rem;
  }
}

@keyframes stack-deck-recede {
  to {
    transform: scale(0.92);
  }
}

@keyframes stack-deck-veil {
  to {
    opacity: 0.45;
  }
}

/* ---------- Reduced motion: no stacking, no runway, no recede ---------- */

@media (prefers-reduced-motion: reduce) {
  /* The runway is gone, so the grid gap takes over the card spacing. */
  .stack-deck {
    gap: var(--stack-deck-gap);
  }

  .stack-deck__runway {
    display: none;
  }

  /* The cards simply sit in the flow. */
  .stack-deck__card {
    position: static;
    animation: none;
  }

  .stack-deck__card::after {
    animation: none;
  }

  .stack-deck__link svg {
    transition: none;
  }
}
