/* ==========================================================================
   Design system: home page styles
   Covers:
   - Interface Tour (Figma frame "Interface Tour")
   - Last News carousel
   - Features: Video Mapping, Lighting & DMX, Laser Control
   - Use Cases grid
   - Showcase
   - Learn
   - Home hero
   - CTA Download
   - Stay connected and Newsletter
   Ported from the designer's export. Every selector is prefixed with :where(.ds): same specificity as the export, but no effect outside .ds containers.
   ========================================================================== */

/* --s (camera zoom) is animated along with the transform: handles, label and
   frame thickness follow the zoom instead of jumping at the start of the movement */
@property --s {
  syntax: "<number>";
  inherits: true;
  initial-value: 1;
}

:where(.ds) .interface-tour .section__container {
  gap: var(--spacing-xl);
}
:where(.ds) .interface-tour__player {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-lg);
}
:where(.ds) .interface-tour__title {
  color: var(--content-primary);
  transition:
    opacity var(--duration-base) var(--ease-standard),
    transform var(--duration-slow) var(--ease-standard);
}
:where(.ds) .interface-tour__title.is-swapping {
  opacity: 0;
  transform: translateY(8px);
}

/* ---- Screen: the interface + the highlight frame ---- */
:where(.ds) .interface-tour__screen {
  position: relative;
  aspect-ratio: 3456 / 1476; /* capture ratio: the whole interface is visible (Figma: 1440 × 680) */
  overflow: hidden;
  border: 1px solid var(--border-quaternary);
  border-radius: var(--radius-xl);
  background-color: var(--background-inverse);
}

/* The camera fills the screen; it zooms and moves */
:where(.ds) .tour-camera {
  position: absolute;
  inset: 0;
  transform-origin: 0 0;
  transition:
    transform 1.1s cubic-bezier(0.65, 0, 0.2, 1),
    --s 1.1s cubic-bezier(0.65, 0, 0.2, 1);
}

/* The image keeps its ratio, pinned to the top of the screen */
:where(.ds) .tour-layer {
  position: absolute;
  top: 0; /* vertical offset set by the JS (cropping) */
  left: 0;
  width: 100%;
  aspect-ratio: 3456 / 1476;
}
:where(.ds) .tour-layer img {
  width: 100%;
  height: 100%;
  user-select: none;
  -webkit-user-drag: none;
}

/* Tour Highlight: accent frame, veil over the rest, 4 handles */
:where(.ds) .tour-highlight {
  --tour-outset: calc(3px / var(--s)); /* 3 px around the panel, scaled with the screen */
  position: absolute;
  border: calc(1px / var(--s)) solid var(--border-accent);
  box-shadow: 0 0 0 300vmax var(--black-alpha-70);
  pointer-events: none;
  transition:
    left 1.1s cubic-bezier(0.65, 0, 0.2, 1),
    top 1.1s cubic-bezier(0.65, 0, 0.2, 1),
    width 1.1s cubic-bezier(0.65, 0, 0.2, 1),
    height 1.1s cubic-bezier(0.65, 0, 0.2, 1),
    border-color var(--duration-slow) var(--ease-standard),
    box-shadow var(--duration-slow) var(--ease-standard);
}
:where(.ds) .tour-highlight.is-overview {
  border-color: transparent;
  box-shadow: 0 0 0 300vmax transparent;
}

:where(.ds) .tour-highlight__handle {
  position: absolute;
  width: 18px;
  height: 18px;
  margin: -9px 0 0 -9px;
  border: 1px solid var(--border-accent);
  border-radius: 50%;
  transform: scale(calc(1 / var(--s)));
  transition: opacity var(--duration-slow) var(--ease-standard);
}
:where(.ds) .tour-highlight__handle--tl { left: 0; top: 0; }
:where(.ds) .tour-highlight__handle--tr { left: 100%; top: 0; }
:where(.ds) .tour-highlight__handle--bl { left: 0; top: 100%; }
:where(.ds) .tour-highlight__handle--br { left: 100%; top: 100%; }

:where(.ds) .tour-highlight.is-overview .tour-highlight__handle {
  opacity: 0;
}

/* ---- Rail: 6 steps (Tour Step) ---- */
:where(.ds) .tour-rail {
  display: flex;
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-x: auto;
  scrollbar-width: none;
}
:where(.ds) .tour-rail::-webkit-scrollbar { display: none; }
:where(.ds) .tour-rail > li { flex: 1 0 0; min-width: 0; }

:where(.ds) .tour-step {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--spacing-sm);
  width: 100%;
  padding: var(--spacing-md) 0 var(--spacing-xs);
  border-top: 2px solid var(--border-quaternary);
  color: var(--content-quaternary);
  text-align: left;
  transition: color var(--duration-base) var(--ease-standard);
}
/* Colors per state (Figma Tour Step 9673:32):
   default: everything in quaternary · hover: title tertiary · selected: title primary, text secondary ·
   keyboard focus: title primary, text tertiary, border/focus outline */
:where(.ds) .tour-step:hover { color: var(--content-tertiary); }
:where(.ds) .tour-step[aria-selected="true"],
:where(.ds) .tour-step:focus-visible { color: var(--content-primary); }

