/* ══════════════════════════════════════════════════════════════
   Keln — empty states.

   THE PRINCIPLE
   An empty state should teach, not apologise.

   "No wins saved yet." is a shrug. It tells the user what isn't
   there, which they can already see, and nothing about why they'd
   want it to be. Every empty surface in a product is a moment where
   the user is asking "what is this for?" — and answering with a grey
   sentence wastes the one time they'll ever ask.

   So every empty state here has four parts, in this order:
     1. a glyph        — makes it feel designed, not missing
     2. a headline     — states what belongs here
     3. one line       — why that matters, concretely
     4. an action      — the shortest path to filling it

   The action is the point. An empty state without one is decoration.

   ONE COMPONENT, EVERY SURFACE. Pipeline, wins, rewards, toolkit,
   Inception, search results. The consistency is the quality signal:
   a user who has seen one empty state understands all of them.
   ══════════════════════════════════════════════════════════════ */

.es {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--s-6);
  padding: 44px 26px;
  border-radius: var(--r-lg);
  /* A faint dashed field rather than a hard border. It reads as
     "space reserved for something" instead of "empty box", which is
     the exact difference between anticipation and absence. */
  border: 1px dashed rgba(91, 140, 255, .16);
  background:
    radial-gradient(ellipse 80% 100% at 50% 0%, rgba(91, 140, 255, .05), transparent 70%);
}

/* Inside an already-bordered card, drop the second border. */
.glass > .es,
.ds-card > .es { border: none; background: none; padding: var(--s-12) var(--s-9); }

.es__glyph {
  position: relative;
  width: 54px;
  height: 54px;
  display: grid;
  place-items: center;
  font-size: 22px;
  line-height: 1;
  border-radius: 50%;
  background: rgba(6, 10, 16, .6);
  border: 1px solid var(--border);
  color: var(--muted);
}

/* A single orbiting tick. Ties every empty state back to the orbit
   and the constellation without needing an illustration per surface. */
.es__glyph::after {
  content: "";
  position: absolute;
  inset: -7px;
  border-radius: 50%;
  border: 1px solid transparent;
  border-top-color: rgba(34, 211, 166, .45);
  animation: es-orbit 3.4s linear infinite;
}

@keyframes es-orbit { to { transform: rotate(360deg); } }

.es__title {
  font-size: 15.5px;
  font-weight: 700;
  letter-spacing: -.015em;
  color: var(--ink);
  margin: var(--s-1) 0 0;
}

.es__body {
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--muted);
  max-width: 340px;
  margin: 0;
}

.es__actions {
  display: flex;
  gap: 9px;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: var(--s-3);
}

.es__btn {
  background: linear-gradient(135deg, var(--accent), var(--accent2));
  border: none;
  color: #04121a;
  font: 800 13px var(--font);
  padding: 9px 18px;
  border-radius: 10px;
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
  transition: filter .2s, transform .2s;
}
.es__btn:hover { filter: brightness(1.1); transform: translateY(-1px); }
.es__btn:focus-visible { outline: 2px solid var(--accent2); outline-offset: 3px; }

.es__btn--ghost {
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  font-weight: 600;
}
.es__btn--ghost:hover { border-color: var(--border-hi); color: var(--ink); filter: none; }

/* A quiet footnote for the rare case where context helps but an
   action doesn't exist yet. Use sparingly — if you reach for this
   often, the surface probably needs an action instead. */
.es__note {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--dim);
  margin-top: var(--s-1);
}

/* Compact variant, for narrow columns like the dossier's transit log
   where a full-height empty state would dominate the card. */
.es--sm { padding: 26px var(--s-8); gap: 9px; }
.es--sm .es__glyph { width: 40px; height: 40px; font-size: 17px; }
.es--sm .es__title { font-size: var(--t-md); }
.es--sm .es__body { font-size: 12.5px; }

/* Locked variant. Not the same thing as empty: empty means "you
   haven't done this yet", locked means "this exists and isn't yours
   yet". Different feeling, different colour. */
.es--locked { border-color: rgba(255, 209, 102, .2); }
.es--locked .es__glyph { border-color: rgba(255, 209, 102, .3); color: var(--gold); }
.es--locked .es__glyph::after { border-top-color: rgba(255, 209, 102, .45); }
.es--locked .es__btn { background: linear-gradient(135deg, var(--gold), var(--warn)); }

@media (max-width: 560px) {
  .es { padding: var(--s-12) 18px; }
  .es__body { font-size: var(--t-base); }
}

@media (prefers-reduced-motion: reduce) {
  .es__glyph::after { animation: none; opacity: .5; }
  .es__btn:hover { transform: none; }
}
