/* ListoGrid coming-soon page (English and French for now). Standalone: no build step, tokens
   copied from DESIGN.md §2 (the source of truth stays client/src/index.css). Logical properties
   and the --dir multiplier are kept, so adding Persian back is a font, a button and its strings. */

@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/poppins-latin-400-normal.woff2?v=1') format('woff2');
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/poppins-latin-500-normal.woff2?v=1') format('woff2');
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/poppins-latin-600-normal.woff2?v=1') format('woff2');
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/poppins-latin-700-normal.woff2?v=1') format('woff2');
}

:root {
  --background: #f4f6fa;
  --surface: #ffffff;
  --surface-sunken: #eef1f6;
  --border: #e3e8f0;
  --control-border: #d6dce7;
  --heading: #111725;
  --body-text: #343d4f;
  --muted-foreground: #5e6779;
  --brand-ink: #0c4173;
  --brand-mark: #f5b800;
  --primary: #f5b800;
  --primary-foreground: #111725;
  --accent: #8a5a00;
  --accent-surface: #f5b80026;
  --focus: #a87600;

  /* The colour of the page comes from the covers, as it will from real thumbnails. */
  --cover-plum: #6b4f73;
  --cover-amber: #80662f;
  --cover-rose: #8a5566;
  --cover-blue: #4a5f8c;
  --cover-green: #566b53;
  --cover-slate: #635c7d;
  --cover-mix: 26%;
  --cover-glow: 46%;

  --radius-control: 8px;
  --radius-card: 12px;
  --radius-feature: 16px;

  --shadow-soft: 0 1px 2px #323a460f, 0 1px 3px #323a4614;
  --shadow-card: 0 2px 4px #323a4610, 0 6px 16px -6px #323a4626;
  --shadow-ring: 0 0 0 2px var(--background), 0 0 0 4px var(--focus);

  --dur-fast: 0.15s;
  --dur-enter: 0.35s;
  --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-smooth: cubic-bezier(0.16, 1, 0.3, 1);

  --gutter: 16px;
  --gap: 12px;
  /* 1 in LTR, -1 in RTL: a transform is not direction-aware, so sideways moves multiply by it. */
  --dir: 1;

  --font-latin: 'Poppins', system-ui, sans-serif;

  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --background: #1b2130;
    --surface: #222a39;
    --surface-sunken: #1f2635;
    --border: #2a3242;
    --control-border: #3b4559;
    --heading: #ffffff;
    --body-text: #c9cfdb;
    --muted-foreground: #8e97ab;
    --brand-ink: #c9d6ee;
    --brand-mark: #f6c23e;
  --primary: #f6c23e;
    --accent: #f6c24a;
    --accent-surface: #f6c23e1f;
    --focus: #f6c24a;
    --cover-plum: #8a6d93;
    --cover-amber: #a8873f;
    --cover-rose: #a86f82;
    --cover-blue: #6a80ad;
    --cover-green: #738a6f;
    --cover-slate: #827aa0;
    --cover-mix: 30%;
    --cover-glow: 40%;
    --shadow-soft: 0 1px 2px #00000040, 0 2px 6px #00000033;
    --shadow-card: 0 2px 6px #0000004d, 0 10px 24px -8px #00000066;
    color-scheme: dark;
  }
}
:root[data-theme='dark'] {
  --background: #1b2130;
  --surface: #222a39;
  --surface-sunken: #1f2635;
  --border: #2a3242;
  --control-border: #3b4559;
  --heading: #ffffff;
  --body-text: #c9cfdb;
  --muted-foreground: #8e97ab;
  --brand-ink: #c9d6ee;
  --brand-mark: #f6c23e;
  --primary: #f6c23e;
  --accent: #f6c24a;
  --accent-surface: #f6c23e1f;
  --focus: #f6c24a;
  --cover-plum: #8a6d93;
  --cover-amber: #a8873f;
  --cover-rose: #a86f82;
  --cover-blue: #6a80ad;
  --cover-green: #738a6f;
  --cover-slate: #827aa0;
  --cover-mix: 30%;
  --cover-glow: 40%;
  --shadow-soft: 0 1px 2px #00000040, 0 2px 6px #00000033;
  --shadow-card: 0 2px 6px #0000004d, 0 10px 24px -8px #00000066;
  color-scheme: dark;
}

[dir='rtl'] {
  --dir: -1;
}

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

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