:where(.ds) .tour-step:focus-visible {
  outline: 2px solid var(--border-focus);
  outline-offset: 0;
  border-radius: var(--radius-sm);
}

:where(.ds) .tour-step__number {
  display: flex;
  align-items: center;
  gap: var(--spacing-sm);
  font-size: var(--type-label-sm);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-tight);
  color: var(--content-quaternary);
}
:where(.ds) .tour-step__dot {
  flex-shrink: 0;
  width: 0;
  height: 8px;
  margin-right: calc(-1 * var(--spacing-sm)); /* cancels the gap while the dot is hidden */
  border-radius: 50%;
  background-color: var(--background-accent);
  opacity: 0;
  transform: scale(0);
  transition:
    width var(--duration-slow) var(--ease-standard),
    margin var(--duration-slow) var(--ease-standard),
    opacity var(--duration-slow) var(--ease-standard),
    transform var(--duration-slow) var(--ease-standard);
}
:where(.ds) .tour-step[aria-selected="true"] .tour-step__dot {
  width: 8px;
  margin-right: 0;
  opacity: 1;
  transform: scale(1);
}

:where(.ds) .tour-step__text {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-xs);
  width: 100%;
  padding-right: var(--spacing-lg);
  line-height: var(--line-height-tight);
}
:where(.ds) .tour-step__label {
  font-size: var(--type-label-md);
  font-weight: var(--font-weight-bold);
}
:where(.ds) .tour-step__body {
  font-size: var(--type-body-xs); /* Body/XS */
  font-weight: var(--font-weight-regular);
  line-height: var(--line-height-text);
  color: var(--content-quaternary);
  transition: color var(--duration-base) var(--ease-standard);
}
:where(.ds) .tour-step[aria-selected="true"] .tour-step__body { color: var(--content-secondary); }
:where(.ds) .tour-step:focus-visible .tour-step__body { color: var(--content-tertiary); }

/* Progress bar: follows the step timer */
:where(.ds) .tour-step__progress {
  position: absolute;
  left: 0;
  top: -2px;
  width: 0;
  height: 2px;
  background-color: var(--border-accent);
}

/* ---- Tablet and mobile (interpreted) ---- */
@media (max-width: 1023px) {
  :where(.ds) .tour-rail > li { flex: 1 0 220px; }
}

/* Mobile (Figma Home Mobile 11201:8866): 24 px between the heading, the screen and the rail;
   328 × 220 screen (the interface is zoomed in it), 240 px steps */
@media (max-width: 767px) {
  :where(.ds) .interface-tour .section__container,
  :where(.ds) .interface-tour__player { gap: 24px; }
  :where(.ds) .interface-tour__title { min-height: 2.4em; } /* prevents the screen from moving when the title wraps to 1 or 2 lines */
  :where(.ds) .interface-tour__screen {
    aspect-ratio: 328 / 220;
    border-radius: var(--radius-lg);
  }
  :where(.ds) .tour-rail > li { flex-basis: 240px; }
  :where(.ds) .interface-tour [data-tour-play] { display: none; } /* no pause button on mobile (Figma) */
}

@media (prefers-reduced-motion: reduce) {
  :where(.ds) .tour-camera, :where(.ds) .tour-highlight { transition: none; }
}

/* ==========================================================================
   Last News (Figma 11075:3656): Section Tertiary + Section Heading,
   Card / Vertical M carousel (5 columns wide, 2 cards and a half visible on desktop)
   ========================================================================== */
:where(.ds) .last-news__content {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-lg);
}

:where(.ds) ul.news-carousel { /* ul.: takes precedence over ul[role="list"] { padding: 0 } from base.css (own padding) */
  --per-view: 2;
  display: flex;
  gap: var(--grid-gutter);
  /* Inner padding so the card shadow (Shadow/LG on hover) is not clipped
     by the scroll area, offset on the outside to keep the grid alignment */
  --bleed: min(var(--spacing-lg), var(--grid-margin)); /* never more than the page margin */
  padding: var(--spacing-lg) var(--bleed);
  margin: calc(-1 * var(--spacing-lg)) calc(-1 * var(--bleed));
  scroll-padding-inline: var(--bleed);
  /* Shadows stay visible above and below (24 px inner padding). Clean cut at both column edges,
     lifted when nothing but a shadow is past the edge (attributes set by carousel.js):
     on the left when a card sits on the column edge (data-aligned, the previous one is a gutter
     away, out of view), on the right at the end of the scroll (data-at-end, last card) */
  clip-path: inset(0 var(--clip-right, var(--bleed)) 0 var(--clip-left, var(--bleed)));
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
}
:where(.ds) .news-carousel::-webkit-scrollbar { display: none; }
:where(.ds) :is(.news-carousel, .showcase__track)[data-aligned] { --clip-left: 0px; }
:where(.ds) :is(.news-carousel, .showcase__track)[data-at-end] { --clip-right: 0px; }

