/*
  Ludifica public site. Depends on tokens.css (load it first).
  No framework. Class prefix .ludi- ; BEM-ish (block__element--modifier).

  Sections
    1. Base and reset
    2. Layout primitives (container, section, headings, buttons, links, role label)
    3. Header, footer
    4. Device clip (host screen + phone)
    5. Home: hero, process track, formats, gallery, waitlist
    6. Interactions gallery (/interacoes) and interaction pages (/interacoes/<slug>)
*/

/* 1. Base ------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body.ludi-site {
  margin: 0;
  background: var(--ludi-color-bg);
  color: var(--ludi-color-text);
  font-family: var(--ludi-font-body);
  font-size: var(--ludi-text-md);
  line-height: var(--ludi-leading-body);
  font-kerning: normal;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

/* :where() keeps the reset at zero specificity so any component class wins. */
:where(.ludi-site) :where(img, svg, video) { display: block; max-width: 100%; }
:where(.ludi-site) :where(h1, h2, h3, p, figure, dl, dd) { margin: 0; }
:where(.ludi-site) :where(ul, ol) { margin: 0; padding: 0; list-style: none; }
:where(.ludi-site) :where(button, input) { font: inherit; color: inherit; }

.ludi-site :focus-visible {
  outline: 3px solid var(--ludi-color-focus);
  outline-offset: 3px;
  border-radius: var(--ludi-radius-xs);
}

#main:focus { outline: none; }

.ludi-visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.ludi-skip {
  position: absolute;
  left: var(--ludi-space-4);
  top: -4rem;
  z-index: 100;
  padding: var(--ludi-space-2) var(--ludi-space-4);
  background: var(--ludi-color-action-bg);
  color: var(--ludi-color-action-text);
  border-radius: var(--ludi-radius-sm);
  text-decoration: none;
}
.ludi-skip:focus { top: var(--ludi-space-4); }

/* 2. Primitives ------------------------------------------------------- */

.ludi-container {
  width: 100%;
  max-width: calc(var(--ludi-container) + 2 * var(--ludi-gutter));
  margin-inline: auto;
  padding-inline: var(--ludi-gutter);
}

.ludi-section { padding-block: var(--ludi-section-pad); }

.ludi-section__head {
  display: grid;
  gap: var(--ludi-space-4);
  margin-bottom: var(--ludi-space-8);
  max-width: var(--ludi-measure);
}

.ludi-h2 {
  font-family: var(--ludi-font-display);
  font-weight: var(--ludi-weight-bold);
  font-size: var(--ludi-text-2xl);
  line-height: var(--ludi-leading-snug);
  letter-spacing: var(--ludi-tracking-display);
  text-wrap: balance;
}

.ludi-h3 {
  font-family: var(--ludi-font-display);
  font-weight: var(--ludi-weight-semibold);
  font-size: var(--ludi-text-xl);
  line-height: var(--ludi-leading-snug);
  letter-spacing: var(--ludi-tracking-tight);
}

.ludi-lead {
  font-size: var(--ludi-text-lg);
  line-height: 1.5;
  color: var(--ludi-color-text-muted);
  max-width: var(--ludi-measure);
  text-wrap: pretty;
}

.ludi-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--ludi-space-2);
  min-height: 3rem;
  padding: 0.7rem 1.4rem;
  border: 2px solid var(--ludi-color-action-bg);
  border-radius: var(--ludi-radius-pill);
  background: var(--ludi-color-action-bg);
  color: var(--ludi-color-action-text);
  font-family: var(--ludi-font-body);
  font-weight: var(--ludi-weight-bold);
  font-size: var(--ludi-text-md);
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--ludi-duration-base) var(--ludi-ease-out),
              border-color var(--ludi-duration-base) var(--ludi-ease-out),
              color var(--ludi-duration-base) var(--ludi-ease-out);
}
.ludi-btn:hover {
  background: var(--ludi-color-action-bg-hover);
  border-color: var(--ludi-color-action-bg-hover);
}
.ludi-btn--ghost {
  background: transparent;
  color: var(--ludi-color-text);
  border-color: var(--ludi-color-line-strong);
}
.ludi-btn--ghost:hover {
  background: transparent;
  color: var(--ludi-color-text);
  border-color: var(--ludi-color-text);
}
.ludi-btn--small {
  min-height: 2.5rem;
  padding: 0.45rem 1rem;
  font-size: var(--ludi-text-sm);
}
.ludi-btn--quiet {
  background: transparent;
  color: var(--ludi-color-text);
  border-color: var(--ludi-color-line-strong);
}
.ludi-btn--quiet:hover {
  background: var(--ludi-color-action-bg);
  color: var(--ludi-color-action-text);
  border-color: var(--ludi-color-action-bg);
}
.ludi-btn--block { width: 100%; }

.ludi-link {
  color: var(--ludi-color-link);
  font-weight: var(--ludi-weight-bold);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.22em;
  text-decoration-color: color-mix(in srgb, currentColor 35%, transparent);
  transition: text-decoration-color var(--ludi-duration-base) var(--ludi-ease-out);
}
.ludi-link:hover { text-decoration-color: currentColor; }

/* Role label: what an interaction does. The colour is information. */
.ludi-role {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  font-size: var(--ludi-text-sm);
  font-weight: var(--ludi-weight-bold);
  line-height: 1.3;
  color: var(--ludi-role-capture-text);
}
.ludi-role::before {
  content: "";
  flex: none;
  width: 0.7em;
  height: 0.7em;
  border-radius: 2px;
  background: var(--ludi-role-capture);
}
.ludi-role[data-role="generate"] { color: var(--ludi-role-generate-text); }
.ludi-role[data-role="generate"]::before { background: var(--ludi-role-generate); border-radius: 50%; }
.ludi-role[data-role="decide"] { color: var(--ludi-role-decide-text); }
.ludi-role[data-role="decide"]::before { background: var(--ludi-role-decide); transform: rotate(45deg) scale(0.85); }
.ludi-role[data-role="facilitate"] { color: var(--ludi-role-facilitate-text); }
.ludi-role[data-role="facilitate"]::before { background: var(--ludi-role-facilitate); border-radius: 50% 50% 2px 2px; }

/* 3. Header and footer ------------------------------------------------ */

.ludi-header {
  border-bottom: 1px solid var(--ludi-color-line);
  background: var(--ludi-color-bg);
}

.ludi-header__bar {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--ludi-space-6);
  min-height: 4.5rem;
}

.ludi-header__brand { display: inline-flex; padding-block: var(--ludi-space-2); }
.ludi-header__brand img { width: 128px; height: auto; }

.ludi-nav__list { display: flex; gap: var(--ludi-space-2); }
.ludi-nav__link {
  display: inline-block;
  padding: var(--ludi-space-2) var(--ludi-space-3);
  border-radius: var(--ludi-radius-sm);
  color: var(--ludi-color-text);
  font-weight: var(--ludi-weight-semibold);
  text-decoration: none;
}
.ludi-nav__link:hover { background: var(--ludi-color-bg-sunken); }

.ludi-header__tools {
  display: flex;
  align-items: center;
  gap: var(--ludi-space-4);
}

.ludi-lang {
  display: inline-flex;
  padding: 3px;
  border: 1px solid var(--ludi-color-line-strong);
  border-radius: var(--ludi-radius-pill);
}
.ludi-lang__opt {
  display: inline-grid;
  place-items: center;
  min-width: 2.5rem;
  min-height: 2rem;
  padding: 0 0.6rem;
  border-radius: var(--ludi-radius-pill);
  color: var(--ludi-color-text-muted);
  font-size: var(--ludi-text-xs);
  font-weight: var(--ludi-weight-bold);
  letter-spacing: 0.04em;
  text-decoration: none;
}
.ludi-lang__opt:hover { color: var(--ludi-color-text); }
.ludi-lang__opt[aria-current="true"] {
  background: var(--ludi-color-action-bg);
  color: var(--ludi-color-action-text);
}
.ludi-nav__link[aria-current="page"] { box-shadow: inset 0 -3px 0 var(--ludi-color-text); border-radius: var(--ludi-radius-sm) var(--ludi-radius-sm) 0 0; }

@media (max-width: 47.99rem) {
  .ludi-header__bar {
    grid-template-columns: auto auto;
    justify-content: space-between;
    gap: 0 var(--ludi-space-4);
    min-height: 0;
    padding-top: var(--ludi-space-3);
  }
  .ludi-header__brand img { width: 108px; }
  .ludi-header__tools { gap: var(--ludi-space-2); }
  .ludi-nav {
    grid-column: 1 / -1;
    grid-row: 2;
    margin-inline: calc(-1 * var(--ludi-space-3));
    padding-block: var(--ludi-space-1) var(--ludi-space-2);
  }
}

.ludi-footer {
  border-top: 1px solid var(--ludi-color-line);
  background: var(--ludi-color-bg-sunken);
  padding-block: var(--ludi-space-8) var(--ludi-space-6);
  font-size: var(--ludi-text-sm);
  color: var(--ludi-color-text-muted);
}
.ludi-footer__grid {
  display: grid;
  gap: var(--ludi-space-6);
  grid-template-columns: 1fr;
}
.ludi-footer__brand { display: grid; gap: var(--ludi-space-3); max-width: 32ch; }
.ludi-footer__links { display: flex; flex-wrap: wrap; gap: var(--ludi-space-2) var(--ludi-space-5); }
.ludi-footer__links a { color: var(--ludi-color-text); text-underline-offset: 0.2em; }
.ludi-footer__legal { color: var(--ludi-color-text-muted); }

