/* OTP — показания прибора: mono, прямой угол, двойное кольцо фокуса.
   Общий для публичной зоны (base_public) и профиля (base): один и тот же
   код вводится одним и тем же контролом, а не двумя разными. */
.otp-group {
  display: flex;
  gap: var(--s-2);
}
.otp-cell {
  width: 3rem;
  height: 3.5rem;
  padding: 0;
  text-align: center;
  font-size: 1.5rem;
  font-weight: var(--fw-semibold);
  font-family: var(--font-mono);
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  transition: border-color var(--d-fast) var(--e-out), box-shadow var(--d-fast) var(--e-out),
              transform 300ms var(--e-out);
}
.otp-cell:focus {
  outline: none;
  border-color: var(--p-500);
  box-shadow: var(--sh-focus);
}
/* Центрирование — только там, где поле стоит одно на листе. В панели профиля
   оно живёт в колонке с формами и выравнивается по её левому краю. */
.otp-group.is-centered { justify-content: center; }
/* Компактный — для узкой колонки: панель email в профиле даёт 323px чистой
   ширины, полный размер (6×48 + 5×8 = 328px) вылезает за её край. */
.otp-group.is-compact { gap: var(--s-2); }
.otp-group.is-compact .otp-cell { width: 2.5rem; height: 3rem; font-size: 1.25rem; }
@media (max-width: 380px) {
  .otp-group { gap: var(--s-1); }
  .otp-cell { width: 2.5rem; height: 3rem; font-size: 1.25rem; }
}

/* Проверка кода в три фазы:
   .is-busy    — ячейки в нейтральном цвете съезжают в центр (--dx считает JS)
                 и сливаются в одну; пока ждём сервер, она пульсирует серым кольцом;
   .is-success / .is-error — только потом окраска, вспышка и значок: галочка
                 на --ok, крестик на --stop. После ошибки классы снимаются и ячейки
                 разъезжаются обратно (transform есть в базовом transition). */
.otp-group { position: relative; --tone: color-mix(in srgb, var(--text) 35%, transparent); }
.otp-group.is-success { --tone: var(--ok);   --tone-bg: var(--ok-bg); }
.otp-group.is-error   { --tone: var(--stop); --tone-bg: var(--stop-bg); }
.otp-mark {
  position: absolute;
  left: 50%; top: 50%;
  width: 1.75rem; height: 1.75rem;
  transform: translate(-50%, -50%);
  fill: none;
  stroke: var(--tone);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;   /* path pathLength="1" */
  stroke-dashoffset: 1;
  pointer-events: none;
}
.otp-group.is-busy .otp-cell {
  transform: translateX(var(--dx, 0));
  color: transparent;
  transition: transform 360ms var(--e-out), color 150ms linear,
              border-color 200ms linear, background 200ms linear;
  animation: otp-scan 800ms ease-out 360ms infinite;
}
.otp-group.is-success .otp-cell,
.otp-group.is-error .otp-cell {
  border-color: var(--tone);
  background: var(--tone-bg);
  animation: otp-flash 420ms ease-out 2;
}
.otp-group.is-success .otp-check,
.otp-group.is-error .otp-cross { animation: otp-draw 380ms var(--e-out) 250ms forwards; }
/* scan и flash — разные имена: только смена имени перезапускает анимацию. */
@keyframes otp-scan {
  0%   { box-shadow: 0 0 0 0 var(--tone); }
  100% { box-shadow: 0 0 0 10px transparent; }
}
@keyframes otp-flash {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--tone) 55%, transparent); }
  100% { box-shadow: 0 0 0 12px color-mix(in srgb, var(--tone) 0%, transparent); }
}
@keyframes otp-draw { to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) {
  .otp-cell,
  .otp-group.is-busy .otp-cell,
  .otp-group.is-success .otp-cell,
  .otp-group.is-error .otp-cell { transition: none; animation: none; }
  .otp-group.is-success .otp-check,
  .otp-group.is-error .otp-cross { animation-duration: 1ms; animation-delay: 0ms; }
}