:where(.ds) .news-carousel__item {
  display: flex;
  flex: 0 0 calc((100% - (var(--per-view) - 1) * var(--grid-gutter)) / var(--per-view));
  min-width: 0;
  scroll-snap-align: start;
}
:where(.ds) .news-carousel .card--vertical {
  max-width: none;
}
@media (min-width: 1024px) {
  :where(.ds) ul.news-carousel {
    --col: calc((100% - 11 * var(--grid-gutter)) / 12); /* 100% = inner width of the list */
  }
  :where(.ds) .news-carousel__item {
    flex-basis: calc(5 * var(--col) + 4 * var(--grid-gutter)); /* grid/span-5: 586 px */
  }
}
/* Text clamped to 3 lines with "..." (Figma: fixed height 376) */
:where(.ds) .news-carousel .card__text {
  display: -webkit-box;
  overflow: hidden;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  min-height: calc(var(--type-body-sm) * var(--line-height-text) * 3); /* else the 4 lines of .card--vertical show past the clamp */
}

:where(.ds) .last-news__controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
:where(.ds) .last-news__controls .dots { justify-content: flex-start; }
:where(.ds) .last-news__arrows {
  display: flex;
  gap: var(--spacing-sm);
}

@media (max-width: 1023px) {
  :where(.ds) ul.news-carousel { --per-view: 1.15; }
}
/* Mobile (Figma Home Mobile 11079:4746): 280 px cards (part of the next one visible),
   dots only below the carousel (no arrows, swipe to scroll) */
@media (max-width: 767px) {
  :where(.ds) .news-carousel__item { flex-basis: 280px; }
  :where(.ds) .last-news__arrows { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  :where(.ds) .news-carousel { scroll-behavior: auto; }
}

/* ==========================================================================
   Feature: Video Mapping (Figma Features › Video Mapping 9770:1617)
   Rounded panel (24 px margin around, ratio 1680 × 780), image as background, veil on the left; text and button at the top, MadMapper panels
   below, Mesh Selection in the Stage (1440 grid).
   #video-mapping anchor: simple trigger (no snapping). When the section fills the screen
   (.is-in), the panels fade in and the image zooms from 100 to 110 %,
   then the mesh is drawn. When leaving it, everything returns to the initial state.
   ========================================================================== */
/* Features section: 24 px around the panels (Figma spacing/lg), 24 px between them */
:where(.ds) .features {
  display: flex;
  flex-direction: column;
  gap: var(--grid-gutter);
  padding: var(--spacing-lg);
  background-color: var(--background-secondary); /* background behind the 3 panels, continuing from Last News */
}

/* Panel: radius/xl rounding, Figma proportions 1680 × 780 from 1440 px;
   below that the ratio would clip the content: the panel takes the content height */
:where(.ds) .feature {
  position: relative;
  display: flex;
  width: 100%;
  max-width: 1680px; /* large screens: Figma width, centered (the image no longer stretches indefinitely) */
  margin-inline: auto;
  overflow: hidden;
  isolation: isolate;
  border-radius: var(--radius-xl);
  color: var(--content-primary);
  scroll-margin-top: var(--spacing-lg); /* link to the anchor: keeps the 24 px margin above */
}

:where(.ds) .feature__background {
  position: absolute;
  inset: 0;
  z-index: -2;
  overflow: hidden;
}
:where(.ds) .feature__image {
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  transition: transform 1.8s cubic-bezier(0.2, 0.7, 0.2, 1);
}
:where(.ds) .feature.is-in .feature__image {
  transform: scale(1.1);
}
/* Image warp onto the projected area: WebGL canvas placed over the mesh (position and size
   provided by feature.js), which redraws the warped photo; edges faded by an ellipse mask */
:where(.ds) .feature__warp {
  position: absolute;
  top: 0;
  left: 0;
  opacity: 0;
  pointer-events: none;
  -webkit-mask-image: radial-gradient(closest-side, #000 72%, transparent);
  mask-image: radial-gradient(closest-side, #000 72%, transparent);
}
:where(.ds) .feature__warp.is-active {
  opacity: 1;
}

/* Vertical veil: 70 % black at the top (behind the text) → transparent at 65 % */
:where(.ds) .feature__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, var(--black-alpha-70) 0%, transparent 65%);
}

:where(.ds) .feature__content {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--spacing-2xl); /* Figma: 48 between the text and the panels */
  padding-block: var(--spacing-3xl); /* 64 at the top and bottom (Figma: 96); sides: .container */
}

/* Panels below the text, MadMapper app layout (outside the columns, as in Figma):
   surface list 308 px, 24 px, Stage on the remaining width */
:where(.ds) .feature__visual {
  display: flex;
  flex: 1;
  gap: var(--spacing-lg);
  min-height: 422px; /* Figma panel height */
}
@media (min-width: 1440px) {
  :where(.ds) .feature { aspect-ratio: 1680 / 780; }
  :where(.ds) .feature__visual { min-height: 0; }
}
:where(.ds) .feature__layers {
  flex: 0 0 308px;
}
:where(.ds) .feature__stage {
  position: relative;
  flex: 1;
  min-width: 0;
}
/* Mesh over the whole Stage view (below the 28 px bar), leaving room for the
   corners (13 px), the move handle above and the rotation handle on the right (20 px + 9 px) */