@media (min-width: 48rem) {
  .ludi-footer__grid { grid-template-columns: 1fr auto; align-items: start; }
  .ludi-footer__legal { grid-column: 1 / -1; padding-top: var(--ludi-space-5); border-top: 1px solid var(--ludi-color-line); }
}

/* 4. Device clip ------------------------------------------------------
   Sized by its container: everything inside uses cqi so the bezel, the
   phone and the toggle keep their proportions from hero to gallery card. */

.ludi-device {
  container-type: inline-size;
  position: relative;
  margin: 0;
}

.ludi-device__host {
  position: relative;
  padding: 1.1cqi;
  border-radius: 1.6cqi;
  background: var(--ludi-device-bezel);
  box-shadow: inset 0 0 0 1px var(--ludi-device-bezel-edge), var(--ludi-shadow-device);
}

.ludi-device__screen,
.ludi-device__phone-screen {
  position: relative;
  overflow: hidden;
  background:
    linear-gradient(135deg, transparent 0 48%, rgb(255 255 255 / 0.04) 48% 52%, transparent 52%) 0 0 / 22px 22px,
    var(--ludi-device-screen-empty);
}

.ludi-device__screen {
  aspect-ratio: 16 / 9;
  border-radius: 0.6cqi;
}

.ludi-device__video {
  position: relative; /* paints over the lazy poster <img> below it */
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: transparent;
}
/* Lazy poster (DeviceClipModel.LazyPoster): under the video, which stays transparent
   until it has a frame. */
.ludi-device__poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* cqi on the children resolves against .ludi-device, so the space for the
   phone is reserved on the host rather than as padding on the device. */
.ludi-device--with-phone .ludi-device__host { margin-right: 12cqi; margin-bottom: 15cqi; }

.ludi-device__phone {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 22cqi;
  padding: 1.1cqi;
  border-radius: 3.6cqi;
  background: var(--ludi-device-bezel);
  box-shadow: inset 0 0 0 1px var(--ludi-device-bezel-edge), var(--ludi-shadow-device);
}
.ludi-device__phone::before {
  /* speaker notch */
  content: "";
  position: absolute;
  z-index: 1;
  top: 2.1cqi;
  left: 50%;
  width: 5cqi;
  height: 1.1cqi;
  transform: translateX(-50%);
  border-radius: var(--ludi-radius-pill);
  background: var(--ludi-device-bezel);
}
.ludi-device__phone-screen {
  aspect-ratio: 780 / 1688;
  border-radius: 2.6cqi;
}

/* Laptop participant (16:10 screen on a thin base), for interactions whose
   participant view is a laptop take (catalog participantDevice: "laptop"). */
.ludi-device--with-laptop .ludi-device__host { margin-right: 20cqi; margin-bottom: 13cqi; }

.ludi-device__laptop {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 44cqi;
  filter: drop-shadow(0 18px 24px rgb(4 12 18 / 0.55));
}
.ludi-device__laptop-lid {
  margin-inline: 3cqi;
  padding: 1cqi 1cqi 1.3cqi;
  border-radius: 1.4cqi 1.4cqi 0.3cqi 0.3cqi;
  background: var(--ludi-device-bezel);
  box-shadow: inset 0 0 0 1px var(--ludi-device-bezel-edge);
}
.ludi-device__laptop-screen {
  position: relative;
  overflow: hidden;
  aspect-ratio: 16 / 10;
  border-radius: 0.4cqi;
  background: var(--ludi-device-screen-empty);
}
.ludi-device__laptop-base {
  height: 1.7cqi;
  border-radius: 0.2cqi 0.2cqi 1.2cqi 1.2cqi;
  background: linear-gradient(to bottom, var(--ludi-device-bezel-edge), var(--ludi-device-bezel) 70%);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.08);
}
.ludi-device__laptop-base::before {
  /* the thumb notch */
  content: "";
  display: block;
  width: 7cqi;
  height: 0.6cqi;
  margin-inline: auto;
  border-radius: 0 0 0.6cqi 0.6cqi;
  background: var(--ludi-device-bezel);
}

.ludi-device__toggle {
  position: absolute;
  left: 2.2cqi;
  bottom: 2.2cqi;
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgb(12 28 39 / 0.72);
  color: #fff;
  cursor: pointer;
  opacity: 0.85;
  transition: opacity var(--ludi-duration-base) var(--ludi-ease-out), background-color var(--ludi-duration-base);
}
.ludi-device--with-phone .ludi-device__toggle { bottom: calc(15cqi + 2.2cqi); }
.ludi-device--with-laptop .ludi-device__toggle { bottom: calc(13cqi + 2.2cqi); }
.ludi-device__toggle:hover, .ludi-device__toggle:focus-visible { opacity: 1; background: rgb(12 28 39 / 0.92); }
.ludi-device__toggle svg { fill: currentColor; }
.ludi-device__icon-pause { display: none; }
.ludi-device.is-playing .ludi-device__icon-pause { display: inline; }
.ludi-device.is-playing .ludi-device__icon-play { display: none; }

/* 5a. Hero ------------------------------------------------------------ */

.ludi-hero { padding-block: var(--ludi-space-7) var(--ludi-section-pad); }

.ludi-hero__grid {
  display: grid;
  gap: var(--ludi-space-7);
  align-items: center;
}

.ludi-hero__copy { display: grid; gap: var(--ludi-space-5); max-width: 38rem; }

.ludi-hero__title {
  font-family: var(--ludi-font-display);
  font-weight: var(--ludi-weight-bold);
  font-size: var(--ludi-text-4xl);
  line-height: var(--ludi-leading-tight);
  letter-spacing: var(--ludi-tracking-display);
  text-wrap: balance;
}

.ludi-hero__title > span { display: block; }

.ludi-hero__lead {
  font-size: var(--ludi-text-lg);
  line-height: 1.5;
  color: var(--ludi-color-text-muted);
  max-width: var(--ludi-measure-narrow);
}

.ludi-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ludi-space-3);
  padding-top: var(--ludi-space-2);
}

/* The stage: a darkened room where the product supplies all the colour. */
.ludi-hero__stage {
  position: relative;
  display: grid;
  gap: var(--ludi-space-5);
  padding: clamp(1.25rem, 0.5rem + 3vw, 3rem);
  border-radius: var(--ludi-radius-lg);
  background:
    radial-gradient(ellipse 70% 55% at 45% 38%, rgb(72 172 215 / 0.16), transparent 70%),
    var(--ludi-color-bg);
}

.ludi-hero__caption {
  font-size: var(--ludi-text-sm);
  color: var(--ludi-color-text-muted);
  max-width: 52ch;
}
.ludi-hero__more {
  display: inline-block;
  margin-left: 0.25em;
  color: var(--ludi-color-link);
  font-weight: var(--ludi-weight-bold);
  text-underline-offset: 0.2em;
}

@media (min-width: 64rem) {
  .ludi-hero { padding-top: var(--ludi-space-8); }
  .ludi-hero__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr); gap: var(--ludi-space-8); }
  .ludi-hero__stage {
    /* bleed off the right edge of the viewport */
    margin-right: calc(-1 * max(var(--ludi-gutter), (100vw - var(--ludi-container)) / 2));
    border-radius: var(--ludi-radius-lg) 0 0 var(--ludi-radius-lg);
    padding-right: max(var(--ludi-gutter), (100vw - var(--ludi-container)) / 2);
  }
}

/* 5b. Process track --------------------------------------------------- */

.ludi-process { background: var(--ludi-color-bg); border-top: 1px solid var(--ludi-color-line); }

@media (min-width: 64rem) {
  .ludi-process__head {
    max-width: none;
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    gap: var(--ludi-space-8);
    align-items: end;
  }
}

.ludi-script { --node: 3rem; margin: 0; }

.ludi-script__caption {
  margin-bottom: var(--ludi-space-6);
  font-size: var(--ludi-text-sm);
  color: var(--ludi-color-text-muted);
}

.ludi-script__track {
  position: relative;
  display: grid;
  gap: var(--ludi-space-6);
}

/* The wire between steps. Dashes drift forward: data moving along. */
.ludi-script__track::before {
  content: "";
  position: absolute;
  z-index: 0;
  left: calc(var(--node) / 2 - 1px);
  top: calc(var(--node) / 2);
  bottom: calc(var(--node) / 2);
  width: 2px;
  background: repeating-linear-gradient(to bottom, var(--ludi-color-line-strong) 0 8px, transparent 8px 14px);
  animation: ludi-wire-v 1.4s linear infinite;
}
@keyframes ludi-wire-v { to { background-position: 0 14px; } }
@keyframes ludi-wire-h { to { background-position: 14px 0; } }

.ludi-script__step,
.ludi-script__next {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: var(--node) minmax(0, 1fr);
  column-gap: var(--ludi-space-4);
  align-items: start;
}

