/* =========================================================================
   Первый экран.

   На нём лежит всё, ради чего сюда приходят: обещание, адрес контракта,
   кнопка покупки, счёт и фигура. Раньше калькулятор был отдельным
   разделом ниже, и до главного числа надо было доскроллить.

   Правило раскладки одно: **верх и низ обеих колонок сходятся**. Поэтому
   подпись живёт в полосе сделки, а не над счётом — иначе она сдвигала бы
   левую колонку вниз относительно правой, и ряд ехал бы на глаз.
   ========================================================================= */

/* ---------- полоса сделки ---------- */

/* Одна строка из трёх частей: обещание, подпись, контракт с покупкой.

   Подпись стоит посередине не для красоты, а чтобы закрыть дыру. Когда
   она сидела под заголовком, полоса делилась надвое, левая половина
   разрасталась под её ширину, и адрес контракта улетал к дальнему краю:
   на экране 1440 между заголовком и контрактом оставалось 483 пустых
   пикселя. Теперь подпись занимает это место, а контракт стоит сразу за
   ней — по-прежнему справа от обещания, но рядом, а не через полполосы. */
.dealbar {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  column-gap: clamp(1rem, 2.4vw, 2rem);
  row-gap: .7rem;
  /* Рамки у полосы больше нет.

     Их выходило три подряд: рамка полосы, рамка калькулятора и рамка
     стакана — одна под другой, и первый экран читался стопкой коробок, а
     не единым местом. Заголовок в коробке ещё и придавливал сам себя:
     подпись «based on live volume» упиралась в правый край и еле влезала.

     Теперь полоса бесшовная. Обособлен только контракт: он единственное
     здесь, что нужно выделить как отдельный предмет — по нему кликают и
     его копируют. */
  border: 0;
  background: none;
  padding: 0 0 clamp(.9rem, 2vw, 1.3rem);
  border-bottom: 1px solid color-mix(in srgb, var(--color-bone) 7%, transparent);
}

.dealbar .hh {
  font-family: var(--font-disp);
  font-weight: 900;
  font-stretch: 78%;
  letter-spacing: -.045em;
  line-height: .95;
  font-size: clamp(1.5rem, 3.6vw, 2.5rem);
  color: var(--color-bone);
}
.dealbar .hh i { font-style: normal; color: var(--color-neon); }

.dealbar .sub {
  margin: 0;
  max-width: 68ch;
  font-size: .82rem;
  line-height: 1.6;
  color: var(--color-h2c);
}

/* Контракт и покупка в строку, а не столбиком: они на одном уровне с
   заголовком, и вертикальный столбик там разогнал бы полосу по высоте. */
.dealbar .dr {
  display: flex;
  align-items: center;
  gap: .55rem;
  flex-wrap: wrap;
  justify-content: flex-end;
}

/* Адрес контракта не растягивает полосу: длинная строка обрезается
   многоточием, а не выталкивает кнопку покупки за край. */
.dealbar .ca {
  display: flex;
  align-items: center;
  gap: .5rem;
  margin: 0;
  min-width: 0;
}
.dealbar .ca-v {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 22rem;
}

.dealbar .acts { margin: 0; display: flex; gap: .5rem; }
.dealbar .acts:empty { display: none; }
.dealbar .acts .btn { margin: 0; }

/* Ниже 1200px три части в строку уже не помещаются: подпись сжимается до
   четырёх слов в строке и полоса растёт вверх. Тогда она уходит вниз, а
   заголовок с контрактом остаются на одной строке. */
@media (max-width: 1200px) {
  .dealbar { grid-template-columns: minmax(0, auto) auto; justify-content: space-between; }
  /* Места назначаются явно. Автоматическая раскладка идёт по порядку в
     разметке, а подпись стоит там между заголовком и контрактом: занимая
     всю ширину, она выталкивала контракт на третью строку и он оказывался
     под заголовком, а не рядом с ним. */
  .dealbar .hh  { grid-area: 1 / 1; }
  .dealbar .dr  { grid-area: 1 / 2; }
  .dealbar .sub { grid-area: 2 / 1 / 3 / -1; max-width: 68ch; }
}

@media (max-width: 900px) {
  .dealbar { grid-template-columns: 1fr; }
  .dealbar .hh  { grid-area: auto; }
  .dealbar .dr  { grid-area: auto; justify-content: flex-start; }
  .dealbar .sub { grid-area: auto; }
  /* На узком экране адрес переносится, а не обрезается многоточием.
     Многоточию нужна заданная ширина; без неё строка в сорок два
     символа просто раздвигала страницу — замер на 390px показал лишние
     54 пикселя вбок. Уехать вбок не давал overflow у ленты, поэтому
     глазом это было незаметно, а горизонтальная прокрутка на телефоне
     появилась бы от любого другого широкого элемента. */
  .dealbar .ca-v {
    max-width: none;
    white-space: normal;
    word-break: break-all;
    text-overflow: clip;
  }
}

/* ---------- ряд: счёт и фигура ---------- */