:where(.ds) .feature__mesh {
  position: absolute;
  top: calc(28px + 40px);
  right: 44px;
  bottom: 24px;
  left: 24px;
  pointer-events: none;
}

/* Text at the top, button right-aligned with the bottom of the text */
:where(.ds) .feature__header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--spacing-lg);
}
/* The text block takes all the space up to the button */
:where(.ds) .feature__text {
  display: flex;
  flex: 1;
  min-width: 0;
  flex-direction: column;
  gap: var(--spacing-md);
}
:where(.ds) .feature__overline {
  color: var(--content-secondary); /* same color for all eyebrows on the page */
}
/* Title + description: 8 px gap (the eyebrow is 16 px above) */
:where(.ds) .feature__heading {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-sm);
}
:where(.ds) .feature__description {
  color: var(--content-secondary);
}
:where(.ds) .feature__header .button {
  flex-shrink: 0;
}

/* ---- Panels appear when arriving on the anchor (fade) ---- */
:where(.ds) .feature.js-reveal [data-reveal] {
  opacity: 0;
  transition: opacity 0.9s var(--ease-standard);
  transition-delay: calc(var(--i, 0) * 200ms);
}
:where(.ds) .feature.js-reveal.is-in [data-reveal] {
  opacity: 1;
}
/* On exit: immediate disappearance, no delay */
:where(.ds) .feature.js-reveal:not(.is-in) [data-reveal] {
  transition-duration: 0.4s;
  transition-delay: 0s;
}

/* Panels with blend modes (.feature__blend: Stage, Input): no opacity on the whole panel (it would isolate the blend modes from the background,
   which would no longer see the photo during the fade and then jump at the end).
   The outline, the bar and each of the two veils fade in separately. */
:where(.ds) .feature.js-reveal .feature__blend .mm-panel {
  border-color: transparent;
  box-shadow: none;
  transition:
    border-color 0.9s var(--ease-standard) 0.2s,
    box-shadow 0.9s var(--ease-standard) 0.2s;
}
:where(.ds) .feature.js-reveal .feature__blend .mm-panel__header,
:where(.ds) .feature.js-reveal .feature__blend .mm-stage__view::before,
:where(.ds) .feature.js-reveal .feature__blend .mm-stage__view::after {
  opacity: 0;
  transition: opacity 0.9s var(--ease-standard) 0.2s;
}
:where(.ds) .feature.js-reveal.is-in .feature__blend .mm-panel { border-color: var(--mm-border); box-shadow: var(--mm-shadow); }
:where(.ds) .feature.js-reveal.is-in .feature__blend .mm-panel__header { opacity: 1; }
:where(.ds) .feature.js-reveal.is-in .feature__blend .mm-stage__view::before { opacity: var(--mm-veil-before, 0.5); }
:where(.ds) .feature.js-reveal.is-in .feature__blend .mm-stage__view::after { opacity: var(--mm-veil-after, 0.5); }
:where(.ds) .feature.js-reveal:not(.is-in) .feature__blend :is(.mm-panel, .mm-panel__header),
:where(.ds) .feature.js-reveal:not(.is-in) .feature__blend .mm-stage__view::before,
:where(.ds) .feature.js-reveal:not(.is-in) .feature__blend .mm-stage__view::after {
  transition-duration: 0.4s;
  transition-delay: 0s;
}

/* ==========================================================================
   Feature: Lighting & DMX (Figma Feature=Right 9769:847)
   Input panel on the left (quad with an animated gradient + its selection),
   "Quad-1" properties panel on the right (308 px).
   ========================================================================== */
/* The properties panel takes the row height without enlarging it (content clipped) */
:where(.ds) .feature__properties {
  position: relative;
  flex: 0 0 308px;
  min-width: 0;
}
:where(.ds) .feature__properties > .mm-panel {
  position: absolute;
  inset: 0;
}