.ludi-script__node {
  display: grid;
  place-items: center;
  width: var(--node);
  height: var(--node);
  border-radius: 50%;
  background: var(--ludi-color-bg);
  border: 3px solid var(--ludi-role-capture);
  font-family: var(--ludi-font-display);
  font-weight: var(--ludi-weight-bold);
  font-size: var(--ludi-text-lg);
}
.ludi-script__step[data-role="generate"] .ludi-script__node { border-color: var(--ludi-role-generate); background: color-mix(in srgb, var(--ludi-role-generate) 22%, var(--ludi-color-bg)); }
.ludi-script__step[data-role="decide"] .ludi-script__node { border-color: var(--ludi-role-decide); }
.ludi-script__step[data-role="capture"] .ludi-script__node { background: color-mix(in srgb, var(--ludi-role-capture) 14%, var(--ludi-color-bg)); }
.ludi-script__step[data-role="decide"] .ludi-script__node { background: color-mix(in srgb, var(--ludi-role-decide) 18%, var(--ludi-color-bg)); }

.ludi-script__node--next {
  border: 2px dashed var(--ludi-color-line-strong);
  background: var(--ludi-color-bg);
  transform: scale(0.75);
}

.ludi-script__body { display: grid; gap: var(--ludi-space-2); padding-top: 0.55rem; }

.ludi-script__title {
  font-family: var(--ludi-font-display);
  font-weight: var(--ludi-weight-semibold);
  font-size: var(--ludi-text-xl);
  line-height: var(--ludi-leading-snug);
  letter-spacing: var(--ludi-tracking-tight);
  order: -1;
}
.ludi-script__desc { color: var(--ludi-color-text-muted); max-width: 34ch; }
.ludi-script__tool { font-size: var(--ludi-text-sm); color: var(--ludi-color-text-muted); }
.ludi-script__tool a {
  color: var(--ludi-color-link);
  font-weight: var(--ludi-weight-semibold);
  text-underline-offset: 0.2em;
  text-decoration-color: color-mix(in srgb, currentColor 40%, transparent);
}
.ludi-script__tool a:hover { text-decoration-color: currentColor; }

.ludi-script__payload {
  position: relative;
  z-index: 2;
  grid-column: 2;
  margin-top: var(--ludi-space-4);
}
.ludi-script__chip {
  display: inline-block;
  padding: 0.3rem 0.85rem;
  border: 1.5px solid var(--ludi-color-text);
  border-radius: var(--ludi-radius-pill);
  background: var(--ludi-color-surface);
  font-size: var(--ludi-text-sm);
  font-weight: var(--ludi-weight-bold);
  white-space: nowrap;
  box-shadow: 3px 3px 0 var(--ludi-color-line-strong);
}

.ludi-script__next-text {
  padding-top: 0.7rem;
  color: var(--ludi-color-text-muted);
  font-style: italic;
}

@media (min-width: 64rem) {
  .ludi-script__track {
    grid-template-columns: repeat(4, minmax(0, 1fr)) minmax(0, 0.55fr);
    gap: 0;
  }
  .ludi-script__track::before {
    left: calc(var(--node) / 2);
    right: 0;
    top: calc(var(--node) / 2 - 1px);
    bottom: auto;
    width: auto;
    height: 2px;
    background: repeating-linear-gradient(to right, var(--ludi-color-line-strong) 0 8px, transparent 8px 14px);
    animation-name: ludi-wire-h;
  }
  .ludi-script__step,
  .ludi-script__next {
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--ludi-space-4);
    padding-right: var(--ludi-space-6);
  }
  .ludi-script__body { padding-top: 0; }
  /* The payload sits on the wire, halfway to the next node. */
  .ludi-script__payload {
    grid-column: 1;
    position: absolute;
    top: calc(var(--node) / 2);
    left: calc(var(--node) / 2 + 50%);
    margin: 0;
    transform: translate(-50%, -50%);
  }
  .ludi-script__next { align-content: start; }
  .ludi-script__next .ludi-script__node--next { transform: none; }
  .ludi-script__next-text { padding-top: 0; }
}

.ludi-legend {
  display: grid;
  gap: var(--ludi-space-5);
  margin-top: var(--ludi-space-8);
  padding-top: var(--ludi-space-6);
  border-top: 1px solid var(--ludi-color-line);
}
.ludi-legend__item { display: grid; gap: var(--ludi-space-2); align-content: start; }
.ludi-legend__item dd { color: var(--ludi-color-text-muted); font-size: var(--ludi-text-sm); max-width: 40ch; }
@media (min-width: 48rem) {
  .ludi-legend { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--ludi-space-6); }
}
@media (min-width: 64rem) {
  .ludi-legend { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}


/* The track plays (Home/Index inline script adds .is-armed, then .is-running in view):
   each step lights up in turn, its output travels along the wire into the next node as
   little role-shaped pieces and lands as the chip. The pieces keep flowing while the
   track is on screen (.is-offscreen pauses them). Never under reduced motion. */
.ludi-script { --beat: 1.1s; }
.ludi-script__flow {
  position: absolute;
  z-index: 0;
  left: calc(var(--node) / 2);
  top: calc(var(--node) / 2);
  width: 0;
  height: calc(100% + var(--ludi-space-6)); /* to the next node: the step plus the gap */
  container-type: size;
  pointer-events: none;
}
.ludi-script__flow i {
  position: absolute;
  left: -0.42rem;
  top: -0.42rem;
  width: 0.84rem;
  height: 0.84rem;
  border-radius: var(--shape-radius);
  background: var(--role);
  box-shadow: 0 0 0 2px var(--ludi-color-bg);
  opacity: 0;
  visibility: hidden;
}
@media (min-width: 64rem) {
  .ludi-script__flow { width: 100%; height: 0; } /* to the next column's node */
}

.ludi-script.is-armed .ludi-script__step,
.ludi-script.is-armed .ludi-script__next { opacity: 0.3; }
.ludi-script.is-armed .ludi-script__chip { opacity: 0; transform: scale(0.3); }

.ludi-script.is-running .ludi-script__step,
.ludi-script.is-running .ludi-script__next {
  animation: ludi-step-on 480ms var(--ludi-ease-out) both;
  animation-delay: calc(var(--i) * var(--beat));
}
.ludi-script.is-running .ludi-script__node {
  animation: ludi-node-pop 620ms cubic-bezier(0.3, 1.6, 0.5, 1) both;
  animation-delay: calc(var(--i) * var(--beat));
}
.ludi-script.is-running .ludi-script__chip {
  animation: ludi-chip-land 520ms cubic-bezier(0.3, 1.6, 0.5, 1) both;
  animation-delay: calc(var(--i) * var(--beat) + 0.8s);
}
.ludi-script.is-running .ludi-script__flow i {
  visibility: visible;
  animation: ludi-flow-v 1.5s cubic-bezier(0.45, 0, 0.55, 1) infinite;
  animation-delay: calc(var(--i) * var(--beat) + 0.25s);
}
.ludi-script.is-running .ludi-script__flow i:nth-child(2) { animation-delay: calc(var(--i) * var(--beat) + 0.6s); }
.ludi-script.is-running .ludi-script__flow i:nth-child(3) { animation-delay: calc(var(--i) * var(--beat) + 0.95s); }
.ludi-script.is-running .ludi-script__flow i:nth-child(4) { animation-delay: calc(var(--i) * var(--beat) + 1.3s); }
@media (min-width: 64rem) {
  .ludi-script.is-running .ludi-script__flow i { animation-name: ludi-flow-h; }
}
.ludi-script.is-offscreen .ludi-script__flow i { animation-play-state: paused; }

@keyframes ludi-step-on { from { opacity: 0.3; } to { opacity: 1; } }
@keyframes ludi-node-pop {
  0% { transform: scale(1); }
  45% { transform: scale(1.22); box-shadow: 0 0 0 8px color-mix(in srgb, var(--role) 25%, transparent); }
  100% { transform: scale(1); box-shadow: 0 0 0 0 transparent; }
}
@keyframes ludi-chip-land {
  from { opacity: 0; transform: scale(0.3) rotate(-8deg); }
  to { opacity: 1; transform: none; }
}
@keyframes ludi-flow-h {
  0% { opacity: 0; transform: translateX(1.6rem) rotate(var(--shape-rotate)) scale(0.5); }
  12%, 82% { opacity: 1; }
  100% { opacity: 0; transform: translateX(calc(100cqi - 1.6rem)) rotate(calc(var(--shape-rotate) + 180deg)) scale(1); }
}
@keyframes ludi-flow-v {
  0% { opacity: 0; transform: translateY(1.6rem) rotate(var(--shape-rotate)) scale(0.5); }
  12%, 82% { opacity: 1; }
  100% { opacity: 0; transform: translateY(calc(100cqb - 1.6rem)) rotate(calc(var(--shape-rotate) + 180deg)) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .ludi-script__track::before { animation: none; }
  .ludi-script__flow { display: none; }
  .ludi-script .ludi-script__step, .ludi-script .ludi-script__next,
  .ludi-script .ludi-script__node, .ludi-script .ludi-script__chip { animation: none; opacity: 1; transform: none; }
}

/* 5c. Formats --------------------------------------------------------- */

.ludi-formats { background: var(--ludi-color-bg-sunken); }

.ludi-formats__list { border-top: 2px solid var(--ludi-color-text); }

.ludi-format {
  display: grid;
  gap: var(--ludi-space-4);
  padding-block: var(--ludi-space-6);
  border-bottom: 1px solid var(--ludi-color-line-strong);
}
.ludi-format__name { display: grid; gap: var(--ludi-space-1); }
.ludi-format__meta { font-size: var(--ludi-text-sm); color: var(--ludi-color-text-muted); }
.ludi-format__desc { color: var(--ludi-color-text-muted); max-width: 52ch; }
.ludi-format .ludi-link { justify-self: start; }

/* The script strip: one block per step, coloured by role. */
.ludi-strip {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  min-height: 1.25rem;
}
.ludi-strip__step {
  position: relative;
  z-index: 1;
  width: 1.4rem;
  height: 1.1rem;
  border-radius: 3px;
  background: var(--ludi-role-capture);
}
.ludi-strip__step[data-role="generate"] { background: var(--ludi-role-generate); border-radius: 50%; width: 1.1rem; }
.ludi-strip__step[data-role="decide"] { background: var(--ludi-role-decide); }
.ludi-strip__step[data-role="facilitate"] { background: var(--ludi-role-facilitate); border-radius: 0.55rem 0.55rem 3px 3px; }
.ludi-strip--linked .ludi-strip__step + .ludi-strip__step::before {
  content: "";
  position: absolute;
  right: 100%;
  top: 50%;
  width: 6px;
  height: 2px;
  background: var(--ludi-color-text);
}
.ludi-strip--loose { gap: var(--ludi-space-6); }

/* Playhead: the steps hop in order the first time a row is in view and again on hover or
   keyboard focus (Home/Index inline script toggles .is-playing). */
.ludi-format.is-playing .ludi-strip__step {
  animation: ludi-hop 420ms cubic-bezier(0.3, 1.6, 0.5, 1) both;
  animation-delay: calc(var(--i) * 65ms);
}
@keyframes ludi-hop {
  0% { transform: none; }
  40% { transform: translateY(-9px) scale(1.18); }
  100% { transform: none; }
}
.ludi-format { transition: background-color var(--ludi-duration-base) var(--ludi-ease-out); }
.ludi-format:hover, .ludi-format:focus-within { background: color-mix(in srgb, var(--ludi-color-surface) 70%, transparent); }
@media (prefers-reduced-motion: reduce) {
  .ludi-format.is-playing .ludi-strip__step { animation: none; }
}

@media (min-width: 64rem) {
  .ludi-format {
    grid-template-columns: 15rem minmax(0, 1fr) 15rem;
    grid-template-areas:
      "name strip link"
      "name desc  link";
    column-gap: var(--ludi-space-7);
    row-gap: var(--ludi-space-3);
    padding-block: var(--ludi-space-7);
    align-items: start;
  }
  .ludi-format__name { grid-area: name; }
  .ludi-format .ludi-strip { grid-area: strip; padding-top: 0.55rem; }
  .ludi-format__desc { grid-area: desc; }
  .ludi-format .ludi-link { grid-area: link; justify-self: end; padding-top: 0.35rem; text-align: right; }
}

/* Dates teaser (the page itself: css/ludi/dates-landing.css). */
.ludi-datesband { padding-top: 0; }
.ludi-datesband__grid { display: grid; gap: var(--ludi-space-7); align-items: center; }
.ludi-datesband__copy { display: grid; gap: var(--ludi-space-5); justify-items: start; }
.ludi-datesband__screen { padding: 0.6rem; border-radius: var(--ludi-radius-md); }
.ludi-datesband__screen img { width: 100%; height: auto; aspect-ratio: 16 / 9; border-radius: var(--ludi-radius-xs); background: var(--ludi-device-screen-empty); }
@media (min-width: 64rem) {
  .ludi-datesband__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); gap: var(--ludi-space-9); }
}