.hero-g {
  /* Счёту дано больше места, чем фигуре. Пополам не работало: в карточку
     шириной 297px не влезает «500,000,000» кеглем в 58 пикселей, и число
     отрывало от себя тикер, а подписи ломались по три строки. Числа тут
     главные, фигура — фон. */
  grid-template-columns: minmax(0, 1.24fr) minmax(0, 1fr);
  /* Растягивание, а не центрирование: иначе колонки разной высоты
     разъезжаются по вертикали, и «ровно» превращается в «примерно». */
  align-items: stretch;
  gap: clamp(.9rem, 2.2vw, 1.6rem);
}

/* min-width: 0 обязателен, и это не перестраховка.

   У элемента сетки минимальная ширина по умолчанию равна ширине его
   содержимого, а внутри лежит поле ввода: у <input> есть собственная
   ширина примерно в двадцать символов, и она не сжимается. Колонка
   упиралась в неё и вырастала шире экрана — замер на 390 пикселях дал
   445, то есть страницу разносило на 55 пикселей вбок. Глазом это опять
   не читалось: уехать вбок не даёт бегущая лента со своим overflow.

   Ноль в минимуме снимает этот пол и пропускает сжатие вниз, к полю. */
.calccol { display: grid; min-width: 0; }
.hero .calc,
.hero .calc-in { min-width: 0; }
.hero .calc-amount { width: 100%; }

/* minmax(0,1fr), а не 1fr: обычный 1fr не даёт колонке стать уже своего
   содержимого, а в левой карточке стоит «19,650,000» кеглем в сорок
   пикселей. Из-за этого карточки выходили разной ширины — 307 и 286 при
   одинаковой доле. Ноль в минимуме снимает этот пол. */
.hero .calc {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(.9rem, 2.2vw, 1.6rem);
  /* Отступ сверху снят: он сдвигал левую колонку на 19 пикселей вниз
     относительно сферы, и ряд переставал быть ровным. Расстояние до
     полосы задаёт сам ряд. */
  margin-top: 0;
}

/* Подписи карточки не ломаются пополам. В половинной колонке «you hold»
   и «not connected · drag» переносились на две строки, и шапки двух
   карточек вставали на разной высоте — ровный ряд рассыпался на мелочи. */
.hero .cbox .hdr { align-items: baseline; gap: .6rem; }
.hero .cbox .hdr > span { white-space: nowrap; }
.hero .cbox .hdr > .ann { overflow: hidden; text-overflow: ellipsis; }

/* Крупное число обязано помещаться в строку вместе с тикером.

   Потолок в 3.6rem был рассчитан на карточку во всю ширину страницы.
   Здесь их две в половине ряда, и «500,000,000 DIMEHOOD» при таком кегле
   занимает 295 пикселей при доступных 300 — тикер срывался на вторую
   строку, а сама карточка при этом росла вверх и ломала ряд. */
.hero .amt { font-size: clamp(1.5rem, 2.5vw, 2.4rem); margin: .5rem 0 .2rem; }
.hero .amt small { font-size: .32em; }

/* Столбики под числом — две подписи в ряд, каждая в одну-две строки.
   «trailing yield, per epoch» ломалось на три и растягивало карточку. */
.hero .cs .k { font-size: .56rem; letter-spacing: .1em; }

/* Фигура тянется на всю высоту соседней колонки.

   Соотношение сторон снято нарочно: с ним коробка задавала себе высоту
   сама и не совпадала со счётом. Здесь высоту диктует ряд, а фигура
   вписывается в то, что дали. */
.hero .stage {
  aspect-ratio: auto;
  height: 100%;
  min-height: 22rem;
}

/* Кегль здесь задаёт РАЗМЕР фигуры, а не только её зернистость: сетка
   символов постоянная, поэтому мелкий шрифт даёт мелкую сферу в пустой
   коробке. Раньше стояло clamp(4.4px,.92vw,9px) — сфера занимала едва
   половину коробки.
   Потолок 11px, а не 13: на 13 сфера перерастала коробку и ей срезало
   макушку и низ. Клипнутая фигура выглядит не крупной, а сломанной.
   Межстрочный ровно 1, как в базовом стиле: фигура считает число строк
   по высоте коробки, деля её на кегль. Любая надбавка сверх единицы
   означает, что нарисованных строк чуть больше, чем помещается, и
   последняя срезается снизу. */
.hero .stage .ascii { font-size: clamp(6px, 1.05vw, 11px); line-height: 1; }

@media (max-width: 900px) {
  .hero-g { grid-template-columns: 1fr; }
  /* min-height обязан уйти вместе с растягиванием. Иначе он остаётся
     сильнее соотношения сторон, и ширина считается ОТ него: 352px / 0.82
     = 429px, то есть коробка вылезала за экран телефона на 54 пикселя.
     Уехать вбок не давала лента с её overflow, поэтому глазом поломка не
     читалась — нашлась замером ширины документа. */
  .hero .stage { height: auto; min-height: 0; aspect-ratio: 1 / .82; }
  .hero .stage .ascii { font-size: clamp(4.4px, 1.6vw, 10px); }
}
@media (max-width: 620px) {
  .hero .calc { grid-template-columns: 1fr; }
}


