/* Gallery: the Components / Compose switch, grouped tiles, and the composer. */

.view-tabs {
  margin-bottom: 28px;
}

.gallery-bar {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: 32px;
}

.gallery-bar input[type="search"] {
  font: inherit;
  padding: 9px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  min-width: 240px;
}

.gallery-bar .swatches {
  margin-left: auto;
}

.count {
  color: var(--ink-2);
  font-size: 0.9rem;
}

/* ---------- Groups and tiles ---------- */

.group {
  padding: 0;
  border-top: 0;
  margin-bottom: 40px;
}

.group-title {
  font-size: 1.25rem;
  margin-bottom: 14px;
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 20px;
  align-items: start; /* tiles keep their own height instead of stretching to the tallest */
}

.tile {
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
  overflow: hidden;
}

.tile.full {
  grid-column: 1 / -1;
}

.tile-head {
  display: grid;
  gap: 4px;
  padding: 18px 20px 14px;
}

.tile-head code {
  font-weight: 600;
  font-size: 0.95rem;
  background: none;
  padding: 0;
}

.tile-head p {
  color: var(--ink-2);
  font-size: 0.9rem;
}

.tile-demo {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: center;
  align-content: center;
  min-height: 120px;
  padding: 20px;
  overflow-x: auto;
  background-color: var(--paper);
  background-image: radial-gradient(var(--line) 1px, transparent 1px);
  background-size: 14px 14px;
}

.tile-demo > * {
  max-width: 100%;
}

.tile-demo-note {
  color: var(--ink-2);
  font-size: 0.9rem;
}

.tile.full .tile-demo {
  justify-content: center;
}

.tile.full .tile-demo > consent-capabilities-screen {
  width: 100%;
  max-width: 480px;
}

/* The last few events an element fired. Used by tiles and by the composer. */
.tile-events {
  display: flex;
  gap: 10px;
  align-items: baseline;
  min-width: 0;
  min-height: 40px;
  padding: 10px 20px;
  border-top: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 0.78rem;
}

.tile-events .label {
  font-family: var(--font-body);
  font-weight: 600;
  color: var(--ink-2);
  white-space: nowrap;
}

.tile-events .last {
  color: var(--ink-2);
  white-space: pre-wrap;
  word-break: break-word;
}

.tile-events .last.hit {
  color: var(--grant);
}

.tile details {
  min-width: 0;
  padding: 12px 20px;
  border-top: 1px solid var(--line);
  font-size: 0.88rem;
}

.tile summary {
  cursor: pointer;
  font-weight: 600;
}

.usage {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 14px;
  padding-top: 12px;
}

.usage-row h4 {
  margin: 0 0 6px;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--ink-2);
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.chip {
  background: var(--paper-2);
  border-radius: 6px;
  padding: 2px 8px;
  font-size: 0.78rem;
}

.usage-note {
  color: var(--ink-2);
  font-size: 0.86rem;
}

/* ---------- Composer ---------- */

.compose {
  display: grid;
  gap: 16px;
  padding: 0 0 56px;
  border-top: 0;
}

.compose h2 {
  font-size: 1.8rem;
}

.compose .lede {
  font-size: 1.05rem;
}

.compose-grid {
  display: grid;
  grid-template-columns: 264px minmax(0, 1fr);
  gap: 24px;
  align-items: start;
}

.compose-grid .controls {
  position: sticky;
  top: 84px;
}

.compose-grid .field select {
  width: 100%;
  min-width: 0;
}

.field-label {
  font-size: 0.88rem;
  font-weight: 600;
}

/* Recipes: a radio group of cards, each with what it is for. */
.recipes {
  display: grid;
  gap: 6px;
}

.recipes button {
  display: grid;
  gap: 1px;
  padding: 9px 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.recipes button strong {
  font-size: 0.9rem;
  font-weight: 600;
}

.recipes button span {
  font-size: 0.8rem;
  font-weight: 400;
  color: var(--ink-2);
}

.recipes button:hover {
  border-color: var(--ink-2);
}

.recipes button[aria-checked="true"] {
  background: var(--surface);
  border-color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink);
}

.compose-out {
  display: grid;
  gap: 14px;
}