/* 5d. Gallery --------------------------------------------------------- */

.ludi-gallery__head {
  max-width: none;
  align-items: end;
}
.ludi-gallery__head > div { display: grid; gap: var(--ludi-space-3); }
@media (min-width: 48rem) {
  .ludi-gallery__head { grid-template-columns: minmax(0, 1fr) auto; gap: var(--ludi-space-6); }
}

.ludi-clipgrid {
  display: grid;
  gap: var(--ludi-space-7) var(--ludi-space-6);
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 40rem) { .ludi-clipgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 64rem) { .ludi-clipgrid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.ludi-clipcard { display: grid; gap: var(--ludi-space-4); align-content: start; }
.ludi-clipcard .ludi-device__host { box-shadow: inset 0 0 0 1px var(--ludi-device-bezel-edge), 0 18px 40px -22px rgb(0 0 0 / 0.8); }
.ludi-clipcard__text { display: grid; gap: var(--ludi-space-1); }
.ludi-clipcard__title {
  font-family: var(--ludi-font-display);
  font-weight: var(--ludi-weight-semibold);
  font-size: var(--ludi-text-lg);
  line-height: var(--ludi-leading-snug);
  order: -1;
}
.ludi-clipcard__tagline { color: var(--ludi-color-text-muted); font-size: var(--ludi-text-sm); max-width: 44ch; }
.ludi-clipcard .ludi-role { font-size: var(--ludi-text-xs); margin-top: var(--ludi-space-1); }

/* The whole teaser is the link to the interaction page; the clip's pause button stays
   clickable above the link's hit area. */
.ludi-clipcard { position: relative; }
.ludi-clipcard__link { color: inherit; text-decoration: none; }
.ludi-clipcard__link::after { content: ""; position: absolute; z-index: 2; inset: 0; }
.ludi-clipcard .ludi-device { z-index: 3; pointer-events: none; transition: transform var(--ludi-duration-base) cubic-bezier(0.3, 1.4, 0.5, 1); }
.ludi-clipcard .ludi-device__toggle { pointer-events: auto; }
.ludi-clipcard:hover .ludi-device,
.ludi-clipcard:focus-within .ludi-device { transform: translateY(-5px) rotate(-0.4deg); }
.ludi-clipcard:hover .ludi-device__host,
.ludi-clipcard:focus-within .ludi-device__host { box-shadow: inset 0 0 0 1px var(--ludi-device-bezel-edge), 7px 7px 0 var(--role); }
.ludi-clipcard:hover .ludi-clipcard__link { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 0.2em; text-decoration-color: var(--role); }
@supports selector(:has(*)) {
  .ludi-clipcard__link:focus-visible { outline: none; }
  .ludi-clipcard:has(.ludi-clipcard__link:focus-visible) { outline: 3px solid var(--ludi-color-focus); outline-offset: 10px; border-radius: var(--ludi-radius-sm); }
}
@media (prefers-reduced-motion: reduce) {
  .ludi-clipcard .ludi-device { transition: none; }
  .ludi-clipcard:hover .ludi-device, .ludi-clipcard:focus-within .ludi-device { transform: none; }
}

/* 5e. Waitlist -------------------------------------------------------- */

.ludi-waitlist__grid { display: grid; gap: var(--ludi-space-7); align-items: start; }
.ludi-waitlist__copy { display: grid; gap: var(--ludi-space-4); }
.ludi-waitlist__contact { color: var(--ludi-color-text-muted); padding-top: var(--ludi-space-2); }

.ludi-waitlist__panel {
  display: grid;
  gap: var(--ludi-space-4);
  padding: clamp(1.25rem, 0.75rem + 2vw, 2.25rem);
  border: 1px solid var(--ludi-color-line-strong);
  border-radius: var(--ludi-radius-md);
  background: var(--ludi-color-surface);
  box-shadow: 6px 6px 0 var(--ludi-color-line);
}
.ludi-waitlist__app { justify-self: start; }
.ludi-form__note { font-size: var(--ludi-text-sm); color: var(--ludi-color-text-muted); }
.ludi-form__note .ludi-link { font-weight: var(--ludi-weight-semibold); }
/* reCAPTCHA v3 floating badge: replaced by the text notice under the waitlist form
   (allowed by Google's reCAPTCHA FAQ). It covered content on phones. */
.ludi-site .grecaptcha-badge { visibility: hidden; }

@media (min-width: 64rem) {
  .ludi-waitlist__grid { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); gap: var(--ludi-space-9); }
}

.ludi-form { display: grid; gap: var(--ludi-space-5); }
.ludi-field { display: grid; gap: var(--ludi-space-2); }
.ludi-field__label { font-weight: var(--ludi-weight-bold); font-size: var(--ludi-text-sm); }
.ludi-field__hint { font-weight: var(--ludi-weight-regular); color: var(--ludi-color-text-muted); }

.ludi-input {
  width: 100%;
  min-height: 3rem;
  padding: 0.65rem 0.9rem;
  border: 1.5px solid var(--ludi-color-line-strong);
  border-radius: var(--ludi-radius-sm);
  background: var(--ludi-color-surface);
  color: var(--ludi-color-text);
  transition: border-color var(--ludi-duration-fast) var(--ludi-ease-out);
}
.ludi-input:hover { border-color: var(--ludi-color-text-subtle); }
.ludi-input:focus-visible { outline-offset: 1px; border-color: var(--ludi-color-focus); }

.ludi-alert {
  padding: var(--ludi-space-3) var(--ludi-space-4);
  border-radius: var(--ludi-radius-sm);
  font-weight: var(--ludi-weight-semibold);
}
.ludi-alert--success { background: var(--ludi-color-success-bg); color: var(--ludi-color-success-text); }
.ludi-alert--error { background: var(--ludi-color-danger-bg); color: var(--ludi-color-danger-text); }

