/**
 * The card row itself. How a row expresses WHICH card is active is
 * css/reveal-modes.css's job; this file is the card.
 *
 * Markup:
 *   <div class="hero-row" data-reveal="spotlight">
 *     <div class="hero-card fragment spotlight" data-glyph="1">
 *       <h3>Title</h3><p>Body</p>
 *     </div>
 *     ...
 *   </div>
 * Each card is a Reveal fragment, so arrow/space steps through them.
 * data-glyph renders above the title in the accent colour - one character, an
 * emoji, or a number.
 */
.reveal .hero-row {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: var(--space-3);
  align-items: stretch;
  margin-top: var(--space-4);
}

.reveal .hero-card {
  position: relative;
  text-align: left;
  padding: var(--space-4) var(--space-3) var(--space-3);
  border: var(--stroke-w) solid var(--stroke);
  border-radius: var(--radius);
  background: var(--surface-glass);
  backdrop-filter: blur(18px);
  transition:
    transform var(--dur-slow) var(--ease),
    flex-grow var(--dur-slow) var(--ease),
    filter var(--dur-slow) var(--ease),
    opacity var(--dur-slow) var(--ease),
    border-color var(--dur-slow) var(--ease),
    box-shadow var(--dur-slow) var(--ease);
}

/* Custom fragment style: overrides Reveal's hide-until-shown default, so
   spotlight cards are all VISIBLE from the start and revealing one changes
   which is lit rather than which exists. Every mode but `deal` reuses this
   class. The dim applies only while a card is not the active one AND only
   under spotlight (or an unattributed row, which defaults to it) - the other
   modes must not inherit a dim they never opted into. */
.reveal .slides section .fragment.spotlight {
  opacity: 1;
  visibility: inherit;
}

.reveal .slides section .hero-row[data-reveal="spotlight"]:not([data-dim="none"]) .fragment.spotlight:not(.is-active),
.reveal .slides section .hero-row[data-reveal="cascade"]:not([data-dim="none"]) .fragment.spotlight:not(.is-active),
.reveal .slides section .hero-row:not([data-reveal]):not([data-dim="none"]) .fragment.spotlight:not(.is-active) {
  filter: blur(3px);
  transform: scale(0.96);
  opacity: 0.4;
}
/* data-dim="none" on a row keeps the step-through (active card grows, cascade
   bar moves) but leaves every other card sharp and fully opaque. */

.reveal .hero-card.is-active {
  filter: none;
  opacity: 1;
  transform: scale(1.06) translateY(-6px);
  border-color: var(--accent-border);
  box-shadow:
    0 0 0 1px var(--accent-ring),
    0 24px 60px -20px var(--accent-cast);
}

/* Hover grows a card independent of which one is active - even a dimmed
   card un-dims and lifts on hover so a mouse-driven audience gets the same
   "look here" affordance a keyboard-driven fragment step gives for free. */
.reveal .slides section .hero-row[data-reveal="spotlight"] .fragment.spotlight:not(.is-active):hover,
.reveal .slides section .hero-row[data-reveal="cascade"] .fragment.spotlight:not(.is-active):hover,
.reveal .slides section .hero-row:not([data-reveal]) .fragment.spotlight:not(.is-active):hover {
  filter: none;
  opacity: 1;
  transform: scale(1.03);
  z-index: 1;
}

.reveal .hero-card.is-active:hover {
  transform: scale(1.1) translateY(-6px);
}

/* A card that is not a fragment is static - no active state to express - so
   hover is its only emphasis. */
.reveal .hero-card:not(.fragment):hover {
  transform: scale(1.04);
  z-index: 1;
}

.reveal .hero-card::before,
.reveal .card-face[data-glyph]::before {
  content: attr(data-glyph);
  display: block;
  font-size: var(--step-2);
  line-height: 1;
  color: var(--accent-key);
  margin-bottom: var(--space-2);
}

.reveal .hero-card h3 {
  font-family: var(--font-mono);
  font-size: var(--step-1);
  margin: 0 0 var(--space-2);
  /* Accent, not --text: a green title is what separates a card's name from
     its body copy at a glance. */
  color: var(--accent-key);
}

/* Body copy in full --text, not --text-muted: on the dimmed glass of a card
   the muted role read as grey-on-grey, and the card title already carries the
   hierarchy through size and the mono face. */
.reveal .hero-card p {
  font-size: var(--step-0);
  color: var(--text);
  margin: 0;
  line-height: 1.5;
  /* A long word ("disappointment,") in a narrow card - four across a process
     row - otherwise runs past the card's edge. */
  hyphens: auto;
  overflow-wrap: break-word;
}

.reveal .hero-card ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--space-1);
}
.reveal .hero-card ul li {
  position: relative;
  font-size: var(--step-0);
  color: var(--text);
  padding-left: var(--space-3);
}
.reveal .hero-card ul li::before {
  content: "-";
  position: absolute;
  left: 0;
  color: var(--accent-key);
}

/* A card opts into the click-to-expand overlay (css/card-detail.css) by
   nesting a .card-detail element. It never renders on the slide itself -
   js/plugins/card-detail.js copies its content into the overlay on click. */
.reveal .hero-card > .card-detail {
  display: none;
}