/* Quad centered in the Input view (below the 28 px bar) */
:where(.ds) .feature__quad {
  position: absolute;
  top: calc(28px + (100% - 28px) * 0.345);
  left: 23.5%;
  width: 53%;
  height: calc((100% - 28px) * 0.31);
}
:where(.ds) .feature__quad--selection {
  pointer-events: none;
}
/* "Gradient" media: gray gradient in "screen" over the photo, glare sweeping across the quad */
:where(.ds) .feature__gradient {
  position: absolute;
  inset: 0;
  background-image: linear-gradient(90deg, #1a1a1a 0%, #1a1a1a 17%, #5c5c5c 33.5%, #c4c4c4 50%, #5c5c5c 66.5%, #1a1a1a 83%, #1a1a1a 100%); /* glare slightly tightened at the center */
  background-size: 220% 100%;
  background-position: calc(var(--sweep, 0.5) * 100%) 0; /* driven by feature.js, together with the LEDs */
  mix-blend-mode: screen;
}
/* Photo LEDs: one layer per tube (created by feature.js in a 1600 × 900 frame cropped like
   the image). Only the opacity of each tube changes during the sweep: no repaint, the halo
   (blurred shadow) is drawn once. Light added with "plus-lighter". */
:where(.ds) .feature__leds {
  position: absolute;
  inset: 0;
  overflow: hidden;
  mix-blend-mode: plus-lighter;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1s var(--ease-standard) 0.3s;
}
:where(.ds) .feature.is-in .feature__leds {
  opacity: 1;
}
:where(.ds) .feature__leds-stage {
  position: absolute;
  top: 0;
  left: 0;
  width: 1600px;
  height: 900px;
  transform-origin: 0 0;
}
:where(.ds) .feature__led {
  position: absolute;
  border-radius: 999px;
  background-color: rgb(235 225 255);
  box-shadow: 0 0 18px 8px rgb(170 130 255 / 0.85);
  opacity: 0;
  will-change: opacity;
}

/* Fade-in on arrival, on the gradient itself (it keeps its blend mode during the fade) */
:where(.ds) .feature.js-reveal .feature__gradient {
  opacity: 0;
  transition: opacity 0.9s var(--ease-standard) 0.3s;
}
:where(.ds) .feature.js-reveal.is-in .feature__gradient {
  opacity: 0.7; /* slightly transparent: the photo shows through */
}

/* ---- Tablet: narrower list, button below the text ---- */
@media (max-width: 1023px) {
  :where(.ds) .feature__layers,
  :where(.ds) .feature__properties { flex-basis: 240px; }
  :where(.ds) .feature__header {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* ---- Mobile (Figma Home Mobile 11079:4730, applied to the current panels): 520 px panels,
   24 px inner margin, text, Stage only, then the full-width button at the bottom (16 px apart) ---- */
@media (max-width: 767px) {
  :where(.ds) .feature { height: 520px; }
  :where(.ds) .feature__content {
    gap: var(--spacing-md);
    padding: 24px;
  }
  :where(.ds) .feature__header { display: contents; } /* the button moves below the Stage */
  :where(.ds) .feature__text { flex: none; }
  :where(.ds) .feature__header .button {
    order: 1;
    width: 100%;
  }
  :where(.ds) .feature__visual { min-height: 0; }
  :where(.ds) .feature__layers,
  :where(.ds) .feature__properties { display: none; }
  :where(.ds) .feature__mesh {
    top: calc(28px + 32px);
    right: 36px;
    bottom: 20px;
    left: 20px;
  }
}

@media (prefers-reduced-motion: reduce) {
  :where(.ds) .feature__leds { display: none; }
  :where(.ds) .feature__light { display: none; }
  :where(.ds) .feature__warp { display: none; }
  :where(.ds) .feature.js-reveal [data-reveal],
  :where(.ds) .feature.js-reveal .feature__beam,
  :where(.ds) .feature.js-reveal .feature__blend :is(.mm-panel, .mm-panel__header),
  :where(.ds) .feature.js-reveal .feature__blend .mm-stage__view::before,
  :where(.ds) .feature.js-reveal .feature__blend .mm-stage__view::after,
  :where(.ds) .feature__image { transition: none; }
}

/* ==========================================================================
   Feature: Laser Control (Figma Frame 273, 10243:41379)
   "Media" library on the left (308 px), Input panel on the right: the "ADN" laser
   media rotates as a helix (feature.js) inside its green selection.
   ========================================================================== */
/* Media area, centered in the Stage view (below the 28 px bar), proportions from the draft */
:where(.ds) .feature__laser {
  position: absolute;
  top: calc(28px + (100% - 28px) * 0.155);
  left: 12%;
  width: 76%;
  height: calc((100% - 28px) * 0.69);
  pointer-events: none;
}
/* Laser selection: MadMapper green */
:where(.ds) .mesh-selection--laser {
  --mesh-accent: #33d65c;
  --mesh-knob-icon: #0d3a18;
}
/* Beam: a white line, light added to the photo ("screen") */
:where(.ds) .feature__beam {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  mix-blend-mode: screen;
}
:where(.ds) .feature__beam-line {
  fill: none;
  stroke: #fff;
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
/* Laser photo slightly darkened (the sheet revived by the band stands out better) */
:where(.ds) .feature--laser .feature__background > .feature__image {
  filter: brightness(0.85);
}
/* Photo highlights (laser sheet) revived by a band crossing the image in 5 s,
   following the wave direction. The image stays fixed; only a white gradient band moves
   (translate, no repaint). In the isolated group: black background + band, then the image in "multiply"
   → light only exists inside the band. The group lights up the photo in "screen". */
:where(.ds) .feature__light {
  position: absolute;
  inset: 0;
  overflow: hidden;
  isolation: isolate;
  background-color: #000;
  mix-blend-mode: screen; /* lights up without ever darkening; softer than plus-lighter */
  pointer-events: none;
  opacity: 0;
  transition: opacity 1s var(--ease-standard) 0.3s;
}
:where(.ds) .feature__light-band {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 56%;
  /* Bell curve: the light fades out smoothly, with no visible edge */
  background-image: linear-gradient(90deg, rgb(255 255 255 / 0) 0%, rgb(255 255 255 / 0.02) 12%, rgb(255 255 255 / 0.08) 22%, rgb(255 255 255 / 0.25) 32%, rgb(255 255 255 / 0.55) 40%, rgb(255 255 255 / 0.85) 46%, rgb(255 255 255 / 1) 50%, rgb(255 255 255 / 0.85) 54%, rgb(255 255 255 / 0.55) 60%, rgb(255 255 255 / 0.25) 68%, rgb(255 255 255 / 0.08) 78%, rgb(255 255 255 / 0.02) 88%, rgb(255 255 255 / 0) 100%);
  animation: feature-light-band 5s linear infinite paused;
  will-change: translate;
}
:where(.ds) .feature__light .feature__image {
  position: absolute;
  inset: 0;
  mix-blend-mode: multiply;
}
:where(.ds) .feature.is-in .feature__light-band {
  animation-play-state: running;
}
/* The band goes from -56 % to 100 % of the section width */
@keyframes feature-light-band {
  from { translate: -100% 0; }
  to { translate: 178.5714% 0; }
}
:where(.ds) .feature.is-in .feature__light {
  opacity: 1;
}
:where(.ds) .feature.js-reveal .feature__beam {
  opacity: 0;
  transition: opacity 0.9s var(--ease-standard) 0.2s;
}
:where(.ds) .feature.js-reveal.is-in .feature__beam {
  opacity: 1;
}
:where(.ds) .feature.js-reveal:not(.is-in) .feature__beam {
  transition-duration: 0.4s;
  transition-delay: 0s;
}
@media (max-width: 767px) {
  :where(.ds) .feature__laser {
    top: calc(28px + 32px);
    left: 20px;
    width: calc(100% - 56px);
    height: calc(100% - 28px - 32px - 20px);
  }
}

/* ==========================================================================
   Use Cases (Figma 11075:3573): dark Section, Section Heading,
   grid of Card / Vertical L, 3 per row
   ========================================================================== */
:where(.ds) .use-cases__cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--grid-gutter);
}
:where(.ds) .use-cases__cards .card {
  max-width: none;
  height: 100%;
}
/* No fixed height (480 px in the export, it clips the text on narrow cards):
   the longest text of a row sets the height, 18 px above the card bottom */
:where(.ds) .use-cases__cards .card__body {
  padding-bottom: 18px;
}
:where(.ds) .use-cases__cards .card__text {
  min-height: 0;
}
@media (max-width: 1023px) {
  :where(.ds) .use-cases__cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 767px) {
  :where(.ds) .use-cases__cards { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   Showcase (Figma 9770:1675)
   Secondary background, 96 px top / 64 px bottom. Title + description on the left, Primary MD button
   on the right; 4 cards of 342 px (24 px gap), top-aligned, images of different heights.
   Cards: .card component (Radius/lg, Shadow/MD → LG on hover, image zoom).
   ========================================================================== */
:where(.ds) .showcase .section__content {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-lg);
}

/* Carousel (like Last News, without dots): 4 cards visible on desktop, top-aligned */
:where(.ds) ul.showcase__track { /* ul.: takes precedence over ul[role="list"] { padding: 0 } from base.css (own padding) */
  --per-view: 4;
  --bleed: min(var(--spacing-lg), var(--grid-margin)); /* room for the card shadow */
  display: flex;
  align-items: flex-start;
  gap: var(--grid-gutter);
  padding: var(--spacing-lg) var(--bleed);
  margin: calc(-1 * var(--spacing-lg)) calc(-1 * var(--bleed));
  scroll-padding-inline: var(--bleed);
  clip-path: inset(0 var(--clip-right, var(--bleed)) 0 var(--clip-left, var(--bleed))); /* same cut as Last News */
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
}
:where(.ds) .showcase__track::-webkit-scrollbar { display: none; }
:where(.ds) .showcase__item {
  flex: 0 0 calc((100% - (var(--per-view) - 1) * var(--grid-gutter)) / var(--per-view));
  min-width: 0;
  scroll-snap-align: start;
}
/* Desktop: width in grid columns (12) depending on the image format:
   portrait on 3 columns, square on 4 (--square), landscape on 5 (--landscape) */
@media (min-width: 1024px) {
  :where(.ds) ul.showcase__track {
    --col: calc((100% - 11 * var(--grid-gutter)) / 12); /* 100 % = inner width of the list */
  }
  :where(.ds) .showcase__item {
    flex-basis: calc(3 * var(--col) + 2 * var(--grid-gutter));
  }
  :where(.ds) .showcase__item--square {
    flex-basis: calc(4 * var(--col) + 3 * var(--grid-gutter));
  }
  :where(.ds) .showcase__item--landscape {
    flex-basis: calc(5 * var(--col) + 4 * var(--grid-gutter));
  }
}
:where(.ds) .showcase__arrows {
  display: flex;
  justify-content: flex-end;
  gap: var(--spacing-sm);
}
:where(.ds) .showcase .card--showcase {
  height: 500px;
}
:where(.ds) .showcase .card__title button {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

/* ---- Tablet: 2 cards and a peek of the next ---- */
@media (max-width: 1023px) {
  :where(.ds) ul.showcase__track { --per-view: 2.2; }
  :where(.ds) .showcase .card--showcase { height: 440px; }
}

/* ---- Mobile (Figma Home Mobile 11211:9057): 285 px high cards, 156 px wide in portrait,
   280 px in landscape or square; no arrows; "Explore the gallery" moves below the carousel,
   full-width Primary LG ---- */
@media (max-width: 767px) {
  :where(.ds) .showcase__item { flex-basis: 156px; }
  :where(.ds) .showcase__item--square,
  :where(.ds) .showcase__item--landscape { flex-basis: 280px; }
  :where(.ds) .showcase .card--showcase { height: 285px; }
  /* Title on one line, cut with "..." (on the button that holds the text) */
  :where(.ds) .showcase .card__title button {
    display: block;
    max-width: 100%;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  :where(.ds) .showcase__arrows { display: none; }
  :where(.ds) .showcase .section-heading { display: contents; }
  :where(.ds) .showcase .section-heading__action {
    order: 1;
    width: 100%;
    height: var(--size-xl);
    padding-inline: var(--spacing-lg);
    border-radius: var(--radius-md);
    font-size: var(--type-label-xl);
  }
  :where(.ds) .showcase .section-heading__action .icon {
    width: 24px;
    height: 24px;
  }
}
@media (prefers-reduced-motion: reduce) {
  :where(.ds) .showcase__track { scroll-behavior: auto; }
}

/* ==========================================================================
   Learn (Figma 9770:1710)
   Secondary Section, Section Heading then 3 vertical cards (.card--vertical component)
   sharing the width, 24 px gap.
   ========================================================================== */
:where(.ds) .learn__cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--grid-gutter);
}
:where(.ds) .learn__cards .card {
  max-width: none; /* cards fill their column (464 px in Figma) */
  height: 100%;
}

/* ---- Tablet: 2 columns; mobile (Figma Home Mobile 11079:4755): stacked cards, 16 px apart,
   Card / Vertical L (280 px media, H5 title, Body MD text, never cut) ---- */
@media (max-width: 1023px) {
  :where(.ds) .learn__cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 767px) {
  :where(.ds) .learn__cards {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--spacing-md);
  }
  :where(.ds) .learn__cards .card__media { height: 280px; }
  :where(.ds) .learn__cards .card__title { font-size: var(--type-display-h5); }
  :where(.ds) .learn__cards .card__text { font-size: var(--type-body-md); }
  /* Card / Action text link instead of the ghost button, as in the mockup */
  :where(.ds) .learn__cards .card__actions .button--ghost {
    gap: var(--spacing-xs);
    min-height: 0;
    font-size: var(--type-label-md);
    font-weight: var(--font-weight-bold);
  }
}

/* ==========================================================================
   Home hero (Figma 9770:845, Hero 1335:10220 component)
   Classes .home-hero: the mockup has evolved (pause button, credit over the video) compared to the
   styleguide .hero component (content.css), which remains unchanged.
   Full-frame video (1728 × 900), veil for legibility, content at the bottom aligned with the grid:
   "MadMapper," Display H1 Heavy + "Light is Your Medium." in italic, text shadow, then the
   Get Started button; pause / play Icon Button Overlay Subtle MD on the right.
   Over the video, bottom right: the credit of the displayed shot.
   ========================================================================== */
:where(.ds) .home-hero {
  position: relative;
}
:where(.ds) .home-hero__frame {
  position: relative;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  isolation: isolate;
  aspect-ratio: 1728 / 900;
  min-height: 520px;
  max-height: calc(100svh - 70px); /* below the header (70 px on the site, 72 in the export), the video fits in the screen */
  width: 100%;
  background-color: var(--background-inverse);
  color: var(--content-primary);
}
:where(.ds) .home-hero__video {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Veil: light gradient from bottom to top behind the title */
:where(.ds) .home-hero__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: linear-gradient(0deg, var(--black-alpha-70) 0%, transparent 45%);
}
:where(.ds) .home-hero__content {
  display: flex;
  align-items: flex-end;
  gap: var(--spacing-lg);
  padding-bottom: calc(var(--spacing-section) + var(--spacing-md));
}
:where(.ds) .home-hero__text {
  display: flex;
  flex: 1;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--spacing-md);
  min-width: 0;
}
:where(.ds) .home-hero__title {
  font-size: var(--type-display-h1);
  font-weight: var(--font-weight-regular);
  line-height: var(--line-height-display);
  text-shadow: 0 0 25.5px rgb(0 0 0 / 0.6); /* Shadow/Text */
}
:where(.ds) .home-hero__title strong {
  font-weight: var(--font-weight-heavy);
}
:where(.ds) .home-hero__title em {
  font-style: italic;
}
:where(.ds) .home-hero__controls {
  display: flex;
  flex-shrink: 0;
}

/* Credit over the video, 16 px from the bottom edge, right-aligned on the grid (right edge of the container) */
:where(.ds) .home-hero__credit {
  position: absolute;
  right: calc((100% - min(100%, var(--container-max-width) + 2 * var(--grid-margin))) / 2 + var(--grid-margin));
  bottom: var(--spacing-md);
  color: var(--content-secondary);
  font-size: var(--type-label-sm);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-tight);
  text-shadow: 0 0 12.75px rgb(0 0 0 / 0.6);
  pointer-events: none;
}
:where(.ds) .home-hero__credit [data-credit-name] {
  display: inline-block;
}
:where(.ds) .home-hero__credit [data-credit-name].is-entering {
  animation: home-hero-credit-in 0.3s var(--ease-standard);
}
@keyframes home-hero-credit-in {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: none; }
}