body {
  margin: 0;
  min-block-size: 100svh;
  display: grid;
  grid-template-rows: auto 1fr auto;
  background: var(--background);
  color: var(--body-text);
  font-family: var(--font-latin);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

p,
h1,
ol,
figure {
  margin: 0;
}

button {
  font: inherit;
  color: inherit;
}

:focus-visible {
  outline: none;
  box-shadow: var(--shadow-ring);
}

/* ---- top bar ---- */

.bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  inline-size: 100%;
  max-inline-size: 1200px;
  margin-inline: auto;
  padding-block: 16px;
  padding-inline: var(--gutter);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-block-size: 44px;
  border-radius: var(--radius-control);
  color: var(--heading);
  text-decoration: none;
}
.brand svg {
  display: block;
  flex-shrink: 0;
}
.brand-name {
  font-size: 24px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.02em;
}
.brand-name .listo {
  color: var(--brand-ink);
}
.brand-name .grid {
  color: var(--brand-ink);
}

.bar-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.langs {
  display: inline-flex;
  padding: 3px;
  border: 1px solid var(--control-border);
  border-radius: var(--radius-control);
  background: var(--surface);
}
.lang,
.theme {
  min-block-size: 38px;
  padding-inline: 12px;
  border: 0;
  border-radius: 5px;
  background: transparent;
  color: var(--muted-foreground);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition:
    background-color var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out),
    transform var(--dur-fast) var(--ease-out);
}
.lang:hover,
.theme:hover {
  color: var(--heading);
}
.lang:active,
.theme:active {
  transform: scale(0.98);
}
.lang[aria-pressed='true'] {
  background: var(--surface);
  color: var(--heading);
  box-shadow: 0 1px 2px #0f141f1f, 0 0 0 1px var(--border);
}
.lang .abbr {
  display: none;
}
@media (max-width: 599.98px) {
  .bar {
    flex-wrap: nowrap;
  }
  .lang .full {
    display: none;
  }
  .lang .abbr {
    display: inline;
  }
}
.theme {
  min-block-size: 44px;
  border: 1px solid var(--control-border);
  border-radius: var(--radius-control);
  background: var(--surface);
}

/* ---- hero ----
   Phones and tablets: the title, then the cards as a band that runs off both edges, then the
   rest. `.copy` dissolves so its children can be ordered around the band. */

.hero {
  display: grid;
  align-content: start;
  gap: 20px;
  inline-size: 100%;
  max-inline-size: 1200px;
  margin-inline: auto;
  padding-block: 12px 32px;
  padding-inline: var(--gutter);
}

.copy {
  display: contents;
}
.badge {
  order: 1;
}
h1 {
  order: 2;
}
.stage {
  order: 3;
}
.lede {
  order: 4;
}
.steps {
  order: 5;
}

.badge {
  justify-self: start;
  padding-block: 2px;
  padding-inline: 12px;
  border-radius: 999px;
  background: var(--accent-surface);
  color: var(--accent);
  font-size: 13px;
  font-weight: 600;
}

h1 {
  color: var(--heading);
  font-size: clamp(28px, 9.4vw, 52px);
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -0.025em;
  text-wrap: balance;
}
h1 span {
  display: block;
}
/* The one accent on the page: the half of the sentence that is the promise. */
h1 .mine {
  display: inline-block;
  color: var(--heading);
  white-space: nowrap;
  background: linear-gradient(
    to bottom,
    transparent 56%,
    color-mix(in oklab, var(--primary) 70%, transparent) 56%,
    color-mix(in oklab, var(--primary) 70%, transparent) 92%,
    transparent 92%
  );
  padding-inline: 0.06em;
  margin-inline: -0.06em;
}

.lede {
  max-inline-size: 30rem;
  font-size: 17px;
  text-wrap: pretty;
}

/* An ordered list on purpose: the page is about putting things in order. Real list rows on a
   phone (French words are long: three in a row do not fit at 360px), one row from the tablet up. */
