/* ═══════════════════════════════════════════════════════════════════
   КАРТОЧКА. Пять слоёв: подложка, арт, затемнение, рамка, текст.
   Плюс два необязательных: бегущая радуга у фойла и блик у золота.

   СГЕНЕРИРОВАНО из демо/galereya-kart.html — это проверенный код,
   он не переписывался руками. Пересобрать: npm run assets

   Всё выражено долей от --w, поэтому карта выглядит одинаково и в
   сетке коллекции, и на весь экран. Пропорция 800/1177 жёсткая:
   по ней сняты все зоны текста, менять нельзя.

   Источник правил: 02-карта-и-конструктор.md
   ═══════════════════════════════════════════════════════════════════ */

@font-face{font-family:'Gill Sans Nova Cond';font-weight:700;font-style:normal;font-display:swap;src:url(../assets/fonts/GillSansNova-CnBold.woff2) format('woff2')}
@font-face{font-family:'Gill Sans Nova';font-weight:400;font-style:normal;font-display:swap;src:url(../assets/fonts/GillSansNova-Book.woff2) format('woff2')}
@font-face{font-family:'Futura PT';font-weight:900;font-style:normal;font-display:swap;src:url(../assets/fonts/FuturaPT-Heavy.woff2) format('woff2')}

/* ─── ШРИФТЫ ВШИТЫ В ФАЙЛ ─────────────────────────────────────────
   Настоящие Gill Sans Nova и Futura PT, формат WOFF2. Ничего не
   грузится из сети — карта выглядит одинаково везде и офлайн.  */

/* ══════════════════════════════════════════════════════════════════
   КОНСТРУКТОР КАРТЫ v2

   Что изменилось против первой версии:
     • углы арта скруглены и подобраны под рамку (ползунки «Арт»)
     • «pts» прибит к своему месту, число растёт влево
     • подпись художника заменена на эмблему (сердце / мини-арт / ничего)
     • на левой части нижней полоски появилась строка тира
     • у мелкого текста внизу свой переключатель шрифта
   ══════════════════════════════════════════════════════════════════ */

:root{
  /* Семейства. Порядок: сначала настоящие, потом бесплатные аналоги. */
  --f-cond:'Gill Sans Nova Cond','Gill Sans MT Condensed','Barlow Semi Condensed',sans-serif;
  --f-text:'Gill Sans Nova','Gill Sans MT',Lato,'Segoe UI',sans-serif;
  --f-num:'Futura PT','Futura',Jost,'Trebuchet MS',sans-serif;
  --f-small:var(--f-cond);          /* шрифт мелких подписей внизу */

  /* ─── твои значения ─── */
  --w:280px;   /* значение по умолчанию, вёрстка его переопределяет */
  --art-inset:0;    --art-radius:.14;
  --art-zoom:1.03;  --art-dx:-1.5;   --art-dy:-5.5;
  --name-size:.074; --name-x:21.5;  --name-y:6.2;
  --hp-size:.058;   --hp-x:67;      --hp-y:6.6;
  --tier-size:.108; --tier-x:4.4;   --tier-y:11.8;
  --atk-size:.062;  --atk-x:8;      --atk-y:72.4;
  --dmg-size:.077;  --dmg-x:66.5;   --dmg-y:72.4;
  --desc-size:.037; --desc-x:8;     --desc-y:79.2; --desc-w:84;
  --stats-size:.032;--stats-y:84.8; --stats-ls:.6;
  --rar-x:6;        --pts-x:49.5;   --mint-x:92;
  --em-size:8.6;    --em-x:7;       --em-y:91.2;
  --em-zoom:1.85;   --em-tx:0;      --em-ty:9;
  --tag-size:.031;  --tag-x:41;     --tag-y:92.4;
  --set-size:.040;  --set-x:90;     --set-y:91.2;
  --copy-size:.029; --copy-y:97.8;
  --scrim-top:.20;  --scrim-bot:.20;
}
/* для сравнения: бесплатные аналоги (нужен интернет) */





*{box-sizing:border-box;margin:0;padding:0}















.card{width:var(--w)}
.stage{position:relative;width:100%;aspect-ratio:800/1177;
  border-radius:calc(var(--w)*.045);
  filter:drop-shadow(0 14px 26px rgba(0,0,0,.75)) drop-shadow(0 0 14px var(--glow,transparent))}