/* ---------- The stage ---------- */

/*
 * --e is how far the screen is taken apart (0 assembled, 1 exploded), --i a
 * plate's place in the stack, --raise the lift of the plate in focus. They are
 * registered so they can transition, and every transform below is built from
 * them, so one change moves the whole drawing.
 */
@property --e {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

@property --i {
  syntax: "<number>";
  inherits: false;
  initial-value: 0;
}

@property --mid {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

@property --raise {
  syntax: "<length>";
  inherits: false;
  initial-value: 0px;
}

@property --orx {
  syntax: "<angle>";
  inherits: true;
  initial-value: 0deg;
}

@property --orz {
  syntax: "<angle>";
  inherits: true;
  initial-value: 0deg;
}

/* Where the exploded drawing sits in the stage, and its scale. They change
   when parts come and go, and the drawing glides to its new place. */
@property --shift {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}

@property --shift-y {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}

@property --fit {
  syntax: "<number>";
  inherits: true;
  initial-value: 1;
}

.compose-stage {
  min-width: 0;
  border: 1px solid var(--line);
  border-radius: 20px;
  background-color: var(--paper);
  background-image: radial-gradient(var(--line) 1px, transparent 1px);
  background-size: 16px 16px;
  overflow: hidden;
}

.stage-bar {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  padding: 14px 16px 0;
}

.stage-hint {
  margin: 0;
  font-size: 0.84rem;
  color: var(--ink-2);
}

.stage-body {
  /* The drawing: tilt, plate spacing and lift. Narrow stages flatten it. */
  --tilt-x: 42deg;
  --tilt-z: -14deg;
  --spread: 72px;
  --lift: 40px;
  --shift: 0px;
  --shift-y: 0px;
  --fit: 1;
  --e: 0;
  position: relative;
  display: grid;
  justify-items: start;
  align-items: center;
  min-height: 600px;
  padding: 28px 24px 36px;
  perspective: 2400px;
  perspective-origin: 40% 30%;
  --ease: cubic-bezier(0.22, 0.8, 0.2, 1);
  transition:
    --e 1.05s var(--ease),
    --orx 0.5s var(--ease),
    --orz 0.5s var(--ease),
    --shift 0.7s var(--ease),
    --shift-y 0.7s var(--ease),
    --fit 0.7s var(--ease);
  outline-offset: -3px;
}

.compose-stage.is-exploded .stage-body {
  --e: 1;
  cursor: grab;
  /* A drag turns the drawing, so it must not select text on the way. */
  user-select: none;
}

/* While dragging, the drawing follows the pointer with no lag. */
.compose-stage.is-dragging .stage-body {
  cursor: grabbing;
  transition:
    --e 1.05s var(--ease),
    --shift 0.7s var(--ease),
    --shift-y 0.7s var(--ease),
    --fit 0.7s var(--ease);
}

/* The screen itself. Its card face fades out as the plates lift off it,
   leaving the footprint they came from. */
.compose-card {
  --mid: calc((var(--n, 1) - 1) / 2);
  position: relative;
  display: grid;
  width: min(100%, 440px);
  padding: 15px 20px;
  justify-self: center;
  transform-style: preserve-3d;
  transform-origin: 50% 50%;
  transform: translate(
      calc(var(--shift) * var(--e)),
      calc(var(--shift-y) * var(--e))
    )
    scale(calc(1 - (1 - var(--fit)) * var(--e)))
    rotateX(calc((var(--tilt-x) + var(--orx)) * var(--e)))
    rotateZ(calc((var(--tilt-z) + var(--orz)) * var(--e)));
  transition: --mid 0.6s cubic-bezier(0.22, 0.8, 0.2, 1);
}

.compose-card::before,
.compose-card::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 20px;
  pointer-events: none;
}

.compose-card::before {
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: 0 30px 60px -36px rgba(14, 26, 51, 0.35);
  opacity: calc(1 - var(--e));
}

.compose-card::after {
  border: 1.5px dashed color-mix(in srgb, var(--ink-2) 45%, transparent);
  background: color-mix(in srgb, var(--surface) 35%, transparent);
  opacity: var(--e);
}

.card-empty {
  display: none;
  justify-self: center;
  color: var(--ink-2);
}

.compose-stage.is-empty .card-empty {
  display: block;
}

.compose-stage.is-empty .compose-card {
  display: none;
}

/* ---------- Plates ---------- */

.part {
  --lift-now: calc(var(--lift) + var(--raise));
  position: relative;
  display: grid;
  grid-template-rows: 1fr;
  min-width: 0;
  transform-style: preserve-3d;
  transform: translateY(
      calc((var(--i) - var(--mid)) * var(--spread) * var(--e))
    )
    translateZ(calc(var(--lift-now) * var(--e)));
  transition:
    --i 0.6s cubic-bezier(0.22, 0.8, 0.2, 1),
    --raise 0.35s cubic-bezier(0.22, 0.8, 0.2, 1),
    grid-template-rows 0.45s cubic-bezier(0.22, 0.8, 0.2, 1),
    opacity 0.35s ease;
}

/* The content floats a pixel above its plate: coplanar layers in a 3D scene
   have no reliable paint order. */
.part-inner {
  min-height: 0;
  min-width: 0;
  transform: translateZ(1px);
}

.part-content {
  display: grid;
  gap: 14px;
  padding-block: 9px;
}

.part-content > p {
  color: var(--ink-2);
  font-size: 0.95rem;
}

/* The plate a part sits on when the screen comes apart. */
.part::before {
  content: "";
  position: absolute;
  inset: 0 -12px;
  border-radius: 14px;
  background: var(--surface);
  box-shadow:
    0 0 0 1px var(--line),
    0 1px 0 1px color-mix(in srgb, var(--line) 70%, var(--ink-2));
  opacity: var(--e);
  pointer-events: none;
  transition: box-shadow 0.25s ease;
}

/* Its shadow, left behind on the card as the plate lifts. */
.part::after {
  content: "";
  position: absolute;
  inset: 8px -4px 0;
  border-radius: 14px;
  background: rgba(14, 26, 51, 0.2);
  filter: blur(12px);
  transform: translateZ(calc(var(--lift-now) * var(--e) * -1));
  opacity: var(--e);
  pointer-events: none;
}

.part-anchor {
  position: absolute;
  right: -12px;
  top: 50%;
  width: 0;
  height: 0;
}

.compose-stage.is-exploded .part.is-active {
  --raise: 22px;
}

.compose-stage.is-exploded .part.is-active::before {
  box-shadow:
    0 0 0 1.5px var(--signal),
    0 1px 0 1.5px var(--signal);
}

.part.is-entering,
.part.is-leaving {
  grid-template-rows: 0fr;
  opacity: 0;
}

.part.is-entering .part-inner,
.part.is-leaving .part-inner {
  overflow: hidden;
}

/* ---------- Labels and leader lines ---------- */

.leaders {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
  opacity: var(--e);
}

.leader {
  fill: none;
  stroke: var(--ink-2);
  stroke-width: 1;
  stroke-opacity: 0.6;
  transition:
    stroke 0.2s ease,
    stroke-width 0.2s ease;
}

.leader-dot {
  fill: var(--surface);
  stroke: var(--ink);
  stroke-width: 1.5;
}

.leader.is-active {
  stroke: var(--signal);
  stroke-width: 1.5;
  stroke-opacity: 1;
}

.leader-dot.is-active {
  stroke: var(--signal);
  fill: var(--signal);
}

.part-labels {
  position: absolute;
  top: 0;
  right: 24px;
  bottom: 0;
  width: 236px;
  margin: 0;
  padding: 0;
  list-style: none;
  opacity: var(--e);
  visibility: hidden;
  transition: visibility 0s linear 1.05s;
}

.compose-stage.is-exploded .part-labels {
  visibility: visible;
  transition-delay: 0s;
}

.part-label {
  position: absolute;
  left: 0;
  right: 0;
}

.part-label button {
  display: grid;
  gap: 2px;
  width: 100%;
  padding: 7px 10px 8px;
  border: 0;
  border-left: 2px solid var(--line);
  border-radius: 0 8px 8px 0;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition:
    border-color 0.2s ease,
    background-color 0.2s ease;
}

.part-label.is-active button {
  border-left-color: var(--signal);
  background: var(--surface);
}

.label-tag {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--ink);
  background: none;
  padding: 0;
}

