/* ==========================================================================
   Cockpits · shared alternating showcase
   ==========================================================================
   Reusable visual grammar for Cockpits sections that pair editorial copy
   with a product screenshot. The section owns its content; this component
   owns the rail, alternating grid, colour tones, responsive order and media
   treatment.

   Public modifiers:
   - .cockpit-showcase__story--reverse
   - .cockpit-showcase__story--tone-violet
   - .cockpit-showcase__story--tone-indigo
   - .cockpit-showcase__story--tone-blue
   - .cockpit-showcase__story--tone-teal
   - .cockpit-showcase__story--tone-mint

   The five tones are the rail read at five heights, so a track picks the ones
   that land where its own stories do: violet/blue/mint for three rows,
   indigo/teal for two, all five for five. Pick any other order and the node
   stops matching the line it sits on.

   Section-level custom properties are intentionally the only extension API:
   --cockpit-showcase-head-max
   --cockpit-showcase-lede-max
   --cockpit-showcase-copy-max
   --cockpit-showcase-container-max
   --cockpit-showcase-page-gutter
   --cockpit-showcase-name-size
   --cockpit-showcase-name-size-mobile
   --cockpit-showcase-title-size
   --cockpit-showcase-title-size-mobile
   ========================================================================== */

.cockpit-showcase {
  --cockpit-showcase-rail-x: 0.55rem;
  --cockpit-showcase-head-max: 52rem;
  --cockpit-showcase-lede-max: 52rem;
  --cockpit-showcase-name-size: clamp(3.4rem, 6.4vw, 6.2rem);
  --cockpit-showcase-name-size-mobile: clamp(2.7rem, 12.5vw, 3.9rem);
  --cockpit-showcase-copy-max: 535px;
  /* These renders are whole dashboards, not one card: every extra pixel of
     width buys back a readable label. The container, the gap and the column
     ratio were widened together until the media box reaches ~886px on a wide
     desktop — the point where the copy column still holds ~46 characters per
     line. Any further move here MUST be mirrored in the `sizes` attribute of
     every showcase fragment (locked by cockpit-showcase-architecture.test.js). */
  --cockpit-showcase-container-max: 1420px;
  --cockpit-showcase-page-gutter: clamp(1.25rem, 3vw, 2.5rem);
  --cockpit-showcase-title-size: var(--feat-title-deck-size);
  --cockpit-showcase-title-size-mobile: var(--feat-title-story-size-mobile);
}

/* --- Section head: the panel's title plate ---------------------------------
   A story title is a sentence with one word painted. A cockpit head is a
   plate, and it is built the other way round on purpose: the word every
   cockpit shares is engraved small in the utility face, and the one word that
   tells them apart is the whole headline. Above it, the track's own rail read
   horizontally — one node per view, in the exact tones the vertical rail takes
   further down — so the head announces how many views are coming, and in which
   colours, before the reader scrolls into them.
   -------------------------------------------------------------------------- */

.cockpit-showcase__head {
  max-width: var(--cockpit-showcase-head-max);
  margin-inline: auto;
  margin-bottom: clamp(4.5rem, 8vw, 7rem);
  text-align: center;
}

.cockpit-showcase__index {
  position: relative;
  display: flex;
  gap: clamp(1rem, 2vw, 1.45rem);
  align-items: center;
  justify-content: center;
  width: max-content;
  margin: 0 auto clamp(1.5rem, 2.8vw, 2.1rem);
}

/* The rail, read across. Same three readings as the vertical one, and it
   overhangs the outer nodes so the line looks cut out of a longer one. */
.cockpit-showcase__index::before {
  position: absolute;
  top: 50%;
  right: -1.75rem;
  left: -1.75rem;
  height: 1px;
  background: linear-gradient(
    to right,
    transparent,
    rgba(var(--feat-violet-rgb), 0.6) 18%,
    rgba(90, 116, 255, 0.44) 50%,
    rgba(var(--feat-mint-rgb), 0.55) 82%,
    transparent
  );
  content: '';
}

.cockpit-showcase__index-node {
  position: relative;
  flex: none;
  width: 9px;
  height: 9px;
  border: 2px solid var(--feat-bg);
  border-radius: 50%;
  background: rgb(var(--cockpit-showcase-node-rgb));
  box-shadow:
    0 0 0 1px rgba(var(--cockpit-showcase-node-rgb), 0.5),
    0 0 14px rgba(var(--cockpit-showcase-node-rgb), 0.55);
}

.cockpit-showcase__heading {
  margin: 0;
}

.cockpit-showcase__kicker {
  display: block;
  /* Letter-spacing hangs a trailing gap off the last glyph, which pulls a
     centred line left by half of it. Give it back. */
  padding-left: 0.4em;
  margin-bottom: clamp(0.8rem, 1.5vw, 1.15rem);
  color: var(--feat-muted);
  font-family: var(--feat-mono);
  font-size: clamp(0.7rem, 0.9vw, 0.79rem);
  font-weight: 600;
  letter-spacing: 0.4em;
  line-height: 1;
  text-transform: uppercase;
}