.steps {
  display: grid;
  padding: 0;
  list-style: none;
  counter-reset: step;
  border-block-start: 1px solid var(--control-border);
  color: var(--heading);
  font-size: 18px;
  font-weight: 500;
}
.steps li {
  display: flex;
  align-items: baseline;
  gap: 14px;
  counter-increment: step;
  padding-block: 12px;
  border-block-end: 1px solid var(--control-border);
}
.steps li::before {
  content: counter(step);
  min-inline-size: 1ch;
  color: var(--accent);
  font-size: 14px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* ---- the mosaic ---- */

/* Two rows of five, wider than the screen, the second row set half a place back so the two do
   not line up: a wall of covers seen through a window. */
.stage {
  display: grid;
  gap: 12px;
  min-inline-size: 0;
  margin-block: 4px;
  margin-inline: calc(var(--gutter) * -1);
  padding-block: 6px;
  overflow: clip;
  mask-image: linear-gradient(to right, transparent 0, #000 7%, #000 93%, transparent 100%);
}

.mosaic {
  --tile: clamp(128px, 39vw, 196px);
  display: grid;
  grid-template-columns: repeat(5, var(--tile));
  gap: var(--gap);
  inline-size: max-content;
  padding-inline: var(--gutter);
}
.mosaic > :nth-child(n + 6) {
  position: relative;
  inset-inline-start: calc((var(--tile) + var(--gap)) * -0.5);
}
.mosaic > :nth-child(n + 11) {
  display: none;
}

.tile,
.slot {
  border-radius: var(--radius-card);
}

.tile {
  display: grid;
  gap: 7px;
  padding: 6px 6px 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  box-shadow: var(--shadow-soft);
}

.slot {
  position: relative;
  border: 1px dashed color-mix(in oklab, var(--muted-foreground) 55%, transparent);
}
.slot > .tile {
  position: absolute;
  inset: -1px;
}

/* A cover out of focus: the hue of a thumbnail without saying what it is. Its radius is the
   card's minus the padding around it, so the two corners stay concentric. */
.cover {
  display: block;
  aspect-ratio: 4 / 3;
  border-radius: 6px;
  background:
    radial-gradient(
      120% 90% at 28% 24%,
      color-mix(in oklab, var(--cover) var(--cover-glow), var(--surface)) 0%,
      transparent 62%
    ),
    color-mix(in oklab, var(--cover) var(--cover-mix), var(--surface-sunken));
}
.t-plum {
  --cover: var(--cover-plum);
}
.t-amber {
  --cover: var(--cover-amber);
}
.t-rose {
  --cover: var(--cover-rose);
}
.t-blue {
  --cover: var(--cover-blue);
}
.t-green {
  --cover: var(--cover-green);
}
.t-slate {
  --cover: var(--cover-slate);
}

.line {
  display: block;
  block-size: 7px;
  margin-inline: 4px;
  inline-size: 72%;
  border-radius: 999px;
  background: var(--control-border);
}
.line.short {
  inline-size: 40%;
  background: var(--border);
}

figcaption {
  padding-inline: var(--gutter);
  color: var(--muted-foreground);
  font-size: 13px;
}

/* ---- footer ---- */

.foot {
  inline-size: 100%;
  max-inline-size: 1200px;
  margin-inline: auto;
  padding-block: 16px 24px;
  padding-inline: var(--gutter);
  color: var(--muted-foreground);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

/* ---- wider screens ---- */

@media (min-width: 600px) {
  :root {
    --gutter: 24px;
    --gap: 14px;
  }
  .hero {
    gap: 24px;
  }
  .steps {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 0;
    border-block-start: 0;
    font-size: 16px;
  }
  .steps li {
    gap: 8px;
    padding-block: 0;
    padding-inline-end: 16px;
    margin-inline-end: 16px;
    border-block-end: 0;
    border-inline-end: 1px solid var(--control-border);
  }
  .steps li:last-child {
    padding-inline-end: 0;
    margin-inline-end: 0;
    border-inline-end: 0;
  }
  .steps li::before {
    font-size: 13px;
  }
}

/* Desktop: the words on one side, the cards on the other, five across with the last column
   running off the end edge. */
@media (min-width: 960px) {
  :root {
    --gutter: 32px;
    --gap: 16px;
  }
  .hero {
    grid-template-columns: minmax(0, 6fr) minmax(0, 7fr);
    align-items: center;
    align-content: center;
    gap: 56px;
    padding-block: 32px 56px;
  }
  .copy {
    display: grid;
    justify-items: start;
    gap: 20px;
    max-inline-size: 34rem;
  }
  h1 {
    font-size: clamp(44px, 4.4vw, 56px);
    line-height: 1.16;
  }
  .lede {
    font-size: 18px;
  }
  .stage {
    gap: 14px;
    margin: 0;
    padding: 0;
    overflow: visible;
    mask-image: none;
  }
  .mosaic {
    grid-template-columns: repeat(5, minmax(0, 1fr));
    inline-size: 122%;
    padding-inline: 0;
    mask-image: linear-gradient(to right, #000 68%, transparent 98%);
  }
  [dir='rtl'] .mosaic {
    mask-image: linear-gradient(to left, #000 68%, transparent 98%);
  }
  .mosaic > :nth-child(n + 6) {
    inset-inline-start: 0;
  }
  .mosaic > :nth-child(n + 11) {
    display: grid;
  }
  .mosaic > .slot:nth-child(n + 11) {
    display: block;
  }
  figcaption {
    padding-inline: 0;
  }
}

/* ---- motion: three small ideas, all of them "this is still being arranged" ----
   1. the places arrive one after another on load (hierarchy);
   2. two pairs of neighbours trade places and trade back (the order is yours to change);
   3. one empty place gets filled, then waits (something is on its way). */

@media (prefers-reduced-motion: no-preference) {
  .mosaic > * {
    animation: arrive var(--dur-enter) var(--ease-smooth) both;
  }
  .mosaic > :nth-child(1) { animation-delay: 60ms; }
  .mosaic > :nth-child(2) { animation-delay: 110ms; }
  .mosaic > :nth-child(3) { animation-delay: 160ms; }
  .mosaic > :nth-child(4) { animation-delay: 210ms; }
  .mosaic > :nth-child(5) { animation-delay: 260ms; }
  .mosaic > :nth-child(6) { animation-delay: 310ms; }
  .mosaic > :nth-child(7) { animation-delay: 360ms; }
  .mosaic > :nth-child(8) { animation-delay: 410ms; }
  .mosaic > :nth-child(9) { animation-delay: 460ms; }
  .mosaic > :nth-child(10) { animation-delay: 510ms; }
  .mosaic > :nth-child(11) { animation-delay: 560ms; }
  .mosaic > :nth-child(12) { animation-delay: 610ms; }
  .mosaic > :nth-child(13) { animation-delay: 660ms; }
  .mosaic > :nth-child(14) { animation-delay: 710ms; }
  .mosaic > :nth-child(15) { animation-delay: 760ms; }

  .mosaic > .swap-a {
    animation:
      arrive var(--dur-enter) var(--ease-smooth) 110ms both,
      trade-forward 16s var(--ease-smooth) 2.4s infinite;
  }
  .mosaic > .swap-b {
    animation:
      arrive var(--dur-enter) var(--ease-smooth) 160ms both,
      trade-back 16s var(--ease-smooth) 2.4s infinite;
  }
  .mosaic > .swap-c {
    animation:
      arrive var(--dur-enter) var(--ease-smooth) 360ms both,
      trade-forward 16s var(--ease-smooth) 6.4s infinite;
  }
  .mosaic > .swap-d {
    animation:
      arrive var(--dur-enter) var(--ease-smooth) 410ms both,
      trade-back 16s var(--ease-smooth) 6.4s infinite;
  }
  .filling > .tile {
    animation: fill 16s var(--ease-smooth) 1.2s infinite both;
  }
}

/* 4. on phones and tablets the band drifts slowly to its other end and back (there is more). */
@media (prefers-reduced-motion: no-preference) and (max-width: 959.98px) {
  .mosaic {
    animation: drift 34s ease-in-out 1.4s infinite alternate both;
  }
}

@keyframes drift {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(calc((100vw - 100% + var(--tile) / 2) * var(--dir)));
  }
}

@keyframes arrive {
  from {
    opacity: 0;
    translate: 0 10px;
  }
  to {
    opacity: 1;
    translate: 0 0;
  }
}

/* One place sideways is the tile's own width plus the gap. The mover on top lifts a little so the
   two never read as one shape while they cross. */
@keyframes trade-forward {
  0%,
  44%,
  100% {
    transform: translateX(0) scale(1);
    box-shadow: var(--shadow-soft);
    z-index: 0;
  }
  3% {
    transform: translateX(calc((50% + var(--gap) / 2) * var(--dir))) scale(1.05);
    box-shadow: var(--shadow-card);
    z-index: 2;
  }
  6%,
  38% {
    transform: translateX(calc((100% + var(--gap)) * var(--dir))) scale(1);
    box-shadow: var(--shadow-soft);
    z-index: 0;
  }
  41% {
    transform: translateX(calc((50% + var(--gap) / 2) * var(--dir))) scale(1.05);
    box-shadow: var(--shadow-card);
    z-index: 2;
  }
}
@keyframes trade-back {
  0%,
  44%,
  100% {
    transform: translateX(0) scale(1);
  }
  3%,
  41% {
    transform: translateX(calc((-50% - var(--gap) / 2) * var(--dir))) scale(0.97);
  }
  6%,
  38% {
    transform: translateX(calc((-100% - var(--gap)) * var(--dir))) scale(1);
  }
}

@keyframes fill {
  0%,
  8% {
    opacity: 0;
    transform: scale(0.94);
  }
  12%,
  78% {
    opacity: 1;
    transform: scale(1);
  }
  84%,
  100% {
    opacity: 0;
    transform: scale(0.94);
  }
}