/* Арт утоплен внутрь и скруглён сильнее рамки, поэтому его углы
   нигде не торчат. Фото не трогали — двигаем и масштабируем слоем.

   .backing  — тёмная подложка: при сильном утоплении в зазор между
               артом и рамкой видно её, а не фон страницы
   .artbox   — окно с обрезкой; внутри арт можно возить и приближать
   .art      — само фото: transform двигает и увеличивает              */
.backing{position:absolute;inset:2%;
  border-radius:calc(var(--w)*var(--art-radius));background:#0d0e13}
.artbox{position:absolute;
  top:calc(var(--art-inset)*1%);left:calc(var(--art-inset)*1%);
  width:calc(100% - var(--art-inset)*2%);
  height:calc(100% - var(--art-inset)*2%);
  border-radius:calc(var(--w)*var(--art-radius));overflow:hidden}
.art{width:100%;height:100%;object-fit:cover;display:block;
  transform:translate(calc(var(--art-dx)*1%),calc(var(--art-dy)*1%)) scale(var(--art-zoom));
  transform-origin:center}
.scrim{position:absolute;
  top:calc(var(--art-inset)*1%);left:calc(var(--art-inset)*1%);
  width:calc(100% - var(--art-inset)*2%);
  height:calc(100% - var(--art-inset)*2%);
  border-radius:calc(var(--w)*var(--art-radius));
  background:linear-gradient(180deg,
    rgba(0,0,0,var(--scrim-top)) 0%,
    rgba(0,0,0,calc(var(--scrim-top)*.55)) 9%,
    rgba(0,0,0,0) 19%,
    rgba(0,0,0,0) 64%,
    rgba(0,0,0,calc(var(--scrim-bot)*.45)) 76%,
    rgba(0,0,0,calc(var(--scrim-bot)*.86)) 89%,
    rgba(0,0,0,var(--scrim-bot)) 100%)}
.frame{position:absolute;inset:0;width:100%;height:100%;display:block}

.common    .frame{filter:saturate(.05) brightness(1.16) contrast(1.04)}
.common               {--glow:#9aa4b666}
.rare      .frame{filter:hue-rotate(163deg) saturate(1.12) brightness(1.02)}
.rare                 {--glow:#4f9fd877}
.epic      .frame{filter:hue-rotate(228deg) saturate(1.05) brightness(1.02)}
.epic                 {--glow:#9257d677}
.legendary .frame{filter:none}
.legendary            {--glow:#d8a02e80}
.mythic    .frame{filter:hue-rotate(303deg) saturate(1.35) brightness(1.02)}
.mythic               {--glow:#e0344f88}

.holo{position:absolute;pointer-events:none;
  top:calc(var(--art-inset)*1%);left:calc(var(--art-inset)*1%);
  width:calc(100% - var(--art-inset)*2%);
  height:calc(100% - var(--art-inset)*2%);
  border-radius:calc(var(--w)*var(--art-radius));mix-blend-mode:overlay;
  background:linear-gradient(112deg,transparent 32%,rgba(255,255,255,.5) 44%,
    rgba(150,225,255,.42) 49%,rgba(255,165,235,.42) 54%,transparent 66%);
  background-size:260% 260%;animation:cardSweep 3.8s ease-in-out infinite}
@keyframes cardSweep{0%,100%{background-position:0% 0%}50%{background-position:100% 100%}}


/* ══ ЗОЛОТОЕ ИЗДАНИЕ ══════════════════════════════════════════════
   Дуотон плюс бегущий блик. Фильтр накрывает карту целиком — арт,
   рамку, текст и эмблему. Отдельный золотой арт НЕ нужен: любая
   карта становится золотой добавлением класса .gold.

   Доступно только для Legendary и Mythic, получается крафтом.     */
.gold .frame{filter:none}
.gold .stage{filter:url(#duotone-gold) saturate(1.05)
  drop-shadow(0 14px 26px rgba(0,0,0,.75)) drop-shadow(0 0 18px #f0c44eaa)}
.gold{--glow:#f0c44eaa}
.gloss{position:absolute;inset:0;z-index:5;pointer-events:none;
  border-radius:calc(var(--w)*var(--art-radius));
  background:linear-gradient(104deg,
    transparent 34%, rgba(255,255,255,.30) 44%, rgba(255,255,255,.72) 50%,
    rgba(255,255,255,.30) 56%, transparent 66%);
  background-size:250% 250%;mix-blend-mode:screen;
  animation:cardSweep 4.2s ease-in-out infinite}

/* ─── зоны текста ────────────────────────────────────────────────── */
.z{position:absolute;z-index:3;line-height:1.15;transform:translateY(-50%);
   display:flex;align-items:center;pointer-events:none}
.shadow{color:#fff;text-shadow:0 2px 6px rgba(0,0,0,.95),0 0 3px rgba(0,0,0,.85)}
.metal{color:#241a03}

.name{left:calc(var(--name-x)*1%);width:46%;top:calc(var(--name-y)*1%);white-space:nowrap;
  font-family:var(--f-cond);font-weight:700;font-size:calc(var(--w)*var(--name-size));
  letter-spacing:-.1px}
.hp{left:calc(var(--hp-x)*1%);width:27%;top:calc(var(--hp-y)*1%);justify-content:flex-end;
  font-family:var(--f-num);font-weight:900;font-size:calc(var(--w)*var(--hp-size));
  letter-spacing:.2px;color:#1b1b1f}
.tier{left:calc(var(--tier-x)*1%);width:12.2%;top:calc(var(--tier-y)*1%);justify-content:center;
  font-family:var(--f-num);font-weight:900;font-size:calc(var(--w)*var(--tier-size));
  color:#4a3406;text-shadow:0 1px 1px rgba(255,255,255,.5)}
.atk{left:calc(var(--atk-x)*1%);width:56%;top:calc(var(--atk-y)*1%);
  font-family:var(--f-cond);font-weight:700;font-size:calc(var(--w)*var(--atk-size));
  letter-spacing:.2px}
.dmg{left:calc(var(--dmg-x)*1%);width:26%;top:calc(var(--dmg-y)*1%);justify-content:flex-end;
  font-family:var(--f-num);font-weight:900;font-size:calc(var(--w)*var(--dmg-size))}
.desc{left:calc(var(--desc-x)*1%);width:calc(var(--desc-w)*1%);top:calc(var(--desc-y)*1%);
  display:block;font-family:var(--f-text);font-weight:400;
  font-size:calc(var(--w)*var(--desc-size));line-height:1.38;
  color:#eef1f6;text-shadow:0 1px 4px rgba(0,0,0,.98)}

/* ─── нижняя полоса: четыре независимых куска ────────────────────────
   Раньше это был один flex со space-between, поэтому «pts» уезжало
   вправо вслед за длинным числом. Теперь «pts» стоит на своём месте,
   а число прижато к нему справа и растёт ВЛЕВО.                      */
.st-rar{left:calc(var(--rar-x)*1%);width:46%;top:calc(var(--stats-y)*1%)}
.st-num{left:0;width:calc(var(--pts-x)*1%);top:calc(var(--stats-y)*1%);
        justify-content:flex-end;padding-right:.3em}
.st-lab{left:calc(var(--pts-x)*1%);width:22%;top:calc(var(--stats-y)*1%)}
.st-mint{left:0;width:calc(var(--mint-x)*1%);top:calc(var(--stats-y)*1%);
        justify-content:flex-end}
/* Вся полоса — ОДИН шрифт и один вес. Раньше число pts было набрано
   Futura, а подписи Gill Sans: у них разные метрики, поэтому цифры
   казались другими и сидели выше строки. */
.st-rar,.st-num,.st-lab,.st-mint{
  font-family:var(--f-small);font-weight:700;text-transform:uppercase;
  font-size:calc(var(--w)*var(--stats-size));
  letter-spacing:calc(var(--stats-ls)*1px);color:#241a03}

/* ─── эмблема внизу слева ───────────────────────────────────────
   Мини-арт берёт ТОТ ЖЕ файл, что и большая картинка, и кадрируется
   своими ползунками. Значит для каждой карты можно подобрать свой
   кроп, не готовя отдельную миниатюру.                            */
.em{left:calc(var(--em-x)*1%);top:calc(var(--em-y)*1%);
    width:calc(var(--em-size)*1%);aspect-ratio:1;transform:translateY(-50%)}
.em>*{width:100%;height:100%;display:none}

.em .thumbwrap{display:block;border-radius:50%;overflow:hidden;
  box-shadow:0 0 0 calc(var(--w)*.005) rgba(255,255,255,.8),0 2px 5px rgba(0,0,0,.6)}
.em .thumb{width:100%;height:100%;object-fit:cover;display:block;
  transform:translate(calc(var(--em-tx)*1%),calc(var(--em-ty)*1%)) scale(var(--em-zoom));
  transform-origin:center}

/* ─── строка тира на левой части металла ─────────────────────────── */
.tag{left:calc(var(--tag-x)*1%);width:40%;top:calc(var(--tag-y)*1%);
  font-family:var(--f-small);font-weight:700;text-transform:uppercase;
  font-size:calc(var(--w)*var(--tag-size));letter-spacing:calc(var(--stats-ls)*1px);
  color:#241a03}
.setno{left:0;width:calc(var(--set-x)*1%);top:calc(var(--set-y)*1%);justify-content:flex-end;
  font-family:var(--f-small);font-weight:700;text-transform:uppercase;
  font-size:calc(var(--w)*var(--set-size));letter-spacing:calc(var(--stats-ls)*1px);
  color:#241a03}
.copy{left:0;width:100%;top:calc(var(--copy-y)*1%);justify-content:center;
  font-family:var(--f-small);font-weight:700;text-transform:uppercase;
  font-size:calc(var(--w)*var(--copy-size));letter-spacing:.8px;color:#332504}

/* ─── ANDROID САМ УВЕЛИЧИВАЕТ МЕЛКИЙ ТЕКСТ ────────────────────────────
   Chrome и WebView на Android умеют «подбустить» шрифт: если в узком
   блоке текст переносится на несколько строк, браузер решает, что его
   не прочитать, и увеличивает — в разы. Официального выключателя нет,
   есть эта строка.

   На карточке под раздачу попадало ровно одно место — описание атаки.
   Это единственный текст на карте, который переносится: у имени стоит
   nowrap, остальные строки короткие. Описание раздувалось и наезжало
   на имя атаки сверху и на строку очков снизу. В коллекции, где карта
   шириной всего ~108 пикселей, это заметнее всего: чем уже блок, тем
   сильнее Android увеличивает.

   Все размеры на карточке заданы долей от --w и должны применяться как
   есть. Самодеятельность браузера здесь ломает вёрстку, а не помогает.

   Правило живёт в card.css, а не в app.css, намеренно: карточка
   рисуется и на proba-kart.html, где кроме этого файла ничего не
   подключено.                                                        */
html{-webkit-text-size-adjust:100%;text-size-adjust:100%}

/* ─── МЕЛКАЯ КАРТА: ВЕРСТАЕМ КРУПНОЙ, ПОКАЗЫВАЕМ МАЛЕНЬКОЙ ────────────
   Android WebView не позволяет шрифту быть меньше 8 пикселей. Всё, что
   мельче, он молча увеличивает до восьми. Это не автоувеличение
   длинных абзацев, это отдельный жёсткий порог, и ни text-size-adjust,
   ни ограничение высоты на него не действуют — выключателя из CSS нет
   вообще.

   Размеры на карточке заданы долей от её ширины. В коллекции карта
   шириной 108 пикселей, и почти весь текст на ней задуман мельче
   восьми: подпись внизу 3.1, тир 3.3, очки 3.5, описание 4.0, номер
   4.3, HP 6.3, атака 6.7. Под порог не попадают только имя, урон и
   буква тира. То есть телефон растягивал почти все надписи до одного
   размера, и вёрстка расползалась. Виднее всего было по описанию: это
   единственная надпись, которая переносится, поэтому она не просто
   становилась крупнее, а занимала лишние строки и наезжала на соседей.

   Обойти порог можно единственным способом — не делать шрифт мелким.
   Карта верстается в полный размер (320 пикселей), где даже самая
   мелкая подпись равна 9.3 пикселя, и уменьшается целиком масштабом.
   Масштаб к шрифту отношения не имеет, порог его не касается: текст
   остаётся ровно там, где нарисован, и в тех же пропорциях.

   Коробка .fit держит настоящий размер места на экране, карта внутри
   лежит поверх и в поток не входит. Во сколько раз уменьшать —
   считает игра, меряя коробку: ширина ячейки зависит от экрана, а в
   CSS длину на длину поделить нельзя. См. fitCards в js/app.js.      */
.fit{display:block;position:relative;width:100%;
  aspect-ratio:800/1177;overflow:hidden}
.fit .card{position:absolute;top:0;left:0;
  --w:var(--fit-base,320px);width:var(--fit-base,320px);
  transform:scale(var(--fit-k,1));transform-origin:0 0}

/* Страховка: даже если размер шрифта где-то уедет, описание не должно
   наезжать на имя атаки сверху и на строку очков снизу. Между ними по
   вёрстке 12.4% высоты карты, то есть 0.18 её ширины. Потолок ниже,
   лишнее обрежется. При правильном размере описание занимает 0.10
   ширины — то есть в обычной жизни потолок недостижим.               */
.desc{max-height:calc(var(--w)*.16);overflow:hidden}

/* ─── НЕСОБРАННАЯ КАРТА: тёмный силуэт ───────────────────────────────
   Контур и цвет редкости видно, арт залит тёмным, текст скрыт. Пустая
   клетка не тянет ничего собирать, а силуэт с подписью «4 000 pts» —
   тянет. Поэтому показываем все карты сезона, включая несобранные. */
.sil .artbox{filter:brightness(.13) saturate(.08) contrast(.95)}
.sil .z{visibility:hidden}
.sil .holo,.sil .gloss{display:none}
/* Рамка тоже гасится: цвет редкости угадывается, но несобранная карта
   не спорит по яркости с собранными. Правила стоят ниже правил
   редкостей — вес у них тот же, решает порядок. Насыщенность вынесена
   в переменную, чтобы подкручивать её в одном месте. */
.sil{--sil-color:.2;--glow:#6e6e7a55}

/* Гасим цвет, но поворот тона трогать нельзя. Рамка в исходнике одна и
   она золотая; синей, фиолетовой и красной её делает именно
   hue-rotate из правил редкости. filter — одно свойство целиком, и
   если задать его заново, поворот пропадает — все несобранные карты
   становятся золотыми.

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

   Common живёт по своим числам: он и в собранном виде почти белый,
   общие 20% сделали бы несобранный ярче собранного.
   Gold сюда не попадает: у него цвет даёт не рамка, а дуотон поверх
   всей карты — он гасится ниже, отдельным правилом.                 */
.sil.common    .frame{filter:saturate(.05) brightness(.8) contrast(1.02)}
.sil.rare      .frame{filter:hue-rotate(163deg) saturate(var(--sil-color)) brightness(.78)}
.sil.epic      .frame{filter:hue-rotate(228deg) saturate(var(--sil-color)) brightness(.78)}
.sil.legendary .frame{filter:saturate(var(--sil-color)) brightness(.78)}
.sil.mythic    .frame{filter:hue-rotate(303deg) saturate(var(--sil-color)) brightness(.78)}
.sil.gold .stage{filter:url(#duotone-gold) saturate(var(--sil-color)) brightness(.78)
  drop-shadow(0 14px 26px rgba(0,0,0,.75))}
.sil .stage::after{content:'?';position:absolute;inset:0;z-index:4;display:flex;
  align-items:center;justify-content:center;font-family:var(--f-num);font-weight:900;
  font-size:calc(var(--w)*.2);color:rgba(255,255,255,.12)}

/* Выравнивание задаём явно: карточка не должна зависеть от того, куда
   её положили. В сетке коллекции у ячейки стоит выравнивание по центру
   — оно нужно подписи под картой, но протекало внутрь, и описание атаки
   на мелких картах выравнивалось по центру, а на крупных по левому
   краю. Из всех надписей это касается только описания: остальные зоны —
   гибкие контейнеры и выравниваются своими правилами.               */
.card{text-align:left}

/* ─── ДУБЛИКАТ: счётчик ×N в углу ────────────────────────────────────── */
.card{position:relative}
.dupe-badge{position:absolute;top:calc(var(--w)*.02);right:calc(var(--w)*.02);z-index:6;
  font-family:var(--f-num);font-weight:900;font-size:calc(var(--w)*.052);
  line-height:1;padding:calc(var(--w)*.022) calc(var(--w)*.042);
  border-radius:calc(var(--w)*.03);color:#fff;background:rgba(12,12,18,.86);
  box-shadow:0 2px 8px rgba(0,0,0,.6),inset 0 0 0 1px rgba(255,255,255,.14)}