/* 6. Interactions gallery and pages -----------------------------------
   Views/Showcase/*, js/ludi/showcase.js. The playful part is the table:
   clip cards are dealt in, rest slightly askew, straighten and lift when
   picked up, and wear their role as a game token. Everything else is quiet. */

/* Role variables. Zero specificity, custom properties only, so any element
   with data-role (and its children) can paint itself in its role. The
   shape vocabulary matches .ludi-role and .ludi-strip: capture = square,
   generate = circle, decide = diamond, facilitate = arch. */
:where([data-role]) {
  --role: var(--ludi-role-capture);
  --role-text: var(--ludi-role-capture-text);
  --shape-radius: 3px;
  --shape-rotate: 0deg;
  --shape-scale: 1;
}
:where([data-role="generate"]) { --role: var(--ludi-role-generate); --role-text: var(--ludi-role-generate-text); --shape-radius: 50%; }
:where([data-role="decide"]) { --role: var(--ludi-role-decide); --role-text: var(--ludi-role-decide-text); --shape-rotate: 45deg; --shape-scale: 0.8; }
:where([data-role="facilitate"]) { --role: var(--ludi-role-facilitate); --role-text: var(--ludi-role-facilitate-text); --shape-radius: 50% 50% 3px 3px; }
:where([data-role="other"]) { --role: var(--ludi-chalk-300); --role-text: var(--ludi-color-text-muted); --shape-radius: 30%; }

.ludi-shape {
  display: inline-block;
  flex: none;
  width: 1em;
  height: 1em;
  background: var(--role);
  border-radius: var(--shape-radius);
  transform: rotate(var(--shape-rotate)) scale(var(--shape-scale));
}
.ludi-shape--lg { width: 1.1em; height: 1.1em; }
.ludi-shape--xl { width: 2.75rem; height: 2.75rem; }

.ludi-pagetitle {
  font-family: var(--ludi-font-display);
  font-weight: var(--ludi-weight-bold);
  font-size: var(--ludi-text-3xl);
  line-height: var(--ludi-leading-tight);
  letter-spacing: var(--ludi-tracking-display);
  text-wrap: balance;
}

.ludi-aichip {
  display: inline-flex;
  align-items: center;
  padding: 0.1rem 0.55rem;
  border: 1.5px solid var(--ludi-color-line-strong);
  border-radius: var(--ludi-radius-pill);
  color: var(--ludi-color-text-muted);
  font-size: var(--ludi-text-xs);
  font-weight: var(--ludi-weight-bold);
  line-height: 1.4;
  white-space: nowrap;
}

/* 6a. Gallery intro and role filter ----------------------------------- */

.ludi-gx-intro { padding-block: var(--ludi-space-8) var(--ludi-space-7); }
.ludi-gx-intro__copy { display: grid; gap: var(--ludi-space-4); max-width: 46rem; }

.ludi-rolefilter {
  display: grid;
  gap: var(--ludi-space-4);
  margin-top: var(--ludi-space-7);
}

.ludi-rolefilter__list {
  display: grid;
  gap: var(--ludi-space-3);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.ludi-rolefilter__list > li:first-child { grid-column: 1 / -1; }

.ludi-rolefilter__opt {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas:
    "shape name"
    "shape count";
  column-gap: var(--ludi-space-3);
  align-items: center;
  height: 100%;
  padding: var(--ludi-space-3) var(--ludi-space-4);
  border: 1.5px solid var(--ludi-color-line-strong);
  border-radius: var(--ludi-radius-md);
  background: var(--ludi-color-surface);
  color: var(--ludi-color-text);
  text-decoration: none;
  transition: border-color var(--ludi-duration-base) var(--ludi-ease-out),
              box-shadow var(--ludi-duration-base) var(--ludi-ease-out),
              transform var(--ludi-duration-base) var(--ludi-ease-out);
}
.ludi-rolefilter__shapes { grid-area: shape; display: inline-flex; gap: 3px; font-size: 1.1rem; }
.ludi-rolefilter__opt[data-role] .ludi-rolefilter__shapes { font-size: 1.6rem; }
.ludi-rolefilter__shapes .ludi-shape { transition: transform var(--ludi-duration-slow) cubic-bezier(0.3, 1.6, 0.5, 1); }
.ludi-rolefilter__name {
  grid-area: name;
  font-family: var(--ludi-font-display);
  font-weight: var(--ludi-weight-bold);
  font-size: var(--ludi-text-md);
  line-height: 1.2;
}
.ludi-rolefilter__count { grid-area: count; font-size: var(--ludi-text-xs); color: var(--ludi-color-text-muted); }
.ludi-rolefilter__def { display: none; }

.ludi-rolefilter__opt:hover { border-color: var(--ludi-color-text); }
.ludi-rolefilter__opt:hover .ludi-shape { transform: rotate(calc(var(--shape-rotate) + 90deg)) scale(var(--shape-scale)); }
.ludi-rolefilter__opt[aria-current="true"] {
  border-color: var(--ludi-color-text);
  background: color-mix(in srgb, var(--role, var(--ludi-chalk-300)) 16%, var(--ludi-color-surface));
  box-shadow: 4px 4px 0 var(--role, var(--ludi-color-text));
  transform: translate(-2px, -2px);
}
.ludi-rolefilter__opt[data-filter="all"][aria-current="true"] {
  background: var(--ludi-color-surface);
  box-shadow: 4px 4px 0 var(--ludi-color-text);
}

@media (min-width: 64rem) {
  .ludi-rolefilter__list { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .ludi-rolefilter__list > li:first-child { grid-column: auto; }
  .ludi-rolefilter__opt {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "shape count"
      "name name"
      "def def";
    row-gap: var(--ludi-space-2);
    align-content: start;
    align-items: start;
    padding: var(--ludi-space-4) var(--ludi-space-4) var(--ludi-space-5);
  }
  .ludi-rolefilter__shapes { min-height: 1.6rem; align-items: center; }
  .ludi-rolefilter__name { font-size: var(--ludi-text-lg); padding-top: var(--ludi-space-2); }
  .ludi-rolefilter__def { display: block; grid-area: def; font-size: var(--ludi-text-sm); color: var(--ludi-color-text-muted); line-height: 1.45; }
}

/* "Only those that use AI" switch (revealed by showcase.js). */
.ludi-switch {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--ludi-space-3);
  justify-self: start;
  min-height: 2.75rem;
  font-weight: var(--ludi-weight-semibold);
  cursor: pointer;
}
/* Revealed by showcase.js; the space is kept so the grid below does not shift (CLS). */
.ludi-switch[hidden] { display: inline-flex; visibility: hidden; }
.ludi-switch__input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.ludi-switch__track {
  position: relative;
  flex: none;
  width: 2.9rem;
  height: 1.65rem;
  border: 2px solid var(--ludi-color-text);
  border-radius: var(--ludi-radius-pill);
  background: var(--ludi-color-surface);
  transition: background-color var(--ludi-duration-base) var(--ludi-ease-out);
}
.ludi-switch__thumb {
  position: absolute;
  top: 50%;
  left: 3px;
  width: 1.05rem;
  height: 1.05rem;
  border-radius: 50%;
  background: var(--ludi-color-text);
  transform: translateY(-50%);
  transition: transform var(--ludi-duration-base) cubic-bezier(0.3, 1.5, 0.5, 1), background-color var(--ludi-duration-base);
}
.ludi-switch__input:checked + .ludi-switch__track { background: var(--ludi-color-text); }
.ludi-switch__input:checked + .ludi-switch__track .ludi-switch__thumb {
  transform: translate(1.2rem, -50%);
  background: var(--ludi-role-generate);
}
.ludi-switch__input:focus-visible + .ludi-switch__track { outline: 3px solid var(--ludi-color-focus); outline-offset: 3px; }
.ludi-switch__count { color: var(--ludi-color-text-muted); font-weight: var(--ludi-weight-regular); }

/* 6b. The table: role sections and clip cards ------------------------- */

.ludi-gx-room { padding-block: var(--ludi-space-8) var(--ludi-section-pad); }
.ludi-gx-room:focus { outline: none; }
.ludi-gx-empty { max-width: var(--ludi-measure); color: var(--ludi-color-text-muted); font-size: var(--ludi-text-lg); }

.ludi-gx-group { scroll-margin-top: var(--ludi-space-5); }
.ludi-gx-group:focus { outline: none; }
.ludi-gx-group + .ludi-gx-group { margin-top: var(--ludi-space-9); }
.ludi-gx-group[hidden] { display: none; }

.ludi-gx-group__head {
  display: grid;
  gap: var(--ludi-space-2);
  margin-bottom: var(--ludi-space-6);
  padding-bottom: var(--ludi-space-4);
  border-bottom: 1px solid var(--ludi-color-line);
}
.ludi-gx-group__title {
  display: flex;
  align-items: center;
  gap: 0.55em;
  font-family: var(--ludi-font-display);
  font-weight: var(--ludi-weight-bold);
  font-size: var(--ludi-text-2xl);
  line-height: var(--ludi-leading-snug);
  letter-spacing: var(--ludi-tracking-display);
}
.ludi-gx-group__title .ludi-shape { width: 0.75em; height: 0.75em; }
.ludi-gx-group__def { color: var(--ludi-color-text-muted); max-width: var(--ludi-measure); }
.ludi-gx-group__empty { color: var(--ludi-color-text-muted); }
.ludi-gx-group__empty[hidden] { display: none; }
@media (min-width: 48rem) {
  .ludi-gx-group__head { grid-template-columns: auto minmax(0, 1fr); align-items: baseline; column-gap: var(--ludi-space-6); }
  .ludi-gx-group__def { justify-self: end; text-align: right; max-width: 44ch; }
}

.ludi-cardgrid {
  display: grid;
  gap: var(--ludi-space-7) var(--ludi-space-6);
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 40rem) { .ludi-cardgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 64rem) { .ludi-cardgrid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.ludi-card {
  --tilt: -0.6deg;
  --deal-x: -36px;
  --deal-r: -10deg;
  position: relative;
  display: grid;
  gap: var(--ludi-space-4);
  align-content: start;
}
.ludi-card[hidden] { display: none; }
.ludi-card:nth-child(3n+2) { --tilt: 0.5deg; --deal-x: 24px; --deal-r: 7deg; }
.ludi-card:nth-child(3n) { --tilt: -0.25deg; --deal-x: 40px; --deal-r: 12deg; }

/* The clip is the hero of the card: it rests askew on the table and
   straightens, lifts and casts a role-coloured shadow when picked up. */
.ludi-card__media {
  transform: rotate(var(--tilt));
  transition: transform var(--ludi-duration-base) cubic-bezier(0.3, 1.4, 0.5, 1);
}
.ludi-card__media .ludi-device__host {
  box-shadow: inset 0 0 0 1px var(--ludi-device-bezel-edge), 0 18px 40px -22px rgb(0 0 0 / 0.8);
  transition: box-shadow var(--ludi-duration-base) var(--ludi-ease-out);
}
.ludi-card:hover .ludi-card__media,
.ludi-card:focus-within .ludi-card__media { transform: rotate(0deg) translateY(-6px); }
.ludi-card:hover .ludi-device__host,
.ludi-card:focus-within .ludi-device__host {
  box-shadow: inset 0 0 0 1px var(--ludi-device-bezel-edge), 7px 7px 0 var(--role);
}

.ludi-card__poster,
.ludi-card__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.ludi-card__video {
  opacity: 0;
  transition: opacity var(--ludi-duration-base) var(--ludi-ease-out);
}
.ludi-card__media.is-playing .ludi-card__video { opacity: 1; }

/* No poster yet: the screen shows the role's shape, large and faint. */
.ludi-card__placeholder {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
}
.ludi-card__placeholder::before {
  content: "";
  width: 22%;
  aspect-ratio: 1;
  background: color-mix(in srgb, var(--role) 55%, transparent);
  border-radius: var(--shape-radius);
  transform: rotate(var(--shape-rotate)) scale(var(--shape-scale));
}

/* The game token pinned to the screen's corner. */
.ludi-card__token {
  position: absolute;
  z-index: 1;
  top: -0.55rem;
  left: -0.55rem;
  width: 1.7rem;
  height: 1.7rem;
  background: var(--role);
  border-radius: var(--shape-radius);
  box-shadow: 0 0 0 4px var(--ludi-color-bg);
  transform: rotate(var(--shape-rotate)) scale(var(--shape-scale));
  transition: transform var(--ludi-duration-slow) cubic-bezier(0.3, 1.6, 0.5, 1);
}
.ludi-card:hover .ludi-card__token,
.ludi-card:focus-within .ludi-card__token {
  transform: rotate(calc(var(--shape-rotate) + 90deg)) scale(calc(var(--shape-scale) * 1.15));
}

.ludi-card__text { display: grid; gap: var(--ludi-space-2); }
.ludi-card__kicker { font-size: var(--ludi-text-xs); color: var(--ludi-color-text-muted); }
.ludi-card__title {
  font-family: var(--ludi-font-display);
  font-weight: var(--ludi-weight-semibold);
  font-size: var(--ludi-text-lg);
  line-height: var(--ludi-leading-snug);
}
.ludi-card__link { color: inherit; text-decoration: none; }
/* The whole card is the link's hit area. */
.ludi-card__link::after { content: ""; position: absolute; z-index: 2; inset: 0; }
.ludi-card:hover .ludi-card__link { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 0.2em; text-decoration-color: var(--role); }
.ludi-card__tagline {
  color: var(--ludi-color-text-muted);
  font-size: var(--ludi-text-sm);
  max-width: 48ch;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}
.ludi-card__meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ludi-space-2) var(--ludi-space-3); }
.ludi-card__meta .ludi-role { font-size: var(--ludi-text-xs); }