/* inline-block, not block: the gradient is painted across the element box, so
   a full-width box would sample only its middle and the word would come out
   one flat blue instead of the rail's full sweep.

   That same box is what the glyphs are painted through, and a box cut to a
   0.95 line-height sits above the descenders — the g of "Pilotage" loses its
   tail. The padding gives the paint room on all four sides and the negative
   margins hand the space back to the layout. */
.cockpit-showcase__name {
  display: inline-block;
  padding-block: 0.14em 0.2em;
  padding-inline: 0.08em;
  margin-block: -0.14em -0.2em;
  margin-inline: -0.08em;
  color: transparent;
  background: var(--brand-title-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  font-size: var(--cockpit-showcase-name-size);
  font-weight: 820;
  letter-spacing: -0.05em;
  line-height: 1;
}

/* The family justifies body copy against a left edge. This lede has no left
   edge to hold — it hangs under a centred plate. It gets a wider measure than
   the head it sits in: these ledes carry a full sentence plus the note that
   everything is computed from the calls, and on the head's own width they
   broke into too many short lines. */
.cockpit-showcase .cockpit-showcase__lede {
  max-width: var(--cockpit-showcase-lede-max);
  margin-inline: auto;
  margin-top: clamp(1.4rem, 2.4vw, 1.9rem);
  text-align: center;
  hyphens: manual;
}

/* Forced colours drop the gradient, and the glyphs are transparent without
   it — same fallback the shared .feat-highlight gets. */
@media (forced-colors: active) {
  .cockpit-showcase__name {
    color: CanvasText;
    background: none;
  }
}

.cockpit-showcase__track {
  position: relative;
  display: grid;
  gap: clamp(6rem, 11vw, 10.5rem);
  padding-left: 2.4rem;
}

.cockpit-showcase__track::before {
  position: absolute;
  top: 1.6rem;
  bottom: 1.6rem;
  left: var(--cockpit-showcase-rail-x);
  width: 1px;
  background: linear-gradient(
    to bottom,
    transparent,
    rgba(var(--feat-violet-rgb), 0.64) 9%,
    rgba(90, 116, 255, 0.42) 50%,
    rgba(var(--feat-mint-rgb), 0.58) 91%,
    transparent
  );
  content: '';
}

.cockpit-showcase__story {
  --story-accent: var(--feat-violet-soft);
  --story-accent-rgb: 169, 144, 255;
  --cockpit-showcase-node-rgb: 169, 144, 255;

  position: relative;
  display: grid;
  grid-template-columns: minmax(21rem, 0.8fr) minmax(0, 1.56fr);
  gap: clamp(2.6rem, 5vw, 5rem);
  align-items: center;
}

/* One declaration per tone, shared by the story it colours and by the head
   node that previews it — a tone can never drift between the two. */
.cockpit-showcase__story--tone-violet,
.cockpit-showcase__index-node--tone-violet {
  --story-accent: var(--feat-violet-soft);
  --story-accent-rgb: 169, 144, 255;
  --cockpit-showcase-node-rgb: 169, 144, 255;
}

.cockpit-showcase__story--tone-indigo,
.cockpit-showcase__index-node--tone-indigo {
  --story-accent: #9b98ff;
  --story-accent-rgb: 155, 152, 255;
  --cockpit-showcase-node-rgb: 129, 130, 255;
}

.cockpit-showcase__story--tone-blue,
.cockpit-showcase__index-node--tone-blue {
  --story-accent: #8da0ff;
  --story-accent-rgb: 141, 160, 255;
  --cockpit-showcase-node-rgb: 90, 116, 255;
}

.cockpit-showcase__story--tone-teal,
.cockpit-showcase__index-node--tone-teal {
  --story-accent: #68d9ee;
  --story-accent-rgb: 104, 217, 238;
  --cockpit-showcase-node-rgb: 58, 160, 197;
}

.cockpit-showcase__story--tone-mint,
.cockpit-showcase__index-node--tone-mint {
  --story-accent: var(--feat-mint);
  --story-accent-rgb: 25, 206, 136;
  --cockpit-showcase-node-rgb: var(--feat-mint-rgb);
}

.cockpit-showcase__story::before {
  position: absolute;
  top: 50%;
  left: calc(-2.4rem + var(--cockpit-showcase-rail-x));
  width: 9px;
  height: 9px;
  border: 2px solid var(--feat-bg);
  border-radius: 50%;
  background: rgb(var(--cockpit-showcase-node-rgb));
  box-shadow:
    0 0 0 1px rgba(var(--cockpit-showcase-node-rgb), 0.5),
    0 0 18px rgba(var(--cockpit-showcase-node-rgb), 0.6);
  content: '';
  transform: translate(-50%, -50%);
}

.cockpit-showcase__story--reverse {
  grid-template-columns: minmax(0, 1.56fr) minmax(21rem, 0.8fr);
}

.cockpit-showcase__story--reverse .cockpit-showcase__copy {
  grid-column: 2;
}

.cockpit-showcase__story--reverse .cockpit-showcase__media {
  grid-row: 1;
  grid-column: 1;
}

.cockpit-showcase__copy {
  position: relative;
  z-index: 2;
  max-width: var(--cockpit-showcase-copy-max);
}

.cockpit-showcase .feat-story__title {
  font-size: var(--cockpit-showcase-title-size);
}

.cockpit-showcase .feat-story__title-accent {
  background-image: var(--brand-title-gradient);
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

.cockpit-showcase__media {
  margin: 0;
}

/* Most of these renders are dashboard strips, roughly 1.6 wide for 1 tall, and
   the media column's width is what sets their size. A near-square render put
   through the same rule stands almost twice as tall and breaks the page's
   rhythm, so it is sized by HEIGHT instead — the height a strip takes in the
   same column. Two consequences worth keeping: the row matches its neighbours
   whatever the render's aspect, and the two languages match each other even
   though their crops do not. The resulting WIDTH is what the `sizes` of those
   images must describe. */
/* Centred in its column rather than pinned to the container edge: a render
   narrower than the column would otherwise sit right against the page margin
   with all of its slack opening between it and the copy. Centring splits that
   slack in two, and works the same way on a reversed row. */
.cockpit-showcase__media--portrait {
  justify-self: center;
}

.cockpit-showcase__media img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 0.8rem;
  box-shadow: 0 0.85rem 2rem rgba(2, 3, 18, 0.18);
}

/* Same specificity as the rule above, so it only wins by coming after it —
   keep them in this order. Sizing by height is the whole point of the
   modifier: `width: 100%` would hand the size back to the column. */
.cockpit-showcase__media--portrait img {
  width: auto;
  max-width: 100%;
  /* The strips in these tracks are ~1.687 wide for 1 tall. Deriving the height
     from the COLUMN rather than from the viewport is what makes a near-square
     render exactly as tall as the strips above and below it — at every width,
     and in both languages, whose crops do not share an aspect. */
  height: calc(var(--cockpit-showcase-media-w) / 1.687);
}

/* The media column's width, as one law in two segments. Below ~1155px the copy
   track is pinned at its minmax() minimum and the media column takes what is
   left, so it grows on a steeper slope than above it. This is the SAME law the
   fragments' `sizes` attributes declare — they cannot read a custom property,
   so the two are kept in step by cockpit-showcase-architecture.test.js. Move
   the grid ratio, the gap or the container max and BOTH have to be re-measured. */
@media (min-width: 901px) {
  .cockpit-showcase {
    --cockpit-showcase-media-w: calc(89vw - 374px);
  }
}

@media (min-width: 1156px) {
  .cockpit-showcase {
    --cockpit-showcase-media-w: min(60.5vw - 44px, 864px);
  }
}

@media (min-width: 901px) {
  .cockpit-showcase > .feat-container {
    width: min(
      var(--cockpit-showcase-container-max),
      calc(100% - 2 * var(--cockpit-showcase-page-gutter))
    );
  }
}

@media (max-width: 900px) {
  .cockpit-showcase__story,
  .cockpit-showcase__story--reverse {
    grid-template-columns: minmax(0, 1fr);
    gap: 2rem;
  }

  .cockpit-showcase__story--reverse .cockpit-showcase__copy,
  .cockpit-showcase__story--reverse .cockpit-showcase__media {
    grid-row: auto;
    grid-column: 1;
  }

  /* One column: nothing left to keep in rhythm with, so it fills the width
     like every other render. */
  /* `justify-self: center` shrink-wraps the figure, and a percentage width
     against a shrink-to-fit parent is indefinite — the render would take its
     size from `sizes` instead of from the column, the exact failure the
     modifier exists to avoid. Stretch first, then fill. */
  .cockpit-showcase__media--portrait {
    justify-self: stretch;
  }

  .cockpit-showcase__media--portrait img {
    width: 100%;
    height: auto;
  }
}

@media (max-width: 760px) {
  .cockpit-showcase__head {
    margin-bottom: 4rem;
  }

  .cockpit-showcase__name {
    font-size: var(--cockpit-showcase-name-size-mobile);
  }

  .cockpit-showcase__kicker {
    padding-left: 0.34em;
    letter-spacing: 0.34em;
  }

  /* The family's phone rule: headlines centre, body copy keeps a left edge. */
  .cockpit-showcase .cockpit-showcase__lede {
    text-align: left;
  }

  .cockpit-showcase__track {
    gap: 5.25rem;
    padding-left: 0;
  }

  .cockpit-showcase__track::before,
  .cockpit-showcase__story::before {
    display: none;
  }

  .cockpit-showcase__story {
    gap: 1.75rem;
  }

  .cockpit-showcase__copy {
    padding-inline: 0.25rem;
  }

  .cockpit-showcase .feat-story__title {
    font-size: var(--cockpit-showcase-title-size-mobile);
  }

  .cockpit-showcase .feat-story__body {
    max-width: 36rem;
    margin-right: auto;
    margin-left: auto;
    text-align: left;
  }

  .cockpit-showcase__media img {
    border-radius: 0.7rem;
    box-shadow: 0 0.65rem 1.5rem rgba(2, 3, 18, 0.16);
  }
}