.label-role {
  font-size: 0.84rem;
  line-height: 1.4;
  color: var(--ink-2);
}

.label-seal,
.label-event {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--ink-2);
}

.label-seal:empty,
.label-event:empty {
  display: none;
}

.label-event {
  color: var(--grant);
  opacity: 0;
}

.part-label.is-firing .label-event {
  animation: fired 2.4s ease forwards;
}

@keyframes fired {
  0%,
  70% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

.part-label.is-firing button {
  animation: fired-edge 1.2s ease;
}

@keyframes fired-edge {
  0% {
    border-left-color: var(--grant);
  }
  100% {
    border-left-color: var(--line);
  }
}

/* ---------- Narrow: no room for a label column, so the drawing goes flat
   and each label sits in the gap above its plate. ---------- */

.compose-stage.is-narrow .stage-body {
  --tilt-x: 0deg;
  --tilt-z: 0deg;
  --spread: 0px;
  --lift: 0px;
  /* The gap above each plate that its label sits in. */
  --label-room: 30px;
  min-height: 0;
  padding: 20px 16px 28px;
  cursor: auto;
  user-select: auto;
}

.compose-stage.is-narrow .compose-card {
  width: 100%;
}

.compose-stage.is-narrow .part-content {
  padding-top: calc(9px + var(--label-room) * var(--e));
}

.compose-stage.is-narrow .part::before {
  top: calc(var(--label-room) * var(--e));
}

.compose-stage.is-narrow .part::after,
.compose-stage.is-narrow .leaders,
.compose-stage.is-narrow .label-role,
.compose-stage.is-narrow .label-event {
  display: none;
}

.compose-stage.is-narrow .part-labels {
  inset: 0;
  width: auto;
  pointer-events: none;
}

.compose-stage.is-narrow .part-label {
  right: auto;
  pointer-events: auto;
}

.compose-stage.is-narrow .part-label button {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 2px 8px;
  border-left: 0;
  border-radius: 6px;
  background: transparent;
  white-space: nowrap;
  overflow: hidden;
}

/* A phone has no room for the tag and the seal on one line. */
.compose-stage.is-tight .stage-body {
  --label-room: 44px;
}

.compose-stage.is-tight .part-label button {
  display: grid;
  gap: 0;
}

/* Measuring the exploded layout: no motion, fully apart, at rest. */
.compose-stage.is-measuring .stage-body {
  --e: 1 !important;
  --orx: var(--measure-x, 0deg) !important;
  --orz: var(--measure-z, 0deg) !important;
}

.compose-stage.is-measuring .part.is-entering {
  grid-template-rows: 1fr;
}

.compose-stage.is-still,
.compose-stage.is-still * {
  transition: none !important;
}

/* ---------- Events and code ---------- */

.compose-events {
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
}

#compose-code {
  min-width: 0;
}

#compose-code pre.code {
  position: relative;
}

#compose-code pre.code code {
  position: relative;
}

.code-band {
  position: absolute;
  left: 0;
  min-width: 100%;
  background: rgba(134, 187, 255, 0.13);
  box-shadow: inset 3px 0 0 #86bbff;
  opacity: 0;
  pointer-events: none;
  transition:
    opacity 0.2s ease,
    top 0.25s cubic-bezier(0.22, 0.8, 0.2, 1),
    height 0.25s cubic-bezier(0.22, 0.8, 0.2, 1);
}

.code-band.is-on {
  opacity: 1;
}

.code-band.is-flash {
  animation: band-flash 0.9s ease;
}

@keyframes band-flash {
  0%,
  40% {
    background: rgba(134, 187, 255, 0.32);
  }
}

@media (max-width: 900px) {
  .compose-grid {
    grid-template-columns: minmax(0, 1fr);
  }
  .compose-grid .controls {
    position: static;
  }
}

@media (max-width: 600px) {
  .gallery-bar input[type="search"] {
    min-width: 0;
    width: 100%;
  }
  .gallery-bar .swatches {
    margin-left: 0;
  }
  .grid {
    grid-template-columns: minmax(0, 1fr);
  }
}