@supports selector(:has(*)) {
  .ludi-card__link:focus-visible { outline: none; }
  .ludi-card:has(.ludi-card__link:focus-visible) {
    outline: 3px solid var(--ludi-color-focus);
    outline-offset: 10px;
    border-radius: var(--ludi-radius-sm);
  }
}

/* Deal-in. html.ludi-deal is set by the gallery's head script (never under
   reduced motion); showcase.js adds .is-dealt when a grid reaches the view
   and sets --d, the card's place in the deal. */
.ludi-deal .ludi-cardgrid:not(.is-dealt) > .ludi-card { opacity: 0; }
.ludi-deal .ludi-cardgrid.is-dealt > .ludi-card {
  animation: ludi-deal 560ms cubic-bezier(0.2, 1.25, 0.35, 1) both;
  animation-delay: calc(min(var(--d, 0), 11) * 55ms);
}
@keyframes ludi-deal {
  0% { opacity: 0; transform: translate3d(var(--deal-x), -56px, 0) rotate(var(--deal-r)) scale(0.9); }
  45% { opacity: 1; }
  100% { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .ludi-deal .ludi-cardgrid > .ludi-card { opacity: 1; animation: none; }
  .ludi-card__media, .ludi-card__token, .ludi-rolefilter__shapes .ludi-shape { transition: none; }
  .ludi-card:hover .ludi-card__token, .ludi-card:focus-within .ludi-card__token,
  .ludi-rolefilter__opt:hover .ludi-shape { transform: rotate(var(--shape-rotate)) scale(var(--shape-scale)); }
}

/* 6c. "These chain into a workshop" band ------------------------------ */

.ludi-chainband { background: var(--ludi-color-bg); }
.ludi-chainband__grid { display: grid; gap: var(--ludi-space-7); align-items: center; }
.ludi-chainband__copy { display: grid; gap: var(--ludi-space-4); justify-items: start; }
.ludi-chainband__copy .ludi-btn { margin-top: var(--ludi-space-2); }
.ludi-chainband__figure { margin: 0; }

.ludi-chainstrip {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--ludi-space-3);
}
/* The wire the output travels along. */
.ludi-chainstrip::before {
  content: "";
  position: absolute;
  top: calc(1.375rem - 1px);
  left: 12.5%;
  right: 12.5%;
  height: 2px;
  background: repeating-linear-gradient(to right, var(--ludi-color-text) 0 8px, transparent 8px 14px);
  animation: ludi-wire-h 1.4s linear infinite;
}
.ludi-chainstrip__step {
  position: relative;
  display: grid;
  justify-items: center;
  gap: var(--ludi-space-3);
  text-align: center;
}
.ludi-chainstrip__step .ludi-shape {
  box-shadow: 0 0 0 6px var(--ludi-color-bg);
}
.ludi-chainstrip__name {
  font-size: var(--ludi-text-xs);
  font-weight: var(--ludi-weight-bold);
  color: var(--role-text);
  line-height: 1.3;
}
@media (min-width: 64rem) {
  .ludi-chainband__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--ludi-space-9); }
  .ludi-chainstrip .ludi-shape--xl { width: 3.5rem; height: 3.5rem; }
  .ludi-chainstrip::before { top: calc(1.75rem - 1px); }
  .ludi-chainstrip__name { font-size: var(--ludi-text-sm); }
}
@media (prefers-reduced-motion: reduce) {
  .ludi-chainstrip::before { animation: none; }
}

/* 6d. Interaction page: stage, clip, synced steps --------------------- */

.ludi-ix__stage {
  padding-block: var(--ludi-space-5) var(--ludi-space-8);
  background:
    radial-gradient(ellipse 60% 50% at 30% 65%, color-mix(in srgb, var(--role) 14%, transparent), transparent 70%),
    var(--ludi-color-bg);
}

.ludi-backlink {
  display: inline-flex;
  align-items: center;
  gap: var(--ludi-space-2);
  min-height: 2.75rem;
  color: var(--ludi-color-text-muted);
  font-size: var(--ludi-text-sm);
  font-weight: var(--ludi-weight-semibold);
  text-decoration: none;
}
.ludi-backlink:hover { color: var(--ludi-color-text); }
.ludi-backlink svg { transition: transform var(--ludi-duration-base) var(--ludi-ease-out); }
.ludi-backlink:hover svg { transform: translateX(-3px); }

