/**
 * Session Teaser Component Styles
 *
 * A clone of teaser-card-content-hub adapted to Session content: a fully
 * clickable card linking to a session, with a full-width image on top.
 * Hover: subtle white overlay on image + image scale + CTA underline.
 * Active: stronger overlay.
 *
 * The format chips sit over the top left corner of the image. Below it the
 * content area runs in a fixed reading order:
 *   speaker names → title → when/where → keywords → description → CTA
 *
 * Differences from teaser-card-content-hub, driven by session needs:
 * - the frame only appears on the white variant. On a solid background a
 *   border does not fit the CI, so ambience and trust zero out
 *   --st-border-width; white keeps it or the card vanishes on a white page
 * - three background variants (white / ambience / trust) instead of two
 * - the label chips carry the session format, and a card without an image
 *   moves them into the content area instead of dropping them
 * - a speaker eyebrow above the title, and a teaser paragraph below the meta
 *   line
 * - a --no-image modifier, because a session whose first speaker has no
 *   portrait must not render an empty framed box
 * - title and teaser are clamped to two lines each, so several cards can sit
 *   in a 33 column grid without one long headline blowing the row open
 *
 * @see components/teaser-card-content-hub/teaser-card-content-hub.css
 */

/* -------------------------------------------------------
 * Component-scoped custom properties
 * ------------------------------------------------------- */