/* ---------- подпись над первым экраном ----------
   «based on live volume at the published rate» стояла в строке с «v1.0»
   и упиралась в правый край: на среднем экране она еле влезала, а на
   узком лезла за границу. Причина в `white-space: nowrap` у .corners span
   из base.css — строка в сорок символов не переносилась вообще.

   Разрешаем перенос и ограничиваем ширину: подпись занимает свою треть и
   не воюет с номером версии. */
.hero > .corners .mid {
  white-space: normal;
  max-width: 34ch;
  text-align: right;
  line-height: 1.5;
}

@media (max-width: 620px) {
  .hero > .corners .mid { max-width: none; text-align: left; }
}

/* =========================================================================
   СТАКАН ПОКА ГРУЗИТСЯ

   Раньше в разметке лежал запечённый кадр той самой фигуры из символов —
   4645 символов текста. Он показывался до тех пор, пока не приедут
   three.js, модель банки и состав корзины, то есть первые несколько
   секунд у каждого посетителя. Выглядело это так, будто сайт и есть тот
   зелёный ком, а потом он ни с того ни с сего сменился упаковкой.

   Хуже того, статичный кадр невозможно отличить от сломанного: он не
   двигается ровно так же, как не двигалась бы не запустившаяся анимация.

   Теперь на его месте честная загрузка. Она говорит, что идёт работа, и
   не притворяется содержимым.

   Полоса бежит сама и НЕ показывает долю: доли этой никто не знает —
   грузятся три разные вещи из трёх мест, и любая цифра здесь была бы
   выдумана. Бегущая полоса означает «идёт», и только.
   ========================================================================= */
.stage-boot {
  position: absolute;
  inset: auto 0 auto 0;
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  justify-items: center;
  gap: .8rem;
  pointer-events: none;
  transition: opacity .35s ease;
}

.stage-boot-bar {
  position: relative;
  width: min(9rem, 42%);
  height: 2px;
  overflow: hidden;
  background: color-mix(in srgb, var(--color-bone) 8%, transparent);
}

.stage-boot-bar i {
  position: absolute;
  inset: 0 auto 0 0;
  width: 42%;
  background: var(--color-neon);
  animation: stage-boot-run 1.25s cubic-bezier(.65, 0, .35, 1) infinite;
}

@keyframes stage-boot-run {
  0%   { left: -42%; }
  100% { left: 100%; }
}

.stage-boot-txt {
  font-family: var(--font-mono);
  font-size: .53rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--color-mute);
}

/* Убирается, как только в стакане появилась канва. Класс вешает stage.js:
   он один знает, что первый кадр действительно нарисован — по появлению
   элемента судить нельзя, канва существует ещё до первого render. */
.stage.ready .stage-boot { opacity: 0; }

/* Кому движение мешает — полоса стоит, надпись остаётся. Смысл её в
   тексте, а не в беге. */
@media (prefers-reduced-motion: reduce) {
  .stage-boot-bar i { animation: none; left: 0; width: 100%; opacity: .4; }
}


/* =========================================================================
   ПОЛОСА КОНТРАКТА

   Было: адрес и три одинаковых на вид действия рядом — copy, explorer и
   покупка. Человек не мог отличить, где ссылка, где кнопка и где главное
   действие, потому что весили они одинаково.

   Стало: рамка со своей подложкой, и внутри ровно две кнопки. Сам адрес
   стал ссылкой в обозреватель — отдельное слово «explorer» было третьим
   элементом, объясняющим то же, что и адрес.

   Покупка выделена акцентом, копирование — обычной рамкой: главное
   действие на полосе одно, и оно должно быть видно первым.
   ========================================================================= */
.dealbar .dr {
  border: 1px solid var(--color-rule-2);
  background: var(--color-ink-2);
  padding: .5rem .5rem .5rem .85rem;
  gap: .75rem;
}
.dealbar .ca { gap: .55rem; }
.dealbar .ca-k {
  font-family: var(--font-mono);
  font-size: .54rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--color-mute);
}
.dealbar .ca-v {
  font-family: var(--font-mono);
  font-size: .72rem;
  color: var(--color-h1c);
  border-bottom: 1px dashed var(--color-rule-2);
  padding-bottom: 1px;
  transition: color .15s, border-color .15s;
}
.dealbar .ca-v:hover { color: var(--color-neon); border-bottom-color: var(--color-neon); }
.dealbar .ca-copy {
  font-family: var(--font-mono);
  font-size: .58rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--color-h2c);
  background: none;
  border: 1px solid var(--color-rule-2);
  padding: .5rem .8rem;
  cursor: pointer;
  white-space: nowrap;
  transition: all .15s;
}
.dealbar .ca-copy:hover { color: var(--color-neon); border-color: var(--color-neon); }
.dealbar .ca-copy.bad { color: var(--color-h2c); border-color: var(--color-h2c); }

@media (max-width: 700px) {
  /* На узком экране полоса складывается в столбик, но рамка остаётся:
     это по-прежнему один блок, а не три отдельные вещи. */
  .dealbar .dr { align-items: stretch; flex-direction: column; }
  .dealbar .acts .btn { width: 100%; text-align: center; }
}