/* Mobile (Figma Home Mobile 11079:4716): 640 px high, full-width Primary LG button, pause button
   top right. Credit under the button, left-aligned with it (the mockup hides it): the content
   goes up to leave room for it (44 px from the bottom instead of 32) */
@media (max-width: 767px) {
  :where(.ds) .home-hero__frame {
    aspect-ratio: auto;
    height: 640px;
    max-height: none;
  }
  :where(.ds) .home-hero__content {
    /* credit (16 px from the bottom, 12 px high) + 16 px gap above it */
    padding-bottom: calc(var(--spacing-md) + var(--type-label-sm) + var(--spacing-md));
  }
  :where(.ds) .home-hero__text .button {
    width: 100%;
    height: var(--size-xl);
    padding-inline: var(--spacing-lg);
    border-radius: var(--radius-md);
    font-size: var(--type-label-xl);
  }
  :where(.ds) .home-hero__text .button .icon {
    width: 24px;
    height: 24px;
  }
  /* The wrapper leaves the row so its gap no longer narrows the button */
  :where(.ds) .home-hero__controls {
    display: contents;
  }
  :where(.ds) .home-hero [data-hero-toggle] {
    position: absolute;
    top: var(--spacing-md);
    right: var(--grid-margin);
  }
  :where(.ds) .home-hero__credit {
    right: var(--grid-margin); /* a long credit wraps inside the margins */
    left: var(--grid-margin);
  }
}