.session-teaser {
  --st-bg-content:     var(--white, #ffffff);
  --st-border:         var(--ambience, #ebe6e1);
  --st-border-width:   var(--border-width-regular, 2px);
  --st-text:           var(--trust, #550a2d);
  --st-muted:          var(--ambience-700, #998c80);
  --st-focus-opacity:  0;
  --st-image-scale:    1;
  --st-title-lines:    2;
  --st-keywords-lines: 1;
  --st-teaser-lines:   2;
}

/* The filled variants carry no frame: a border on top of a solid background
   does not fit the CI. The white variant keeps its border, otherwise the card
   would be invisible against a white page. */
.session-teaser--ambience {
  --st-bg-content:   var(--ambience-300, #efebe7);
  --st-border-width: 0;
  --st-muted:        var(--trust, #550a2d);
}

.session-teaser--trust {
  --st-bg-content:   var(--trust, #550a2d);
  --st-border-width: 0;
  --st-text:         var(--white, #ffffff);
  --st-muted:        var(--ambience-300, #efebe7);
}

/* -------------------------------------------------------
 * Root wrapper — positions the bookmark against the card
 * -------------------------------------------------------
 * The card itself is one big <a>, and a <button> cannot live inside a link.
 * So the root is this wrapper, the <a> is its child and the bookmark is the
 * <a>'s sibling, absolutely positioned over it.
 *
 * display:flex is not cosmetic: the <a> used to be the direct grid/flex item
 * and stretched to the row height on its own. With the wrapper in between,
 * the wrapper stretches instead, and only a flex (or grid) wrapper passes that
 * height on — otherwise cards in a row stop matching heights.
 */
.session-teaser-card {
  position: relative;
  display: flex;
  width: 100%;
}

/* -------------------------------------------------------
 * Card — link wrapper
 * ------------------------------------------------------- */
/* A <div>, not the link — the card's one <a> is the CTA, stretched over the
   whole card (see the actions row below). :hover and :active still fire here
   because the pointer is over the card; keyboard focus lands on the CTA
   instead, so the outline is driven off that. */
.session-teaser {
  display: flex;
  flex-direction: column;
  width: 100%;
  border-radius: var(--border-radius-m, 4px);
  overflow: hidden;
  color: var(--st-text);
  cursor: pointer;
}

/* ── Hover ── */
.session-teaser:hover {
  --st-focus-opacity: 0.15;
  --st-image-scale:   1.05;
}

.session-teaser:hover .session-teaser__cta-label {
  text-decoration: underline;
  text-decoration-skip-ink: none;
}

/* ── Active / pressed ── */
.session-teaser:active {
  --st-focus-opacity: 0.3;
  --st-image-scale:   1.05;
}

/* ── Focus-visible (keyboard navigation) ── */
/* The CTA takes the focus; the card wears the outline, so tabbing to the card
   looks the way it did while the card itself was the <a>. */
.session-teaser:has(.session-teaser__cta:focus-visible) {
  outline: var(--border-width-regular, 2px) solid var(--trust, #550a2d);
  outline-offset: 2px;
  --st-focus-opacity: 0.15;
}

.session-teaser__cta:focus-visible {
  outline: none;
}

/* -------------------------------------------------------
 * Media / Image area
 * ------------------------------------------------------- */
.session-teaser__media {
  position: relative;
  width: 100%;
  aspect-ratio: 420 / 280;
  overflow: hidden;
  border-left:  var(--st-border-width) solid var(--st-border);
  border-right: var(--st-border-width) solid var(--st-border);
  border-top:   var(--st-border-width) solid var(--st-border);
}

.session-teaser__image {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

/* Every wrapper Drupal renders between the container and the img must have a
   definite height so that height: 100% cascades down.
   Targets: figure.image → .image__media → article.media → .field → .field__item → picture */
.session-teaser__image *:not(.contextual, .contextual *) {
  display: block;
  width: 100%;
  height: 100%;
  margin: 0;

  img {
    position: absolute;
    inset: 0;
    object-fit: cover;
    /* Speaker portraits: bias the crop upward so faces survive a 3:2 box. */
    object-position: center top;
    transform: scale(var(--st-image-scale));
    transform-origin: center center;
    transition: transform 0.4s ease;
  }

  .media__credits-overlay {
    display: none;
  }
}

/* White hover overlay */
.session-teaser__focus {
  position: absolute;
  inset: 0;
  background-color: var(--white, #ffffff);
  opacity: var(--st-focus-opacity);
  transition: opacity 0.3s ease;
  pointer-events: none;
}

/* -------------------------------------------------------
 * Format
 *
 * bosch:label chips (secondary, size s), pinned to the top left corner of the
 * image the way teaser-card-content-hub pins its labels. They come after the
 * hover overlay in the markup, so they paint on top of it without a z-index.
 *
 * flex-wrap, so a long format list drops to a second line in a narrow card.
 *
 * Without an image there is no media area to pin to, so the chips render at the
 * top of the content area instead and simply flow with the text group's gap.
 * Their on_background follows the card variant there (beige on white, white on
 * ambience, trust-300 on trust), so they need no backing plate either way.
 * ------------------------------------------------------- */
.session-teaser__format {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-100, 8px);
}

.session-teaser__media .session-teaser__format {
  position: absolute;
  top: var(--spacing-150, 12px);
  left: var(--spacing-150, 12px);
  /* Never let a long format list cover the whole picture. */
  max-width: calc(100% - 2 * var(--spacing-150, 12px));
}

/* A cart in the corner shares that top row, so the chips have to stop before
   it — otherwise a long format list wraps underneath it. The 44px is the
   cart's 36px plus 8px of air; the rest is the inset it already had. */
.session-teaser-card:has(.session-teaser__bookmark) .session-teaser__media .session-teaser__format {
  max-width: calc(100% - 2 * var(--spacing-150, 12px) - 44px);
}

/* Without an image the cart sits over the top right of the content area, where
   the first line (chips, or the speaker eyebrow) would otherwise run under it.
   Only that first line is at risk — the cart is 36px tall and everything below
   clears it. */
.session-teaser-card:has(.session-teaser__bookmark) .session-teaser--no-image .session-teaser__text > *:first-child {
  padding-right: 44px;
}

/* -------------------------------------------------------
 * Content area (below the image)
 * ------------------------------------------------------- */
.session-teaser__content {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-height: 200px;
  padding: var(--spacing-200, 16px) var(--spacing-250, 20px);
  background-color: var(--st-bg-content);
  border-left:   var(--st-border-width) solid var(--st-border);
  border-right:  var(--st-border-width) solid var(--st-border);
  border-bottom: var(--st-border-width) solid var(--st-border);
  border-top:    none;
  border-radius: 0 0 var(--border-radius-m, 4px) var(--border-radius-m, 4px);
}

/* No portrait to show: the content area is the whole card, so it closes the
   frame at the top and takes the radius on all four corners. */
.session-teaser--no-image .session-teaser__content {
  border-top: var(--st-border-width) solid var(--st-border);
  border-radius: var(--border-radius-m, 4px);
}

/* -------------------------------------------------------
 * Text group — one column, gaps carry the rhythm
 * ------------------------------------------------------- */
.session-teaser__text {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-150, 12px);
}

/* -------------------------------------------------------
 * Speakers — eyebrow above the title
 *
 * Names only, inline and comma separated, however many there are. The role is
 * not part of the card any more: on a teaser the names carry the recognition,
 * and the positions pushed the title below the fold in a 33 column.
 * ------------------------------------------------------- */
.session-teaser__speakers {
  display: block;
  /* The eyebrow belongs to the title, so it sits closer to it than the rest of
     the rhythm carried by the text group's gap. */
  margin: 0 0 calc(-1 * var(--spacing-075, 6px));
  padding: 0;
  list-style: none;
  font-weight: var(--font-weight-bold, 700);
  font-size: var(--text-card-s, 15px);
  line-height: 1.4;
  color: var(--st-muted);
}

.session-teaser__speaker {
  display: inline;
}

.session-teaser__speaker:not(:last-child)::after {
  content: ", ";
}

/* -------------------------------------------------------
 * Title
 * ------------------------------------------------------- */
.session-teaser__title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: var(--st-title-lines);
  overflow: hidden;
  margin: 0;
  font-weight: var(--font-weight-bold);
  font-size: var(--text-card-m);
  line-height: 1.3;
  letter-spacing: -0.24px;
  color: var(--st-text);
  text-wrap: pretty;
  font-feature-settings: 'zero';
}

/* -------------------------------------------------------
 * When and where — date · time · room in one line
 *
 * Wraps rather than truncates: a long room name must stay readable, and the
 * line is short enough that two lines are the worst case.
 * ------------------------------------------------------- */
.session-teaser__meta {
  margin: 0;
  font-weight: var(--font-weight-bold, 700);
  font-size: var(--text-card-s, 15px);
  line-height: 1.5;
  color: var(--st-text);
  font-feature-settings: 'zero';
}

/* -------------------------------------------------------
 * Keywords — one line directly below the when/where line
 *
 * Belongs to the meta line rather than to the rhythm of the text group, so a
 * negative margin pulls it up against it, the same trick the speaker eyebrow
 * uses above the title.
 *
 * Clamped to a single line: the keyword list is editor-supplied free text and
 * a long one would otherwise push the teaser and the CTA out of the card.
 * ------------------------------------------------------- */
.session-teaser__keywords {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: var(--st-keywords-lines);
  overflow: hidden;
  margin: calc(-1 * var(--spacing-075, 6px)) 0 0;
  font-size: var(--text-card-xs, 14px);
  line-height: 1.5;
  color: var(--st-muted);
}

/* -------------------------------------------------------
 * Teaser text
 * ------------------------------------------------------- */
.session-teaser__teaser {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: var(--st-teaser-lines);
  overflow: hidden;
  margin: 0;
  font-size: var(--text-card-s, 15px);
  line-height: 1.5;
  color: var(--st-text);
}

/* -------------------------------------------------------
 * Bookmark cart (sibling of the card link, pinned top right)
 * -------------------------------------------------------
 * Sits over the image when there is one and over the top right of the content
 * area when there is not, so it needs a backdrop of its own rather than
 * relying on whatever it happens to land on. The chip is that backdrop.
 */
.session-teaser__bookmark {
  position: absolute;
  top: var(--spacing-150, 12px);
  right: var(--spacing-150, 12px);
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background-color: var(--white, #ffffff);
  box-shadow: 0 1px 4px rgb(0 0 0 / 20%);
}

/* A full session hides its cart button (rba-sessions-bookmark.html.twig), and
   the chip is only a backdrop for that button - left standing it would be an
   empty white disc over the image. */
.session-teaser__bookmark:has(> [hidden]) {
  display: none;
}

/* The button is rba_sessions', shared with the schedule grid and the session
   sidebar — only its size and colour are set here, so the cart matches the
   card rather than the admin table it was first written for. One colour for
   both states; the filled cart is what says "saved". */
.session-teaser__bookmark .rba-sessions-schedule__bookmark {
  --rba-bookmark-icon-size: 20px;

  padding: 0;
  line-height: 1;
  color: var(--trust, #550a2d);
}

/* -------------------------------------------------------
 * Actions row — the card's link, and the cart button beside it
 * -------------------------------------------------------
 * Stacked by default and side by side from 1120px: the landing pages do not
 * use the white space left and right at smaller sizes, so the column runs out
 * of room for two controls on one line well before the usual 1200px step.
 */
.session-teaser__actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--spacing-150, 12px);
  margin-top: var(--spacing-200, 16px);
}

@media (min-width: 1120px) {
  .session-teaser__actions {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-100, 8px);
  }
}

/* -------------------------------------------------------
 * Session link (stretched over the whole card)
 * ------------------------------------------------------- */
.session-teaser__cta {
  display: flex;
  align-items: center;
  gap: var(--spacing-100, 8px);
  padding: var(--spacing-025, 2px);
  border-radius: var(--border-radius-m, 4px);
  text-decoration: none;
  color: inherit;
}

/* The card is clickable everywhere because this one link covers it, which is
   what lets every other control stay a plain sibling instead of being nested
   in an <a>. Anything that takes its own click sits above it. */
.session-teaser__cta::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
}

.session-teaser__cart {
  position: relative;
  z-index: 2;
}

/* Same for the actions row: with the button hidden the wrapper would keep its
   share of the row's gap next to the CTA. */
.session-teaser__cart:has(> [hidden]) {
  display: none;
}

/* The button is rba_sessions', shared with the session sidebar — only its
   type is set here, matched to the CTA it shares the row with, so the two read
   as one pair of actions rather than a link next to a form control. */
.session-teaser__cart .rba-sessions-cart-button {
  padding: var(--spacing-025, 2px);
  border-radius: var(--border-radius-m, 4px);
  font-weight: var(--font-weight-bold, 700);
  font-size: var(--text-card-cta, 16px);
  line-height: 1.1;
  letter-spacing: -0.18px;
  color: var(--st-text);
  font-feature-settings: 'zero';
}

.session-teaser__cart .rba-sessions-cart-button:hover {
  text-decoration: underline;
  text-decoration-skip-ink: none;
}

.session-teaser__cart .rba-sessions-cart-button:focus-visible {
  outline: var(--border-width-regular, 2px) solid var(--trust, #550a2d);
  outline-offset: 2px;
}

.session-teaser__cta-label {
  font-weight: var(--font-weight-bold, 700);
  font-size: var(--text-card-cta, 16px);
  line-height: 1.1;
  letter-spacing: -0.18px;
  color: var(--st-text);
  white-space: nowrap;
  font-feature-settings: 'zero';
  transition: text-decoration 0.2s ease;
}

.session-teaser__cta-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  color: var(--st-text);
}

.session-teaser__cta-icon svg {
  width: 16px;
  height: 16px;
  stroke: currentColor;
  fill: none;
}

/* -------------------------------------------------------
 * Tablet (≥ 768px)
 * ------------------------------------------------------- */
@media (min-width: 768px) {
  .session-teaser__content {
    min-height: 220px;
  }
}

/* -------------------------------------------------------
 * Desktop (≥ 1200px)
 * ------------------------------------------------------- */
@media (min-width: 1200px) {
  .session-teaser__content {
    min-height: 250px;
  }
}

/* -------------------------------------------------------
 * Desktop XL (≥ 1920px)
 * ------------------------------------------------------- */
@media (min-width: 1920px) {
  .session-teaser__content {
    min-height: 280px;
  }
}