/* data-connect="arrows": a process row. Cards stay equal width and a
   <span class="hero-arrow" aria-hidden="true">→</span> between each pair
   sits in its own auto-sized slot - flex rather than the row's usual grid,
   because a grid's implicit columns would give the arrows a card's width. */
.reveal .hero-row[data-connect="arrows"] {
  display: flex;
  align-items: stretch;
  gap: var(--space-1);
}
.reveal .hero-row[data-connect="arrows"] > .hero-card {
  flex: 1 1 0;
  min-width: 0;
}
/* Four cards plus three arrows leave each card narrow; a tighter side inset
   is what lets a long word ("disappointment,") fit on one line rather than
   break mid-word (Chromium on Linux ships no hyphenation dictionary). The
   face selector carries an extra class to beat the flip padding in
   css/reveal-modes.css, which loads later. */
.reveal .hero-row[data-connect="arrows"] > .hero-card:not(:has(.card-face)),
.reveal .hero-row[data-connect="arrows"] .hero-card > .card-face {
  padding-inline: var(--space-2);
}
.reveal .hero-row > .hero-arrow {
  flex: none;
  align-self: center;
  font-size: var(--step-2);
  line-height: 1;
  color: var(--accent-key);
}

/* data-align="center": card content centred both ways - glyph, title and
   body stacked in the middle of the card. On a flip row it applies per face,
   since each face is its own absolutely positioned box. */
.reveal .hero-row[data-align="center"] > .hero-card:not(:has(.card-face)),
.reveal .hero-row[data-align="center"] .hero-card > .card-face {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
}

/* data-direction="column": cards stack as full-width strips, one per line,
   for a list of short items (a flip row of strips, or ideas that each open a
   .card-detail). Tighter inset, and no empty glyph slot above a glyph-less
   card. A flip row of strips gets a strip-sized --flip-height: five strips
   and a heading fill the 700px standard box. */
.reveal .hero-row[data-direction="column"] {
  grid-auto-flow: row;
  grid-auto-columns: auto;
  gap: var(--space-2);
  /* 0.125, measured: at 0.115 a three-column back face (idea | truth | new
     story) clipped 5px of a two-line truth in the 960px standard box. */
  --flip-height: calc(var(--slide-h) * 0.125);
}
/* A sixth strip closes the gaps up rather than shrinking every strip: at the
   --space-2 gap six strips ran 25px past the 700px box, and shorter strips
   would clip three-line beats. */
.reveal .hero-row[data-direction="column"]:has(> .hero-card:nth-child(6)) {
  gap: var(--space-1);
}
.reveal .hero-row[data-direction="column"] > .hero-card:not(:has(.card-face)) {
  padding: var(--space-2) var(--space-3);
}
.reveal .hero-row[data-direction="column"] > .hero-card:not([data-glyph])::before {
  content: none;
}
.reveal .hero-row[data-direction="column"] > .hero-card:not(:has(.card-face)) h3 {
  margin: 0;
}

/* data-story="negative": a card holding a negative story is struck through
   once any later card in its row has been revealed - the story is thrown off
   while its words stay readable. */
.reveal .hero-card[data-story="negative"] p {
  transition: color var(--dur-slow) var(--ease);
}
.reveal .hero-card[data-story="negative"]:has(~ .hero-card.visible) p {
  color: var(--text-muted);
  text-decoration: line-through;
  text-decoration-color: var(--accent-key);
  text-decoration-thickness: 2px;
}

/* data-size="large": taller cards and bigger type, for a row that is the
   whole slide. A fraction of --slide-h, never vh (css/tokens.css). Also sets
   the fixed height a flip row needs (css/reveal-modes.css). */
.reveal .hero-row[data-size="large"] {
  /* 0.5, not more: the flow slide stacks a two-line title, this row and a
     lede, and at 0.52 it ran 2px past the 700px standard box. */
  --flip-height: calc(var(--slide-h) * 0.5);
}
.reveal .hero-row[data-size="large"]:not([data-reveal="flip"]) .hero-card {
  min-height: var(--flip-height);
}
.reveal .hero-row[data-size="large"] .hero-card::before,
.reveal .hero-row[data-size="large"] .card-face[data-glyph]::before {
  font-size: var(--step-3);
}
.reveal .hero-row[data-size="large"] .hero-card p {
  font-size: calc(var(--step-0) * 1.15);
}

/* Five cards plus four arrows (the flow slide's Event -> Idea -> Emotion ->
   Story -> Effect) leave each card about 138px. Measured at the four-card
   settings: "disappointment," ran 10px past the Emotion card and the Story
   back ran 18px long at the large size. A tighter inset, smaller arrows and
   body text back at --step-0 fit both. nth-of-type counts only the cards'
   divs, not the arrow spans between them. */
.reveal .hero-row[data-connect="arrows"]:has(> .hero-card:nth-of-type(5)) {
  gap: 2px;
}
.reveal .hero-row[data-connect="arrows"]:has(> .hero-card:nth-of-type(5)) .hero-card > .card-face {
  padding-inline: var(--space-1);
}
.reveal .hero-row[data-connect="arrows"]:has(> .hero-card:nth-of-type(5)) > .hero-arrow {
  font-size: var(--step-1);
}
.reveal .hero-row[data-size="large"][data-connect="arrows"]:has(> .hero-card:nth-of-type(5)) .hero-card p {
  font-size: var(--step-0);
  line-height: 1.4;
}