/* ==========================================================================
   CTA Download (Figma 11075:3802): capture 586 px wide (grid/span-5),
   aligned to the right of its column
   ========================================================================== */
:where(.ds) .cta-download .section__column {
  gap: var(--spacing-xl);
}
:where(.ds) .cta-download .section__actions {
  align-items: center;
}
:where(.ds) .cta-download .section__content {
  display: flex;
  justify-content: flex-end;
}
:where(.ds) .cta-download__visual {
  display: block;
  width: 100%;
  max-width: 586px;
  height: auto;
  border: 1px solid var(--border-tertiary);
  border-radius: var(--radius-lg);
  box-shadow: 0 16px 48px var(--shadow-strong);
}
/* Mobile (Figma Home Mobile 11201:8967): heading, capture, then the full-width stacked buttons
   (16 px) and "See pricing" in Link SM; 24 px between the blocks */
@media (max-width: 767px) {
  :where(.ds) .cta-download .section__container { gap: 24px; }
  :where(.ds) .cta-download .section__column { display: contents; }
  :where(.ds) .cta-download .section__actions {
    order: 1;
    flex-direction: column;
    align-items: stretch;
  }
  :where(.ds) .cta-download__pricing {
    align-self: flex-start;
    font-size: var(--type-body-sm);
  }
  :where(.ds) .cta-download__pricing .icon {
    width: 16px;
    height: 16px;
  }
  :where(.ds) .cta-download__visual { max-width: none; }
}