.ludi-ix__head {
  display: grid;
  gap: var(--ludi-space-3);
  max-width: 50rem;
  margin-block: var(--ludi-space-5) var(--ludi-space-7);
}
.ludi-ix__head .ludi-role { color: var(--role-text); }
.ludi-ix__title {
  font-family: var(--ludi-font-display);
  font-weight: var(--ludi-weight-bold);
  font-size: var(--ludi-text-3xl);
  line-height: var(--ludi-leading-tight);
  letter-spacing: var(--ludi-tracking-display);
  text-wrap: balance;
}
.ludi-ix__tagline {
  font-size: var(--ludi-text-lg);
  line-height: 1.5;
  color: var(--ludi-color-text-muted);
  max-width: 58ch;
  text-wrap: pretty;
}
.ludi-ix__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ludi-space-2);
  padding-top: var(--ludi-space-2);
}
.ludi-ix__meta > li {
  display: inline-flex;
  align-items: center;
  padding: 0.2rem 0.75rem;
  border: 1.5px solid var(--ludi-color-line-strong);
  border-radius: var(--ludi-radius-pill);
  font-size: var(--ludi-text-xs);
  font-weight: var(--ludi-weight-semibold);
  color: var(--ludi-color-text-muted);
}
.ludi-ix__meta > li.ludi-ix__meta-ai { padding: 0; border: 0; }
.ludi-ix__meta .ludi-aichip { padding: 0.2rem 0.75rem; border-color: var(--ludi-role-generate); color: var(--ludi-role-generate-text); }

.ludi-ix__player { display: grid; gap: var(--ludi-space-7); align-items: start; }
.ludi-ix__clip { display: grid; gap: var(--ludi-space-3); min-width: 0; }
.ludi-ix__missing { font-size: var(--ludi-text-sm); color: var(--ludi-color-text-muted); }

@media (min-width: 64rem) {
  .ludi-ix__player { grid-template-columns: minmax(0, 1.7fr) minmax(17rem, 1fr); gap: var(--ludi-space-8); }
  .ludi-ix__player--device .ludi-steps { padding-top: var(--ludi-space-4); }
}

.ludi-steps { display: grid; gap: var(--ludi-space-3); }
.ludi-steps__title {
  font-family: var(--ludi-font-display);
  font-weight: var(--ludi-weight-semibold);
  font-size: var(--ludi-text-xl);
  line-height: var(--ludi-leading-snug);
}
.ludi-steps__hint { font-size: var(--ludi-text-sm); color: var(--ludi-color-text-muted); }
.ludi-steps__hint[hidden] { display: block; visibility: hidden; } /* space kept: no layout shift on reveal */

.ludi-steps__list {
  --node: 1.05rem;
  position: relative;
  display: grid;
  margin-top: var(--ludi-space-2);
  counter-reset: none;
}
/* the wire between the nodes */
.ludi-steps__list::before {
  content: "";
  position: absolute;
  left: calc(0.75rem + var(--node) / 2 - 1px);
  top: 1.5rem;
  bottom: 1.5rem;
  width: 2px;
  background: repeating-linear-gradient(to bottom, var(--ludi-color-line-strong) 0 6px, transparent 6px 11px);
}

.ludi-steps__item { position: relative; }
.ludi-steps__btn,
.ludi-steps__list:not(.is-synced) .ludi-steps__item {
  position: relative;
  display: grid;
  grid-template-columns: var(--node) minmax(0, 1fr);
  column-gap: var(--ludi-space-4);
  align-items: start;
  width: 100%;
  padding: var(--ludi-space-3) var(--ludi-space-3) var(--ludi-space-3) 0.75rem;
  text-align: left;
}
.ludi-steps__btn {
  border: 0;
  border-radius: var(--ludi-radius-sm);
  background: transparent;
  color: inherit;
  cursor: pointer;
  transition: background-color var(--ludi-duration-fast) var(--ludi-ease-out);
}
.ludi-steps__btn:hover { background: color-mix(in srgb, var(--ludi-color-text) 6%, transparent); }

.ludi-steps__node {
  position: relative;
  z-index: 1;
  width: var(--node);
  height: var(--node);
  margin-top: 0.2rem;
  border-radius: var(--shape-radius);
  background: var(--ludi-color-bg);
  box-shadow: inset 0 0 0 2px var(--role), 0 0 0 4px var(--ludi-color-bg);
  transform: rotate(var(--shape-rotate)) scale(var(--shape-scale));
  transition: transform var(--ludi-duration-base) cubic-bezier(0.3, 1.6, 0.5, 1), background-color var(--ludi-duration-base);
}
.ludi-steps__body { display: grid; gap: 0.1rem; }
.ludi-steps__clock {
  font-size: var(--ludi-text-xs);
  font-weight: var(--ludi-weight-bold);
  color: var(--ludi-color-text-subtle);
  font-variant-numeric: tabular-nums;
}
.ludi-steps__text { color: var(--ludi-color-text-muted); line-height: 1.4; transition: color var(--ludi-duration-base); }

.ludi-steps__bar {
  position: absolute;
  left: calc(0.75rem + var(--node) + var(--ludi-space-4));
  right: var(--ludi-space-3);
  bottom: 0.3rem;
  height: 3px;
  border-radius: var(--ludi-radius-pill);
  background: var(--role);
  transform: scaleX(var(--p, 0));
  transform-origin: left center;
  opacity: 0;
}

.ludi-steps__item.is-past .ludi-steps__node { background: color-mix(in srgb, var(--role) 45%, var(--ludi-color-bg)); }
.ludi-steps__item.is-current .ludi-steps__node {
  background: var(--role);
  transform: rotate(var(--shape-rotate)) scale(calc(var(--shape-scale) * 1.3));
}
.ludi-steps__item.is-current .ludi-steps__text { color: var(--ludi-color-text); font-weight: var(--ludi-weight-semibold); }
.ludi-steps__item.is-current .ludi-steps__clock { color: var(--role-text); }
.is-live .ludi-steps__item.is-current .ludi-steps__bar { opacity: 1; }

/* 6e. What goes in, what comes out ------------------------------------ */

.ludi-io { background: var(--ludi-color-bg); }
.ludi-io .ludi-h2 { margin-bottom: var(--ludi-space-6); }
.ludi-io__flow {
  position: relative;
  display: grid;
  gap: var(--ludi-space-5);
  justify-items: stretch;
}
.ludi-io__cell {
  display: grid;
  gap: var(--ludi-space-2);
  align-content: start;
  padding: var(--ludi-space-5);
  border: 1.5px solid var(--ludi-color-text);
  border-radius: var(--ludi-radius-md);
  background: var(--ludi-color-surface);
  box-shadow: 5px 5px 0 var(--ludi-color-line-strong);
}
.ludi-io__cell--out { box-shadow: 5px 5px 0 var(--role); }
.ludi-io__label { font-size: var(--ludi-text-sm); font-weight: var(--ludi-weight-bold); color: var(--ludi-color-text-muted); }
.ludi-io__text {
  font-family: var(--ludi-font-display);
  font-weight: var(--ludi-weight-semibold);
  font-size: var(--ludi-text-xl);
  line-height: var(--ludi-leading-snug);
  letter-spacing: var(--ludi-tracking-tight);
  text-wrap: pretty;
}
/* The interaction itself sits between input and output, on the wire. */
.ludi-io__machine {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 3.5rem;
}
.ludi-io__machine::before {
  content: "";
  position: absolute;
  top: calc(-1 * var(--ludi-space-5));
  bottom: calc(-1 * var(--ludi-space-5));
  left: calc(50% - 1px);
  width: 2px;
  background: repeating-linear-gradient(to bottom, var(--ludi-color-text) 0 8px, transparent 8px 14px);
  animation: ludi-wire-v 1.4s linear infinite;
}
.ludi-io__machine .ludi-shape { position: relative; box-shadow: 0 0 0 8px var(--ludi-color-bg); }
.ludi-io__feeds { margin-top: var(--ludi-space-6); color: var(--ludi-color-text-muted); max-width: var(--ludi-measure); }

@media (min-width: 48rem) {
  .ludi-io__flow { grid-template-columns: minmax(0, 1fr) 6rem minmax(0, 1fr); align-items: stretch; gap: 0; }
  .ludi-io__machine::before {
    top: calc(50% - 1px);
    bottom: auto;
    left: 0;
    right: 0;
    width: auto;
    height: 2px;
    background: repeating-linear-gradient(to right, var(--ludi-color-text) 0 8px, transparent 8px 14px);
    animation-name: ludi-wire-h;
  }
}
@media (prefers-reduced-motion: reduce) {
  .ludi-io__machine::before { animation: none; }
}

/* 6f. Pairs well with, prev / next, CTA, not found -------------------- */

.ludi-pairs__head { max-width: none; align-items: end; }
.ludi-pairs__head > div { display: grid; gap: var(--ludi-space-3); }
@media (min-width: 48rem) {
  .ludi-pairs__head { grid-template-columns: minmax(0, 1fr) auto; gap: var(--ludi-space-6); }
}