/* ==========================================================================
   Stay connected (Figma 11176:5352) and Newsletter (Figma 11185:5755):
   dark Sections at the end of the page
   ========================================================================== */
:where(.ds) .connect-social__cards {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--grid-gutter);
}
:where(.ds) .connect-social__cards .card {
  height: 100%;
}
:where(.ds) .connect-newsletter {
  padding-top: 0;
}
:where(.ds) .connect-newsletter__form {
  display: flex;
  align-items: flex-end;
  gap: var(--spacing-md);
  max-width: 708px; /* grid/span-6 */
}
:where(.ds) .connect-newsletter__form .field {
  flex: 1;
  min-width: 0;
}
/* Stays not clickable until the email is valid, without the dimmed look */
:where(.ds) .connect-newsletter__form .button:disabled {
  opacity: 1;
}
/* Out of the flow: the error message must not move the button away from the field */
:where(.ds) .connect-newsletter__form .field__helper {
  position: absolute;
  top: 100%;
  margin-top: var(--spacing-sm);
}
@media (max-width: 1023px) {
  :where(.ds) .connect-social__cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 767px) {
  :where(.ds) .connect-social__cards { grid-template-columns: minmax(0, 1fr); }
  :where(.ds) .connect-social__cards .card--social { min-height: 0; } /* content height (Figma Footer mobile 11085:5225) */
  :where(.ds) .connect-newsletter__form {
    flex-direction: column;
    align-items: stretch;
  }
  :where(.ds) .connect-newsletter__form .field__helper {
    position: static;
    margin-top: 0;
  }
}

/* ==========================================================================
   Pricing (Figma 11457:27510): Section Heading (inline) and a full-width visual below,
   radius/lg, ratio of the image (3960 × 1668)
   ========================================================================== */
:where(.ds) .pricing-cta__media {
  overflow: hidden;
  border-radius: var(--radius-lg);
  background-color: var(--background-secondary);
}
:where(.ds) .pricing-cta__media img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3960 / 1668;
  object-fit: cover;
}