.ludi-ixnav { border-top: 1px solid var(--ludi-color-line); border-bottom: 1px solid var(--ludi-color-line); }
.ludi-ixnav__grid { display: grid; }
.ludi-ixnav__link {
  display: grid;
  grid-template-columns: 7.5rem minmax(0, 1fr);
  gap: var(--ludi-space-4);
  align-items: center;
  padding-block: var(--ludi-space-5);
  color: var(--ludi-color-text);
  text-decoration: none;
}
.ludi-ixnav__link + .ludi-ixnav__link { border-top: 1px solid var(--ludi-color-line); }
.ludi-ixnav__thumb {
  position: relative;
  display: block;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: var(--ludi-radius-sm);
  background: var(--ludi-device-screen-empty);
  box-shadow: inset 0 0 0 4px var(--ludi-device-bezel);
  transition: transform var(--ludi-duration-base) cubic-bezier(0.3, 1.4, 0.5, 1);
}
.ludi-ixnav__thumb img { width: 100%; height: 100%; object-fit: cover; border: 4px solid var(--ludi-device-bezel); border-radius: var(--ludi-radius-sm); }
.ludi-ixnav__link:hover .ludi-ixnav__thumb { transform: rotate(-2deg) translateY(-2px); }
.ludi-ixnav__link--next:hover .ludi-ixnav__thumb { transform: rotate(2deg) translateY(-2px); }
.ludi-ixnav__text { display: grid; gap: 0.15rem; justify-items: start; }
.ludi-ixnav__dir { font-size: var(--ludi-text-xs); color: var(--ludi-color-text-muted); font-weight: var(--ludi-weight-semibold); }
.ludi-ixnav__title { font-family: var(--ludi-font-display); font-weight: var(--ludi-weight-semibold); font-size: var(--ludi-text-lg); line-height: var(--ludi-leading-snug); }
.ludi-ixnav__link:hover .ludi-ixnav__title { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 0.2em; }
.ludi-ixnav .ludi-role { font-size: var(--ludi-text-xs); }
@media (min-width: 48rem) {
  .ludi-ixnav__grid { grid-template-columns: 1fr 1fr; }
  .ludi-ixnav__link + .ludi-ixnav__link { border-top: 0; border-left: 1px solid var(--ludi-color-line); }
  .ludi-ixnav__link--prev { padding-right: var(--ludi-space-6); }
  .ludi-ixnav__link--next { grid-template-columns: minmax(0, 1fr) 7.5rem; padding-left: var(--ludi-space-6); }
  .ludi-ixnav__link--next .ludi-ixnav__thumb { order: 2; }
  .ludi-ixnav__link--next .ludi-ixnav__text { justify-items: end; text-align: right; }
}
@media (prefers-reduced-motion: reduce) {
  .ludi-ixnav__link:hover .ludi-ixnav__thumb { transform: none; }
}

.ludi-ixcta { background: var(--ludi-color-bg-sunken); }
.ludi-ixcta__grid { display: grid; gap: var(--ludi-space-6); align-items: end; }
.ludi-ixcta__copy { display: grid; gap: var(--ludi-space-4); }
.ludi-ixcta__actions { display: flex; flex-wrap: wrap; gap: var(--ludi-space-3); }
@media (min-width: 64rem) {
  .ludi-ixcta__grid { grid-template-columns: minmax(0, 1fr) auto; gap: var(--ludi-space-8); }
}

.ludi-ixmissing__grid { display: grid; gap: var(--ludi-space-7); align-items: center; }
.ludi-ixmissing__copy { display: grid; gap: var(--ludi-space-4); justify-items: start; max-width: 40rem; }
.ludi-ixmissing__cards { display: flex; gap: var(--ludi-space-4); align-items: center; }
.ludi-ixmissing__gap {
  background: transparent;
  border: 2px dashed var(--ludi-color-line-strong);
  border-radius: 50%;
}
@media (min-width: 64rem) {
  .ludi-ixmissing__grid { grid-template-columns: auto minmax(0, 1fr); gap: var(--ludi-space-9); }
}

/* 7. Privacy and other long text pages --------------------------------- */

.ludi-legal__grid { display: grid; gap: var(--ludi-space-7); }
.ludi-legal__head { display: grid; gap: var(--ludi-space-4); max-width: var(--ludi-measure); }
.ludi-legal__date { font-size: var(--ludi-text-sm); color: var(--ludi-color-text-muted); }
.ludi-legal__toc {
  align-self: start;
  padding: var(--ludi-space-5);
  border: 1.5px solid var(--ludi-color-line-strong);
  border-radius: var(--ludi-radius-md);
  background: var(--ludi-color-surface);
}
.ludi-legal__toc-title { font-family: var(--ludi-font-display); font-weight: var(--ludi-weight-bold); font-size: var(--ludi-text-md); margin-bottom: var(--ludi-space-3); }
.ludi-legal__toc ol { display: grid; gap: var(--ludi-space-2); padding-left: 1.4em; list-style: decimal; }
.ludi-legal__toc a { color: var(--ludi-color-link); text-underline-offset: 0.2em; }
.ludi-legal__body { min-width: 0; }
@media (min-width: 64rem) {
  .ludi-legal__grid { grid-template-columns: 16rem minmax(0, 1fr); column-gap: var(--ludi-space-9); }
  .ludi-legal__head { grid-column: 1 / -1; }
  .ludi-legal__toc { position: sticky; top: var(--ludi-space-5); }
}

.ludi-prose { max-width: 46rem; }
.ludi-prose section { scroll-margin-top: var(--ludi-space-5); }
.ludi-prose section + section { margin-top: var(--ludi-space-8); padding-top: var(--ludi-space-6); border-top: 1px solid var(--ludi-color-line); }
.ludi-prose h2 {
  font-family: var(--ludi-font-display);
  font-weight: var(--ludi-weight-bold);
  font-size: var(--ludi-text-xl);
  line-height: var(--ludi-leading-snug);
  margin-bottom: var(--ludi-space-4);
}
.ludi-prose h3 { font-family: var(--ludi-font-display); font-weight: var(--ludi-weight-semibold); font-size: var(--ludi-text-lg); margin: var(--ludi-space-5) 0 var(--ludi-space-3); }
.ludi-prose p, .ludi-prose ul { margin-bottom: var(--ludi-space-4); }
.ludi-prose ul { display: grid; gap: var(--ludi-space-2); padding-left: 1.25em; list-style: disc; }
.ludi-prose li::marker { color: var(--ludi-color-text-muted); }
.ludi-prose a { color: var(--ludi-color-link); font-weight: var(--ludi-weight-semibold); text-underline-offset: 0.2em; overflow-wrap: anywhere; }
.ludi-prose code { font-size: 0.88em; padding: 0.05em 0.35em; border-radius: var(--ludi-radius-xs); background: var(--ludi-color-bg-sunken); overflow-wrap: anywhere; }
.ludi-legal__note { padding: var(--ludi-space-4); border-left: 4px solid var(--ludi-role-capture); background: var(--ludi-color-bg-sunken); border-radius: 0 var(--ludi-radius-sm) var(--ludi-radius-sm) 0; }
.ludi-legal__table { overflow-x: auto; margin-bottom: var(--ludi-space-4); border: 1px solid var(--ludi-color-line-strong); border-radius: var(--ludi-radius-sm); }
.ludi-legal__table table { width: 100%; border-collapse: collapse; font-size: var(--ludi-text-sm); }
.ludi-legal__table th, .ludi-legal__table td { padding: var(--ludi-space-3); text-align: left; vertical-align: top; border-bottom: 1px solid var(--ludi-color-line); }
.ludi-legal__table thead th { background: var(--ludi-color-bg-sunken); font-weight: var(--ludi-weight-bold); }
.ludi-legal__table tbody th { font-weight: var(--ludi-weight-semibold); min-width: 9rem; }
.ludi-legal__table tr:last-child > * { border-bottom: 0; }
/* Facts the owner still has to supply. Loud on purpose. */
.ludi-tbc {
  padding: 0.05em 0.35em;
  border-radius: var(--ludi-radius-xs);
  background: var(--ludi-color-danger-bg);
  color: var(--ludi-color-danger-text);
  font-weight: var(--ludi-weight-bold);
}

/* 8. Public 404 and error page ----------------------------------------- */

.ludi-oops__code {
  font-family: var(--ludi-font-display);
  font-weight: var(--ludi-weight-bold);
  font-size: var(--ludi-text-sm);
  color: var(--ludi-color-text-muted);
  letter-spacing: 0.08em;
}
.ludi-oops__links { display: flex; flex-wrap: wrap; gap: var(--ludi-space-3); padding-top: var(--ludi-space-2); }
.ludi-oops__ref { font-size: var(--ludi-text-sm); color: var(--ludi-color-text-muted); }
.ludi-oops__ref code { overflow-wrap: anywhere; }
.ludi-oops__track { position: relative; }
.ludi-oops__track::before {
  content: "";
  position: absolute;
  z-index: -1;
  left: 1.375rem;
  right: 1.375rem;
  top: calc(50% - 1px);
  height: 2px;
  background: repeating-linear-gradient(to right, var(--ludi-color-line-strong) 0 8px, transparent 8px 14px);
}
.ludi-oops__track .ludi-ixmissing__gap { animation: ludi-gap 2.4s var(--ludi-ease-out) infinite; }
@keyframes ludi-gap { 50% { transform: scale(1.12) rotate(45deg); border-color: var(--ludi-color-text-muted); } }
.ludi-oops__track--jam .ludi-shape:nth-child(3) { transform: translateY(1.6rem) rotate(28deg) scale(0.8); }
.ludi-oops__track--jam .ludi-shape:nth-child(4) { transform: translateY(0.4rem) rotate(-12deg); }
@media (prefers-reduced-motion: reduce) {
  .ludi-oops__track .ludi-ixmissing__gap { animation: none; }
}
