/* IT DEVELOPMENT — оформление платформы.
   Стекло поверх мягкого света: полупрозрачные слои, крупные скругления,
   один насыщенный цвет и много воздуха. Фирменный — #00208a. */

/* Токены.
   Главное про стекло: оно видно только тогда, когда под ним есть что
   размывать. Бледно-серый фон превращает любую полупрозрачность в плоскую
   белую карточку — поэтому здесь под стеклом лежит насыщенный цвет, а у
   самого стекла есть бликующий верхний край, как у настоящего. */
:root{
  --brand:        #00208a;
  --brand-soft:   #2a56d6;
  --brand-glow:   #5b7cff;
  --violet:       #6d3df5;
  --cyan:         #00b8d4;
  --brand-tint:   rgba(0, 32, 138, .09);
  --brand-line:   rgba(0, 32, 138, .18);

  --ok:      #0a7d4f;
  --warn:    #a86a00;
  --danger:  #b3261e;

  /* Фирменный цвет живёт двумя жизнями: заливкой под белым текстом и самим
     текстом на стекле. На белом фоне это может быть один цвет, на тёмном —
     нет: то, что читается как надпись, слишком светлое для подложки под
     белыми буквами. Отсюда две переменные вместо одной. */
  --brand-fill: #00208a;

  /* Цветные пятна за стеклом — тоже переменными. Днём они лежат на светлом
     фоне и потому глубокие; ночью на почти чёрном такие же превращаются в
     грязь, и их приходится делать светлее самого фона, а не темнее. */
  --glow-1: rgba(0, 32, 138, .55);
  --glow-2: rgba(109, 61, 245, .40);
  --glow-3: rgba(0, 184, 212, .30);
  --glow-4: rgba(42, 86, 214, .38);
  --glow-sat: 115%;
  --grid-line: rgba(0, 32, 138, .05);
  /* Блик по верхнему краю стекла. Днём это белый свет; ночью белому свету
     взяться неоткуда — на тёмной карточке он читается как серый налёт и
     съедает весь цвет, поэтому там он холодный и вчетверо слабее. */
  --glass-gloss: rgba(255, 255, 255, .55);

  /* Подложки и рамки смысловых цветов — тоже переменными: в тёмной теме у них
     другая не только яркость, но и плотность. */
  --ok-bg:      rgba(10, 125, 79, .12);
  --warn-bg:    rgba(168, 106, 0, .13);
  --danger-bg:  rgba(179, 38, 30, .12);
  --neutral-bg: rgba(8, 12, 26, .08);
  --ok-line:     rgba(10, 125, 79, .22);
  --warn-line:   rgba(168, 106, 0, .22);
  --danger-line: rgba(179, 38, 30, .22);

  --bg:        #eaeeff;
  --bg-2:      #d6def8;
  --text:      #080c1a;
  --muted:     #4d5670;
  --faint:     #7d879f;

  /* Стекло — не заливка, а градиент: сверху светлее, снизу прозрачнее, как
     на изогнутой поверхности. */
  --glass-top:    rgba(255, 255, 255, .74);
  --glass-bottom: rgba(255, 255, 255, .38);
  --glass-edge:   rgba(255, 255, 255, .92);
  --glass-inner:  rgba(255, 255, 255, .95);
  --glass-under:  rgba(0, 32, 138, .07);
  --border:       rgba(8, 12, 26, .08);

  --blur: 42px;

  /* Тень в три слоя: контактная, объёмная и цветной отсвет от фирменного
     цвета — без него белая карточка висит в воздухе без причины. */
  --shadow:
    inset 0 1px 0 var(--glass-inner),
    inset 0 -1px 0 var(--glass-under),
    0 1px 2px rgba(8, 12, 26, .04),
    0 8px 24px rgba(0, 32, 138, .09);
  --shadow-lift:
    inset 0 1px 0 var(--glass-inner),
    inset 0 -1px 0 var(--glass-under),
    0 2px 4px rgba(8, 12, 26, .05),
    0 18px 48px rgba(0, 32, 138, .20);

  --r-sm: 14px;
  --r-md: 20px;
  --r-lg: 28px;
  --r-xl: 38px;
  --pill: 999px;

  --ease: cubic-bezier(.22, 1, .36, 1);
  --t: .24s var(--ease);
}

/* Тёмная тема в трёх состояниях, и порядок здесь важен.

   «Системная» — значение по умолчанию: сайт подхватывает настройку телефона
   или ноутбука, ничего не спрашивая. Но если человек выбрал тему руками, его
   выбор сильнее системы — иначе переключатель врёт.

   Отсюда два блока с одинаковым содержимым: первый ловит системную тёмную,
   но только когда светлая не выбрана явно; второй — явный выбор. */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --bg: #05070f;  --bg-2: #0a1024;
    --text: #f3f5fc; --muted: #c2c9dd; --faint: #98a2bd;
    --glass-top:    rgba(78, 106, 195, .30);
    --glass-bottom: rgba(24, 36, 82, .26);
    --glass-edge:   rgba(168, 196, 255, .20);
    --glass-inner:  rgba(255, 255, 255, .18);
    --glass-under:  rgba(0, 0, 0, .22);
    --border:       rgba(255, 255, 255, .11);
    --brand-tint: rgba(91, 124, 255, .16);
    --brand-line: rgba(120, 150, 255, .30);
    /* Ночью фирменный синий #00208a — почти чёрный: на тёмном стекле он
       перестаёт быть цветом и становится дырой. Надписи, значки и активный
       раздел уходят в светлый оттенок, а заливка под белым текстом остаётся
       плотной. Смысловые цвета подняты по той же причине. */
    --brand:      #93a9ff;
    --brand-fill: #2545c9;
    --ok:      #3ddc97;
    --warn:    #ffb648;
    --danger:  #ff7d73;
    --ok-bg:      rgba(61, 220, 151, .14);
    --warn-bg:    rgba(255, 182, 72, .15);
    --danger-bg:  rgba(255, 125, 115, .15);
    --neutral-bg: rgba(255, 255, 255, .10);
    --ok-line:     rgba(61, 220, 151, .28);
    --warn-line:   rgba(255, 182, 72, .30);
    --danger-line: rgba(255, 125, 115, .30);
    /* Ночью светятся, а не заливают: на #05070f тот же синий с прозрачностью
       .55 читается как чёрное пятно. Цвета взяты светлее фона, насыщенность
       поднята — иначе размывать под стеклом просто нечего. */
    --glow-1: rgba(48, 88, 235, .40);
    --glow-2: rgba(138, 74, 255, .32);
    --glow-3: rgba(0, 205, 235, .20);
    --glow-4: rgba(74, 112, 255, .28);
    --glow-sat: 135%;
    --grid-line: rgba(150, 180, 255, .07);
    --glass-gloss: rgba(176, 205, 255, .14);
    --shadow:
      inset 0 1px 0 var(--glass-inner),
      inset 0 -1px 0 var(--glass-under),
      0 2px 6px rgba(0,0,0,.4), 0 12px 36px rgba(0,0,0,.44);
    --shadow-lift:
      inset 0 1px 0 var(--glass-inner),
      inset 0 -1px 0 var(--glass-under),
      0 4px 10px rgba(0,0,0,.46), 0 22px 60px rgba(0,0,0,.6);
  }
  :root:not([data-theme="light"]) .brandmark-word{ color: #f3f5fc !important; }
}

:root[data-theme="dark"]{
    --bg: #05070f;  --bg-2: #0a1024;
    --text: #f3f5fc; --muted: #c2c9dd; --faint: #98a2bd;
    --glass-top:    rgba(78, 106, 195, .30);
    --glass-bottom: rgba(24, 36, 82, .26);
    --glass-edge:   rgba(168, 196, 255, .20);
    --glass-inner:  rgba(255, 255, 255, .18);
    --glass-under:  rgba(0, 0, 0, .22);
    --border:       rgba(255, 255, 255, .11);
    --brand-tint: rgba(91, 124, 255, .16);
    --brand-line: rgba(120, 150, 255, .30);
    /* Ночью фирменный синий #00208a — почти чёрный: на тёмном стекле он
       перестаёт быть цветом и становится дырой. Надписи, значки и активный
       раздел уходят в светлый оттенок, а заливка под белым текстом остаётся
       плотной. Смысловые цвета подняты по той же причине. */
    --brand:      #93a9ff;
    --brand-fill: #2545c9;
    --ok:      #3ddc97;
    --warn:    #ffb648;
    --danger:  #ff7d73;
    --ok-bg:      rgba(61, 220, 151, .14);
    --warn-bg:    rgba(255, 182, 72, .15);
    --danger-bg:  rgba(255, 125, 115, .15);
    --neutral-bg: rgba(255, 255, 255, .10);
    --ok-line:     rgba(61, 220, 151, .28);
    --warn-line:   rgba(255, 182, 72, .30);
    --danger-line: rgba(255, 125, 115, .30);
    /* Ночью светятся, а не заливают: на #05070f тот же синий с прозрачностью
       .55 читается как чёрное пятно. Цвета взяты светлее фона, насыщенность
       поднята — иначе размывать под стеклом просто нечего. */
    --glow-1: rgba(48, 88, 235, .40);
    --glow-2: rgba(138, 74, 255, .32);
    --glow-3: rgba(0, 205, 235, .20);
    --glow-4: rgba(74, 112, 255, .28);
    --glow-sat: 135%;
    --grid-line: rgba(150, 180, 255, .07);
    --glass-gloss: rgba(176, 205, 255, .14);
    --shadow:
      inset 0 1px 0 var(--glass-inner),
      inset 0 -1px 0 var(--glass-under),
      0 2px 6px rgba(0,0,0,.4), 0 12px 36px rgba(0,0,0,.44);
    --shadow-lift:
      inset 0 1px 0 var(--glass-inner),
      inset 0 -1px 0 var(--glass-under),
      0 4px 10px rgba(0,0,0,.46), 0 22px 60px rgba(0,0,0,.6);
}
:root[data-theme="dark"] .brandmark-word{ color: #f3f5fc !important; }

*{ box-sizing: border-box; }

html{ scroll-behavior: smooth; }

body{
  margin:0; min-height:100vh;
  color: var(--text);
  background: var(--bg);
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI",
               Roboto, "Helvetica Neue", sans-serif;
  font-size: 15px; line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Свет за стеклом: четыре цветных пятна, крупные и насыщенные. Именно их
   размывает backdrop-filter — на бледном фоне стекло выглядит как белый
   прямоугольник, и вся затея разваливается. */
body::before{
  content:''; position: fixed; inset: -20%; z-index: -2; pointer-events: none;
  background:
    radial-gradient(48vw 46vw at 10% -4%,  var(--glow-1), transparent 60%),
    radial-gradient(42vw 40vw at 92% 2%,   var(--glow-2), transparent 60%),
    radial-gradient(46vw 42vw at 78% 88%,  var(--glow-3), transparent 62%),
    radial-gradient(52vw 48vw at 22% 104%, var(--glow-4), transparent 62%),
    linear-gradient(170deg, var(--bg), var(--bg-2));
  filter: saturate(var(--glow-sat, 115%));
}

/* Второй слой — очень слабая крупная сетка. Даёт стеклу что преломлять на
   пустых участках, где цветных пятен нет. */
body::after{
  content:''; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  opacity: .35;
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 68px 68px;
  mask-image: radial-gradient(70% 60% at 50% 40%, #000, transparent 100%);
  -webkit-mask-image: radial-gradient(70% 60% at 50% 40%, #000, transparent 100%);
}

a{ color: inherit; text-decoration: none; }
h1,h2,h3,h4{ margin:0; letter-spacing:-.028em; line-height:1.12; font-weight:750; }
p{ margin:0; }

.wrap{ max-width: 1240px; margin: 0 auto; padding: 0 24px; }
.stack > * + *{ margin-top: 14px; }

/* ---------------------------------------------------------------- стекло */
.glass{
  position: relative;
  background: linear-gradient(158deg, var(--glass-top), var(--glass-bottom));
  border: 1px solid var(--glass-edge);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  backdrop-filter: blur(var(--blur)) saturate(190%);
  -webkit-backdrop-filter: blur(var(--blur)) saturate(190%);
  overflow: hidden;
}
/* Блик по верхнему краю. Одна короткая дуга света — то, что отличает стекло
   от полупрозрачного прямоугольника. */
.glass::before{
  content:''; position:absolute; inset:0; pointer-events:none; border-radius:inherit;
  background: linear-gradient(180deg, var(--glass-gloss), transparent 42%);
  opacity: .7;
}
.glass > *{ position: relative; }
.glass-strong{ --glass-top: rgba(255,255,255,.88); --glass-bottom: rgba(255,255,255,.62); }
.pad{ padding: 26px; }

/* ---------------------------------------------------------------- шапка */
.topbar{
  position: sticky; top: 0; z-index: 50;
  background: var(--glass);
  border-bottom: 1px solid var(--border);
  backdrop-filter: blur(24px) saturate(180%);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
}
.topbar-in{
  display:flex; align-items:center; gap: 22px;
  height: 64px;
}
.nav{ display:flex; gap: 4px; margin-left: 10px; }
.nav a{
  padding: 8px 14px; border-radius: var(--pill);
  font-size: 14px; font-weight: 600; color: var(--muted);
  transition: background var(--t), color var(--t);
}
.nav a:hover{ background: var(--brand-tint); color: var(--brand); }
.nav a.on{ background: var(--brand-tint); color: var(--brand); }
.spacer{ flex: 1; }

/* ------------------------------------------------------------ логотип */
.brandmark{ display:flex; align-items:center; gap:10px; flex:none; }
.brandmark svg{ display:block; border-radius: 11px; box-shadow: 0 4px 14px rgba(0,32,138,.30); }
.brandmark-word{
  font-size: 15.5px; font-weight: 800; letter-spacing: -.02em;
  color: var(--text); line-height:1.05; white-space: nowrap;
}
.brandmark-word small{
  display:block; font-size: 9.5px; font-weight: 650; letter-spacing: .1em;
  color: var(--faint); text-transform: uppercase;
}

/* ---------------------------------------------------------- языки */
.langs{
  display:flex; gap:2px; padding:3px;
  background: var(--brand-tint); border-radius: var(--pill);
  border: 1px solid var(--brand-line);
}
.langs a{
  padding: 5px 11px; border-radius: var(--pill);
  font-size: 12.5px; font-weight: 700; color: var(--muted);
  transition: background var(--t), color var(--t);
}
.langs a.on{ background: var(--brand-fill); color:#fff; box-shadow: 0 2px 8px rgba(0,32,138,.32); }
.langs a:not(.on):hover{ color: var(--brand); }

/* ---------------------------------------------------------------- кнопки */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  padding: 12px 22px; border-radius: var(--pill); border:1px solid transparent;
  font: inherit; font-weight: 700; font-size: 14.5px; cursor:pointer;
  white-space: nowrap;
  transition: transform var(--t), box-shadow var(--t), background var(--t), color var(--t);
}
.btn:active{ transform: scale(.97); }
.btn-primary{
  background: var(--brand-fill); color:#fff;
  box-shadow: 0 2px 8px rgba(0,32,138,.28), 0 10px 26px rgba(0,32,138,.24);
}
.btn-primary:hover{ background: var(--brand-soft); transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(0,32,138,.30), 0 16px 34px rgba(0,32,138,.28); }
.btn-ghost{
  background: var(--glass-strong); color: var(--text);
  border-color: var(--border); backdrop-filter: blur(20px);
}
.btn-ghost:hover{ border-color: var(--brand-line); color: var(--brand); transform: translateY(-1px); }
.btn-sm{ padding: 8px 15px; font-size: 13px; }

/* ------------------------------------------------------- размещение груза */
/* Две колонки, а не одна: четырнадцать полей в столбик — это экран, который
   надо прокручивать, чтобы увидеть кнопку. Всё, чему тесно вдвоём (название
   груза, примечание), помечается wide и занимает строку целиком. */
.post-wrap{ max-width: 760px; }
.post-h{ font-size: 30px; letter-spacing:-.02em; margin-bottom: 6px; }
.form-grid{ display:grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.form-grid .wide{ grid-column: 1 / -1; }
.post-hint{ font-size: 13.5px; color: var(--muted); line-height: 1.6; }
.post-submit{ width:100%; margin-top: 18px; }
@media (max-width: 620px){ .form-grid{ grid-template-columns: 1fr; } }

/* ---------------------------------------------------------- отклик и ставки */
.bid-form{ margin-top: 16px; }
.bid-form > * + *{ margin-top: 11px; }
.bid-row{
  display:grid; grid-template-columns: 1fr auto; gap: 12px; align-items:start;
  padding: 12px 0; border-bottom: 1px solid var(--border);
}
.bid-row:last-child{ border-bottom: 0; padding-bottom: 0; }
.bid-note{ margin-top: 6px; font-size: 13.5px; color: var(--muted); line-height: 1.5; }
.bid-acts{ display:flex; gap: 7px; justify-content:flex-end; margin-top: 9px; }
.bid-acts form{ margin: 0; }

/* Строка кабинета: объявление и действие над ним. Форма не помещается
   внутрь ссылки, поэтому лежит рядом, а не в строке. */
.cab-row{ display:grid; grid-template-columns: 1fr auto; gap: 10px; align-items:center; }
.cab-row .mini-row{ min-width: 0; }
@media (max-width: 620px){ .cab-row{ grid-template-columns: 1fr; } }

/* ---------------------------------------------------------------- поля */
.field{ display:flex; flex-direction:column; gap:6px; }
.field > span{
  font-size: 11px; font-weight: 750; letter-spacing:.06em;
  text-transform: uppercase; color: var(--faint);
}
input[type=text], input[type=search], input[type=email], input[type=number],
input[type=password], input[type=date], select, textarea{
  width:100%; padding: 11px 15px;
  font: inherit; font-size: 14.5px; color: var(--text);
  background: var(--glass-strong);
  border: 1px solid var(--border); border-radius: var(--r-sm);
  outline: none; transition: border-color var(--t), box-shadow var(--t);
  -webkit-appearance: none; appearance: none;
}
select{
  background-image: linear-gradient(45deg, transparent 50%, var(--faint) 50%),
                    linear-gradient(135deg, var(--faint) 50%, transparent 50%);
  background-position: calc(100% - 18px) 51%, calc(100% - 13px) 51%;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
  padding-right: 36px;
}
input:focus, select:focus, textarea:focus{
  border-color: var(--brand);
  box-shadow: 0 0 0 4px var(--brand-tint);
}
.check{ display:inline-flex; align-items:center; gap:8px; cursor:pointer;
  font-size: 13.5px; color: var(--muted); font-weight: 600; }
.check input{ width:17px; height:17px; accent-color: var(--brand-fill); }

/* ---------------------------------------------------------------- главная */
.hero{ padding: 74px 0 46px; }
.hero h1{
  font-size: clamp(38px, 6.4vw, 70px); font-weight: 800;
  letter-spacing: -.04em; margin-bottom: 20px;
}
.hero h1 em{ font-style: normal; color: var(--brand); }
.hero p.lead{
  font-size: clamp(15.5px, 1.7vw, 18.5px); color: var(--muted);
  max-width: 620px; line-height: 1.6;
}
.hero-cta{ display:flex; gap:10px; flex-wrap:wrap; margin-top: 30px; }

.searchbar{ display:flex; gap:10px; margin-top: 34px; max-width: 720px; }
.searchbar input{ flex:1; padding: 15px 20px; font-size: 15.5px; border-radius: var(--pill); }
.searchbar .btn{ padding-left: 26px; padding-right: 26px; }
.search-hint{ font-size: 12.5px; color: var(--faint); margin-top: 9px; padding-left: 20px; }

.stats{ display:grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-top: 54px; }
.stat{ padding: 22px; text-align:left; }
.stat b{ display:block; font-size: clamp(26px, 3.4vw, 38px); font-weight: 800;
  letter-spacing:-.03em; color: var(--brand); line-height:1.05; }
.stat span{ font-size: 12.5px; color: var(--muted); font-weight: 600; }

.why{ display:grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin: 68px 0; }
.why-card{ padding: 28px; }
.why-card .ic{
  width: 46px; height: 46px; border-radius: 14px; margin-bottom: 16px;
  display:grid; place-items:center; font-size: 21px;
  background: var(--brand-tint); border: 1px solid var(--brand-line);
}
.why-card h3{ font-size: 17px; margin-bottom: 9px; }
.why-card p{ font-size: 14px; color: var(--muted); line-height:1.62; }

.section-head{ display:flex; align-items:baseline; gap:12px; margin: 0 0 18px; }
.section-head h2{ font-size: clamp(22px, 2.6vw, 30px); }
.section-head .count{ font-size: 13.5px; color: var(--faint); font-weight: 650; }

/* ------------------------------------------------------------ доска грузов */
.board-layout{ display:grid; grid-template-columns: 268px 1fr; gap: 20px; align-items:start; }
.filters{ padding: 22px; position: sticky; top: 84px; }
.filters .field + .field{ margin-top: 14px; }
.filters .btn{ width:100%; margin-top: 16px; }

.load{
  display:grid; grid-template-columns: minmax(0,1.4fr) minmax(0,1.1fr) minmax(0,.88fr) minmax(0,.68fr) minmax(0,1.55fr) minmax(120px,.8fr);
  gap: 16px; align-items:center;
  padding: 16px 20px; border-radius: var(--r-md);
  border: 1px solid transparent;
  transition: background var(--t), border-color var(--t), transform var(--t), box-shadow var(--t);
}
.load + .load{ margin-top: 6px; }
/* Наведение на строку. Раньше под курсором вспыхивало почти непрозрачное
   белое стекло с тенью — строка отрывалась от списка и читалась как всплывшая
   карточка, то есть как свет, а не как «вот эта». Достаточно бледной заливки
   фирменным цветом: она отмечает строку, но не вынимает её из таблицы. */
.load:hover{
  background: var(--brand-tint); border-color: var(--brand-line);
}
.load-route{ font-weight: 750; font-size: 15px; letter-spacing:-.015em; }
.load-route .arrow{ color: var(--brand); margin: 0 5px; }
.load-sub{ font-size: 12.5px; color: var(--faint); margin-top: 3px; font-weight: 600; }
.load-title{ font-size: 14px; color: var(--muted); font-weight: 600; }
.load-num{ font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums; }
.load-price{ font-size: 15px; font-weight: 800; color: var(--brand);
  font-variant-numeric: tabular-nums; text-align:right; white-space:nowrap; }
.load-price.free{ color: var(--faint); font-weight: 650; font-size: 13.5px; }

.head-row{
  display:grid; grid-template-columns: minmax(0,1.4fr) minmax(0,1.1fr) minmax(0,.88fr) minmax(0,.68fr) minmax(0,1.55fr) minmax(120px,.8fr);
  gap:16px; padding: 0 20px 10px;
  font-size: 11px; font-weight: 750; letter-spacing:.06em;
  text-transform: uppercase; color: var(--faint);
}

/* --------------------------------------------------------------- компания */
.co{ display:flex; align-items:center; gap:9px; min-width:0; }
.co-ava{
  width: 34px; height: 34px; border-radius: 11px; flex:none;
  display:grid; place-items:center; font-size: 13px; font-weight: 800; color:#fff;
  background: linear-gradient(140deg, var(--brand-fill), var(--brand-soft));
  box-shadow: 0 2px 8px rgba(0,32,138,.26);
}
.co-name{ font-size: 13.5px; font-weight: 700; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
.co-meta{ font-size: 11.5px; color: var(--faint); font-weight: 600;
  display:flex; align-items:center; gap:6px; }

.badge{
  display:inline-flex; align-items:center; gap:4px;
  padding: 2px 8px; border-radius: var(--pill);
  font-size: 11px; font-weight: 750; letter-spacing:.01em; white-space:nowrap;
}
.badge-verified{ background: var(--ok-bg); color: var(--ok); }
.badge-pending{ background: var(--warn-bg); color: var(--warn); }
.badge-basic{ background: var(--neutral-bg); color: var(--muted); }
.badge-restricted{ background: var(--danger-bg); color: var(--danger); }
/* Прямой заказчик, а не посредник — то, что перевозчик ищет глазами. */
.badge-direct{ background: var(--brand-tint); color: var(--brand); margin-left: 5px; }

/* Trust Score: число и полоса. Формула наружу не выносится. */
.trust{ display:flex; align-items:center; gap:7px; }
.trust-bar{ width: 44px; height: 5px; border-radius: var(--pill);
  background: var(--border); overflow:hidden; flex:none; }
.trust-bar i{ display:block; height:100%; border-radius: var(--pill); }
/* Красим только заливку полосы. Без уточнения «.trust-bar» правило било по
   любому <i> внутри блока — в карточке профиля рядом с числом стоит подпись
   «/ 100», и она заливалась зелёным вместе с полосой. */
.trust-high .trust-bar i{ background: var(--ok); }
.trust-mid  .trust-bar i{ background: var(--brand); }
.trust-low  .trust-bar i{ background: var(--warn); }
.trust-none .trust-bar i{ background: var(--faint); }
.trust b{ font-size: 12px; font-weight: 800; font-variant-numeric: tabular-nums; }

.tag{
  display:inline-flex; align-items:center; gap:5px;
  padding: 4px 11px; border-radius: var(--pill);
  background: var(--brand-tint); border:1px solid var(--brand-line);
  font-size: 12px; font-weight: 700; color: var(--brand);
}

.empty{ padding: 64px 24px; text-align:center; color: var(--faint); }
.empty .big{ font-size: 40px; margin-bottom: 12px; opacity:.5; }

/* --------------------------------------------------------------- карточки */
.co-grid{ display:grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.co-card{ padding: 22px; transition: transform var(--t), box-shadow var(--t); }
.co-card:hover{ transform: translateY(-2px); box-shadow: var(--shadow-lift); }
.co-card .top{ display:flex; align-items:center; gap:11px; margin-bottom: 14px; }
.co-card .co-ava{ width: 42px; height: 42px; border-radius: 13px; font-size: 15px; }
.co-card h3{ font-size: 15.5px; margin-bottom: 3px; }
.co-card .rows{ display:flex; flex-direction:column; gap:8px; margin-top: 14px;
  padding-top: 14px; border-top: 1px solid var(--border); }
.co-card .row{ display:flex; justify-content:space-between; align-items:center;
  font-size: 12.5px; color: var(--muted); font-weight: 600; }

/* ---------------------------------------------------------------- подвал */
.foot{ margin-top: 74px; padding: 34px 0 44px; border-top: 1px solid var(--border);
  color: var(--faint); font-size: 13px; }
.foot-in{ display:flex; align-items:center; gap:16px; flex-wrap:wrap; }

/* Подпись автора: тонкая таблетка, «Developed by» — мелкой разрядкой,
   имя — фирменным градиентом. Подпись, а не баннер: с логотипом за
   внимание не спорит. Градиент от --brand к --brand-glow, а не к
   --violet: фиолетовый в тёмной теме не поднят и тонет в фоне. */
.foot-sign{
  display:inline-flex; align-items:baseline; gap:7px;
  padding: 6px 15px; border-radius: var(--pill);
  background: var(--brand-tint); border: 1px solid var(--brand-line);
  transition: border-color .2s ease, transform .2s ease;
}
.foot-sign:hover{ border-color: var(--brand-glow); transform: translateY(-1px); }
.foot-by{
  font-size: 10.5px; font-weight: 650; letter-spacing: .12em;
  text-transform: uppercase; color: var(--faint);
}
.foot-author{
  font-size: 14px; font-weight: 800; letter-spacing: .02em;
  color: var(--brand);  /* запас, если background-clip: text не поддержан */
  background: linear-gradient(90deg, var(--brand), var(--brand-glow));
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
}
@media (prefers-reduced-motion: reduce){ .foot-sign{ transition: none; } }

/* ------------------------------------------------------------- адаптив */
@media (max-width: 1080px){
  .board-layout{ grid-template-columns: 1fr; }
  .filters{ position: static; }
  .why{ grid-template-columns: 1fr; }
  .co-grid{ grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 860px){
  .stats{ grid-template-columns: repeat(2, 1fr); }
  .head-row{ display:none; }
  .load{ grid-template-columns: 1fr 1fr; row-gap: 10px; }
  .load-price{ text-align:left; }
  .nav{ display:none; }
}
@media (max-width: 620px){
  .wrap{ padding: 0 16px; }
  .co-grid{ grid-template-columns: 1fr; }
  .searchbar{ flex-direction: column; }
  .brandmark-word small{ display:none; }
}

/* ===========================================================================
   Движение
   ---------------------------------------------------------------------------
   Правило одно: анимация объясняет, откуда взялся элемент, и заканчивается.
   Ничего не пульсирует в покое — «дышащий» интерфейс отвлекает от таблицы,
   которую человек пришёл читать, и через минуту начинает раздражать.

   Длительности короткие (.35–.6s), кривая одна на весь проект (--ease), и
   всё уважает системную настройку «уменьшить движение»: для тех, кому от
   анимации физически плохо, она выключается целиком, а не смягчается.
   =========================================================================== */

@keyframes riseIn{
  from{ opacity:0; transform: translate3d(0, 16px, 0) scale(.99); }
  to  { opacity:1; transform: none; }
}
@keyframes blurIn{
  from{ opacity:0; filter: blur(10px); transform: translate3d(0, 12px, 0); }
  to  { opacity:1; filter: none;      transform: none; }
}
@keyframes slideIn{
  from{ opacity:0; transform: translate3d(-14px, 0, 0); }
  to  { opacity:1; transform: none; }
}
@keyframes popIn{
  0%  { opacity:0; transform: scale(.86); }
  60% { opacity:1; transform: scale(1.03); }
  100%{ opacity:1; transform: scale(1); }
}
/* Медленный дрейф светового пятна за стеклом. Единственное, что живёт
   постоянно, — и то настолько медленно (28 s), что замечается только боковым
   зрением: стекло должно выглядеть как стекло, а не как картинка. */
@keyframes drift{
  0%,100%{ transform: translate3d(0,0,0) scale(1); }
  50%    { transform: translate3d(1.5%, -1.5%, 0) scale(1.04); }
}

body::before{ animation: drift 28s ease-in-out infinite; will-change: transform; }

/* Появление на входе. `--i` — порядковый номер, из него считается задержка,
   поэтому стаггер не требует ни одной строчки JS. */
.rise    { animation: riseIn .5s var(--ease) both;  animation-delay: calc(var(--i, 0) * 60ms); }
.rise-blur{ animation: blurIn .62s var(--ease) both; animation-delay: calc(var(--i, 0) * 90ms); }
.rise-x  { animation: slideIn .45s var(--ease) both; animation-delay: calc(var(--i, 0) * 40ms); }
.pop     { animation: popIn .42s var(--ease) both;   animation-delay: calc(var(--i, 0) * 50ms); }

/* Появление по мере прокрутки: до попадания в кадр элемент спрятан,
   в кадре — проигрывает то же самое. */
/* Прятать блок можно только тогда, когда есть кому его показать: класс `js`
   ставится встроенным скриптом в <head>. Если скрипты выключены или файл не
   доехал, правило не сработает вовсе — и половина страницы не исчезнет. */
.js .reveal{ opacity: 0; }
.reveal.in{ animation: riseIn .55s var(--ease) both; animation-delay: calc(var(--i, 0) * 70ms); }

/* Строка биржи: подъезжает слева, потому что читается тоже слева направо. */
.load{ animation: slideIn .4s var(--ease) both; animation-delay: calc(var(--i, 0) * 28ms); }

/* Счётчик на главной: пока цифра набирается, она не должна прыгать по
   ширине — моноширинные цифры удерживают колонку на месте. */
.stat b{ font-variant-numeric: tabular-nums; }

/* Мелкая моторика */
/* Раньше здесь стояло `will-change: transform` на каждой кнопке и каждом
   стекле. Это обещание браузеру «сейчас буду двигать», по которому он заводит
   отдельный слой в памяти — и держит его всё время, пока страница открыта,
   хотя карточка стоит на месте, пока на неё не навели. Слой нужен ровно там,
   где движение действительно идёт покадрово за курсором. */
.tilt.live{ will-change: transform; }
.nav a, .langs a{ transition: background var(--t), color var(--t), transform var(--t); }
.nav a:active, .langs a:active{ transform: scale(.94); }
.co-ava{ transition: transform var(--t), box-shadow var(--t); }
.load:hover .co-ava{ transform: scale(1.08) rotate(-3deg); }
.trust-bar i{ transition: width .8s var(--ease); }
.searchbar input{ transition: border-color var(--t), box-shadow var(--t), transform var(--t); }
.searchbar input:focus{ transform: translateY(-1px); }
.tag{ animation: popIn .38s var(--ease) both; animation-delay: calc(var(--i, 0) * 60ms); }
.badge{ animation: popIn .34s var(--ease) both; }

/* Системная настройка сильнее любых наших намерений. */
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .reveal{ opacity: 1; }
}

/* ------------------------------------------------------- вход и регистрация */
.auth-wrap{ display:grid; place-items:center; min-height: calc(100vh - 64px); padding: 40px 0 80px; }
.auth-card{ width:100%; max-width: 430px; padding: 34px 32px 28px; border-radius: var(--r-xl); }
.auth-card h1{ font-size: 27px; margin-bottom: 7px; }
.auth-sub{ font-size: 14px; color: var(--muted); margin-bottom: 22px; line-height:1.5; }
.auth-foot{ margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--border);
  font-size: 13.5px; color: var(--muted); text-align:center; }
.auth-foot a, .linkish{ color: var(--brand); font-weight: 700; }
.linkish{ background:none; border:0; padding:0; font:inherit; cursor:pointer; }
.auth-foot a:hover, .linkish:hover{ text-decoration: underline; }

/* Четыре шага регистрации: видно, сколько пройдено и сколько осталось. */
.auth-steps{ display:flex; gap:6px; margin-bottom: 22px; }
.auth-step{ flex:1; height:4px; border-radius: var(--pill); background: var(--border);
  transition: background .4s var(--ease); }
.auth-step.done{ background: var(--brand-line); }
.auth-step.now{ background: var(--brand); }

.code-input{
  font-size: 26px !important; font-weight: 800; letter-spacing: .38em;
  text-align:center; font-variant-numeric: tabular-nums; padding: 15px !important;
}

.note{ padding: 11px 15px; border-radius: var(--r-sm); font-size: 13.5px;
  font-weight: 600; margin-bottom: 14px; border:1px solid transparent; }
.note-danger { background: var(--danger-bg); color: var(--danger); border-color: var(--danger-line); }
.note-warning{ background: var(--warn-bg);   color: var(--warn);   border-color: var(--warn-line); }
.note-success{ background: var(--ok-bg);     color: var(--ok);     border-color: var(--ok-line); }
.note-info   { background: var(--brand-tint);   color: var(--brand); border-color: var(--brand-line); }

/* Выбор роли: карточки, а не выпадающий список — выбор из трёх вариантов,
   у каждого своё объяснение, и его надо прочитать, а не развернуть. */
.role-grid{ display:flex; flex-direction:column; gap:10px; }
.role-card{
  display:grid; grid-template-columns: 42px 1fr; grid-template-rows: auto auto;
  column-gap: 14px; align-items:center; cursor:pointer;
  padding: 15px 17px; border-radius: var(--r-md);
  border: 1.5px solid var(--border); background: var(--glass-bottom);
  transition: border-color var(--t), background var(--t), transform var(--t);
}
.role-card:hover{ border-color: var(--brand-line); transform: translateY(-1px); }
.role-card.on, .role-card:has(input:checked){
  border-color: var(--brand); background: var(--brand-tint);
  box-shadow: 0 0 0 4px var(--brand-tint);
}
.role-card input{ position:absolute; opacity:0; pointer-events:none; }
.role-ic{ grid-row: 1 / 3; font-size: 27px; text-align:center; }
.role-card b{ font-size: 14.5px; }
.role-card small{ font-size: 12.5px; color: var(--muted); line-height:1.4; }

/* Кто вошёл — в шапке */
.usertag{ display:flex; align-items:center; gap:8px; padding: 5px 13px 5px 5px;
  border-radius: var(--pill); background: var(--brand-tint);
  border: 1px solid var(--brand-line); transition: transform var(--t); }
.usertag:hover{ transform: translateY(-1px); }
.usertag-ava{ width:26px; height:26px; border-radius:50%; flex:none;
  display:grid; place-items:center; font-size:12px; font-weight:800; color:#fff;
  background: linear-gradient(140deg, var(--brand-fill), var(--brand-soft)); }
.usertag-name{ font-size:13px; font-weight:700; max-width:120px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
@media (max-width: 720px){ .usertag-name{ display:none; } }

/* ------------------------------------------------- карточка груза и профиль */
.backlink{ display:inline-block; margin-bottom: 16px; font-size: 13.5px;
  font-weight: 700; color: var(--muted); transition: color var(--t), transform var(--t); }
.backlink:hover{ color: var(--brand); transform: translateX(-3px); }

.profile-head{ display:flex; justify-content:space-between; gap: 26px;
  flex-wrap: wrap; align-items:center; margin-bottom: 16px; }
.profile-id{ display:flex; align-items:center; gap:16px; min-width:0; }
.profile-ava{ width:62px !important; height:62px !important; border-radius:20px !important;
  font-size:25px !important; }
.profile-head h1{ font-size: clamp(21px, 2.6vw, 29px); margin-bottom:8px; }
.profile-badges{ display:flex; gap:7px; flex-wrap:wrap; }

.profile-scores{ display:flex; gap: 12px; flex-wrap:wrap; }
.score-box{ min-width: 132px; padding: 13px 17px; border-radius: var(--r-md);
  background: var(--brand-tint); border: 1px solid var(--brand-line); }
.score-label{ display:block; font-size:10.5px; font-weight:750; letter-spacing:.06em;
  text-transform:uppercase; color: var(--faint); margin-bottom:3px; }
.score-box b{ font-size: 27px; font-weight: 800; letter-spacing:-.03em;
  color: var(--brand); font-variant-numeric: tabular-nums; }
.score-box i{ font-style:normal; font-size:13px; color: var(--faint); font-weight:700; }
.score-note{ display:block; font-size:11.5px; color: var(--faint); font-weight:600; margin-top:2px; }
.trust-bar.wide{ width:100%; margin-top:7px; height:6px; }

.profile-body{ display:grid; grid-template-columns: 1fr 330px; gap: 16px; align-items:start; }
.sec-h{ font-size:16.5px; margin-bottom:14px; display:flex; align-items:baseline; gap:9px; }
.sec-h .count{ font-size:12.5px; color:var(--faint); font-weight:700; }

.kv{ display:flex; justify-content:space-between; align-items:center; gap:12px;
  padding: 8px 0; font-size:13.5px; border-bottom: 1px solid var(--border); }
.kv:last-child{ border-bottom:0; }
.kv span{ color: var(--muted); font-weight:600; }
.kv b{ font-weight:700; }

.mini-row{ display:grid; grid-template-columns: 1.4fr 1.2fr .5fr .8fr; gap:12px;
  align-items:center; padding: 11px 12px; border-radius: var(--r-sm);
  font-size:13.5px; transition: background var(--t); }
.mini-row:hover{ background: var(--brand-tint); }
.mini-row b{ font-weight:750; }
.mini-row span{ color: var(--muted); }

.spec-grid{ display:grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.spec{ padding: 13px 15px; border-radius: var(--r-sm); background: var(--brand-tint); }
.spec span{ display:block; font-size:10.5px; font-weight:750; letter-spacing:.05em;
  text-transform:uppercase; color: var(--faint); margin-bottom:3px; }
.spec b{ font-size:16px; font-weight:750; }

.cargo-route{ display:flex; align-items:center; gap: 22px; flex-wrap:wrap; }
.cargo-city{ font-size: clamp(21px, 3vw, 31px); font-weight:800; letter-spacing:-.03em; display:block; }
.cargo-route small{ font-size:11.5px; color:var(--faint); font-weight:750; letter-spacing:.08em; }
.cargo-arrow{ text-align:center; color: var(--brand); }
.cargo-arrow span{ font-size:27px; font-weight:800; display:block; line-height:1; }
.cargo-arrow small{ font-size:11.5px; color:var(--faint); font-weight:700; }

.price-big{ font-size: clamp(23px, 3vw, 31px); font-weight:800; letter-spacing:-.03em;
  color: var(--brand); font-variant-numeric: tabular-nums; }
.price-big.free{ color: var(--faint); font-size: 21px; }
.price-note{ font-size:12.5px; color:var(--faint); font-weight:650; margin-top:3px; }
.co-side{ display:block; transition: transform var(--t), box-shadow var(--t); }
.co-side:hover{ transform: translateY(-2px); box-shadow: var(--shadow-lift); }

.stars-breakdown{ margin-bottom: 20px; }
.star-row{ display:grid; grid-template-columns: 34px 1fr 26px; gap:9px; align-items:center;
  font-size:12px; color:var(--muted); font-weight:650; margin-bottom:5px; }
.star-bar{ height:6px; border-radius:var(--pill); background:var(--border); overflow:hidden; }
.star-bar i{ display:block; height:100%; background: var(--brand); border-radius:var(--pill);
  transition: width .9s var(--ease); }
.star-n{ text-align:right; font-variant-numeric: tabular-nums; }

.review{ padding: 15px 0; border-top: 1px solid var(--border); }
.review-top{ display:flex; align-items:center; gap:9px; flex-wrap:wrap; margin-bottom:7px; }
.review-kind{ font-size:15px; }
.review-top b{ color: var(--brand); letter-spacing:.06em; font-size:13.5px; }
.review-when{ font-size:12px; color:var(--faint); font-weight:650; }
.review p{ font-size:14px; color:var(--muted); line-height:1.6; }
.review-reply{ margin-top:11px; padding: 12px 15px; border-radius: var(--r-sm);
  background: var(--brand-tint); border-left: 3px solid var(--brand); }
.review-reply b{ font-size:12px; color:var(--brand); display:block; margin-bottom:4px; }
.review-reply p{ font-size:13.5px; }

@media (max-width: 980px){
  .profile-body{ grid-template-columns: 1fr; }
  .spec-grid{ grid-template-columns: repeat(2, 1fr); }
  .mini-row{ grid-template-columns: 1fr 1fr; row-gap:6px; }
}

/* --------------------------------------------------------- боковые виджеты */
.side-card{ border-radius: var(--r-md); overflow:hidden; }
.side-h{ padding: 12px 16px; font-size: 13px; font-weight: 750;
  background: var(--brand-tint); border-bottom: 1px solid var(--brand-line);
  color: var(--brand); display:flex; justify-content:space-between; align-items:center; gap:8px; }
.side-h small{ font-size: 10.5px; color: var(--faint); font-weight: 650; }
.side-body{ padding: 14px 16px; }
.side-note{ font-size: 10.5px; color: var(--faint); font-weight: 600;
  margin-top: 10px; line-height:1.45; }
.side-form .field + .field{ margin-top: 9px; }
.side-form .btn{ margin-top: 12px; }
.side-pair{ display:grid; grid-template-columns: 1fr 1fr; gap: 7px; }

.rate{ display:flex; align-items:baseline; gap:8px; padding: 6px 0;
  border-bottom: 1px solid var(--border); }
.rate:last-of-type{ border-bottom:0; }
.rate-code{ font-size: 11px; font-weight: 800; letter-spacing:.05em;
  color: var(--brand); background: var(--brand-tint); padding: 3px 7px;
  border-radius: 6px; min-width: 44px; text-align:center; }
.rate b{ font-size: 16px; font-weight: 800; font-variant-numeric: tabular-nums; }
.rate-unit{ font-size: 12px; color: var(--faint); font-weight:700; }
.rate-delta{ margin-left:auto; font-size: 11.5px; font-weight: 750;
  font-variant-numeric: tabular-nums; }
.rate-delta.up{ color: var(--ok); }
.rate-delta.down{ color: var(--danger); }

.dist{ padding: 9px 0; border-bottom: 1px dashed var(--border); }
.dist:last-of-type{ border-bottom:0; }
.dist b{ display:block; font-size: 13px; font-weight: 750; }
.dist span{ font-size: 11.5px; color: var(--muted); font-weight: 600; }

.price-row{ display:block; padding: 9px 0; border-bottom: 1px dashed var(--border);
  transition: background var(--t); border-radius: 6px; }
.price-row:last-of-type{ border-bottom:0; }
.price-row:hover{ background: var(--brand-tint); }
.price-row b{ display:block; font-size: 12.5px; font-weight: 750; margin-bottom:2px; }
.price-row span{ display:flex; justify-content:space-between; align-items:baseline; gap:8px; }
.price-row em{ font-style:normal; font-size: 14px; font-weight: 800; color: var(--brand);
  font-variant-numeric: tabular-nums; }
.price-row i{ font-style:normal; font-size: 11.5px; color: var(--faint); font-weight: 700; }

/* Три колонки: фильтры, доска, справки. */
.board-layout{ grid-template-columns: 246px 1fr 262px; }
@media (max-width: 1240px){
  .board-layout{ grid-template-columns: 232px 1fr; }
  .side-col{ grid-column: 1 / -1; display:grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap:12px; }
  .side-col > *{ margin:0 !important; }
}
@media (max-width: 1080px){ .board-layout{ grid-template-columns: 1fr; } }

/* ===========================================================================
   Телефон
   ---------------------------------------------------------------------------
   Не «уменьшенный ноутбук», а другой порядок чтения. Таблица из шести колонок
   на узком экране нечитаема в любом масштабе, поэтому строка биржи становится
   карточкой, а разделы уезжают вниз — туда, куда дотягивается большой палец.
   =========================================================================== */

/* Страховка от горизонтальной прокрутки: одна непереносящаяся строка где
   угодно — и весь сайт едет вбок, что на телефоне читается как поломка. */
html, body{ max-width: 100%; overflow-x: hidden; }

.filters-sum{ display:none; }

@media (max-width: 1080px){
  .filters-sum{
    display:flex; align-items:center; gap:8px; cursor:pointer; list-style:none;
    padding: 15px 20px; margin: -22px -22px 0;
    font-size: 14px; font-weight: 750; color: var(--brand);
  }
  .filters-sum::-webkit-details-marker{ display:none; }
  .filters-sum::after{ content:'▾'; margin-left:auto; transition: transform var(--t); }
  .filters[open] .filters-sum{ margin-bottom: 16px; border-bottom: 1px solid var(--border); }
  .filters[open] .filters-sum::after{ transform: rotate(180deg); }
}

@media (max-width: 720px){
  .topbar-in{ height: 56px; gap: 10px; }
  .brandmark-word{ font-size: 14px; }
  .langs a{ padding: 4px 9px; font-size: 11.5px; }
  .nav{ display:none; }

  .hero{ padding: 38px 0 26px; }
  .hero h1{ font-size: 34px; }
  .hero-cta{ flex-direction: column; }
  .hero-cta .btn{ width: 100%; }
  .searchbar{ flex-direction: column; }
  .searchbar .btn{ width: 100%; }
  .search-hint{ padding-left: 4px; }
  .stats{ grid-template-columns: 1fr 1fr; gap: 10px; }
  .stat{ padding: 16px; }

  /* Чекбоксы фильтров: каждый на своей строке. inline-flex ставил их в ряд,
     и второй уезжал за край экрана. */
  .check{ display:flex; width:100%; }

  /* Строка биржи -> карточка. Значения подписаны: «20.5 т» и «84 м³» друг под
     другом без подписи ничего не объясняют. */
  .head-row{ display:none; }
  .load{
    display:block; padding: 15px 16px; margin-bottom: 8px;
    border: 1px solid var(--border); background: var(--glass-bottom);
  }
  .load + .load{ margin-top: 0; }
  .load > div{ display:flex; justify-content:space-between; align-items:baseline;
    gap: 12px; padding: 4px 0; }
  .load > div:first-child{ display:block; padding-bottom: 8px; margin-bottom: 6px;
    border-bottom: 1px solid var(--border); }
  .load-route{ font-size: 16px; }
  .load-price{ text-align:right; font-size: 17px; }
  .load .co{ justify-content: flex-end; }

  .co-grid{ grid-template-columns: 1fr; }
  .side-col{ grid-template-columns: 1fr !important; }
  .profile-body{ grid-template-columns: 1fr; }
  .profile-head{ flex-direction: column; align-items: flex-start; }
  .profile-scores{ width:100%; }
  .score-box{ flex:1; min-width:0; }
  .spec-grid{ grid-template-columns: 1fr 1fr; }
  .mini-row{ grid-template-columns: 1fr; row-gap: 3px; }
  .auth-card{ padding: 26px 20px 22px; }
  .code-input{ font-size: 22px !important; letter-spacing: .28em; }
}

/* Нижняя панель разделов — как в любом приложении на телефоне. */
.tabbar{ display:none; }
@media (max-width: 720px){
  .tabbar{
    display:flex; position: fixed; left:0; right:0; bottom:0; z-index: 60;
    background: var(--glass-strong); border-top: 1px solid var(--glass-line);
    backdrop-filter: blur(24px) saturate(180%);
    -webkit-backdrop-filter: blur(24px) saturate(180%);
    padding: 7px 6px calc(7px + env(safe-area-inset-bottom));
  }
  .tabbar a{
    flex:1; display:flex; flex-direction:column; align-items:center; gap:3px;
    padding: 6px 2px; border-radius: var(--r-sm);
    font-size: 10.5px; font-weight: 700; color: var(--faint);
    transition: color var(--t), background var(--t);
  }
  .tabbar a span{ font-size: 18px; line-height:1; }
  .tabbar a.on{ color: var(--brand); background: var(--brand-tint); }
  /* Место под панель, иначе она накрывает подвал. */
  body{ padding-bottom: 70px; }
}

/* Переполнение по ширине на телефоне.
   Причина не в общей ширине, а в том, что элемент во flex по умолчанию не
   сжимается меньше своего содержимого: длинное название компании в nowrap
   распирало карточку, и вся страница уезжала вбок. min-width:0 снимает этот
   запрет и включает многоточие, ради которого overflow и ставился. */
.co{ min-width: 0; }
.co > div{ min-width: 0; }
.load > div > *{ min-width: 0; }
.load-title, .load-num{ min-width: 0; }

/* Колонкам разрешено сжиматься меньше текста (см. minmax выше) — значит текст
   надо чем-то останавливать, иначе он молча уедет под соседнюю колонку и
   обрежется на полубукве краем строки. Маршрут и название груза — одна
   строка с многоточием: «Алматы → Пет…» читается, склейка двух колонок нет. */
.load-route, .load-title, .load-num{
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* «20.5 т · 80.4 м³» — одно значение, а не два: перенос «м³» на вторую строку
   делал строку выше соседних, и список переставал читаться как таблица.
   Колонке веса добавлено места ровно под самое длинное значение. */

@media (max-width: 720px){
  /* В шапке на 390 пикселях не помещаются логотип, три языка и две кнопки.
     Регистрация уходит: со страницы входа на неё есть ссылка, а вход нужен
     чаще — возвращаются больше, чем регистрируются. */
  .topbar .btn-primary{ display: none; }
  .usertag-name{ display: none; }
  .load .co{ max-width: 100%; }
  .load .co-name{ max-width: 190px; }
  /* Иконка транспорта одна в строке ничего не объясняет — оставляем подпись. */
  .load-num > span{ white-space: nowrap; }
}

/* Вертикальные отступы страницы — переменными, а не инлайновым `padding`.
   Инлайновая запись «padding: 34px 0 60px» обнуляла боковые отступы .wrap,
   и на телефоне текст упирался в края экрана, а карточки выдавливали
   страницу вбок. Здесь трогаются только верх и низ. */
.page{ padding-top: var(--pt, 34px); padding-bottom: var(--pb, 60px); }

/* Классическая ловушка grid и flex: элемент по умолчанию не сжимается меньше
   своего содержимого (min-width: auto). Достаточно одного <select> с длинным
   вариантом — «Открытая / платформа» — и колонка распирает страницу шире
   экрана, а обрезается при этом всё подряд, включая шапку. Снимаем запрет
   там, где содержимое обязано ужиматься. */
.board-layout > *,
.profile-body > *,
.co-grid > *,
.side-col > *{ min-width: 0; }
select, input, textarea{ min-width: 0; }
.searchbar input{ min-width: 0; }

/* Три колонки — только там, где доске действительно хватает места.
   На 1500 px виджеты съедали ширину у самой таблицы: названия компаний
   ужимались до «ТО…», а подписи наезжали друг на друга. Доска — главное на
   странице, справки — второстепенное, поэтому уступают они, а не она. */
@media (min-width: 1560px){
  .board-layout{ grid-template-columns: 246px minmax(0, 1fr) 262px; }
  .side-col{ display: block; }
  .side-col > * + *{ margin-top: 12px; }
}
@media (max-width: 1559px){
  .board-layout{ grid-template-columns: 232px minmax(0, 1fr); }
  .side-col{
    grid-column: 1 / -1;
    display: grid; gap: 12px;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  }
  .side-col > *{ margin: 0 !important; }
}
@media (max-width: 1080px){
  .board-layout{ grid-template-columns: minmax(0, 1fr); }
}

/* Компании нужно больше места, чем весу: «ТОО «Kazakh Trans Line»» — это
   то, ради чего человек и смотрит в строку, а вес читается и в четыре знака.

   Ширины заданы через minmax, а не голыми fr и auto, и вот почему. Каждая
   строка биржи — самостоятельная сетка: они стоят друг под другом, но ничего
   друг о друге не знают. Голый `1.45fr` — это `minmax(auto, 1.45fr)`, то есть
   колонке запрещено сжиматься меньше своего содержимого. Длинный маршрут или
   длинное название груза раздвигали колонку в своей строке — и всё, что
   правее, съезжало вправо ровно в этой строке. Аватарки компаний вставали
   лесенкой, хотя в разметке колонка одна.

   `minmax(0, …)` снимает этот запрет, а последняя колонка получает пол в
   пикселях вместо `auto`: и нижняя, и верхняя граница у всех колонок теперь
   не зависят от текста, поэтому во всех строках они считаются одинаково и
   встают в одну вертикаль. Расплата — обрезка многоточием, она ниже. */
.load, .head-row{ grid-template-columns: minmax(0,1.4fr) minmax(0,1.1fr) minmax(0,.88fr) minmax(0,.68fr) minmax(0,1.55fr) minmax(120px,.8fr); }

/* Ячейка транспорта: «Мультимодальные» длиннее своей колонки и наезжало на
   соседнюю. Обрезаем многоточием — полное слово остаётся в подсказке. */
.load-num[title]{ display: flex; align-items: center; gap: 5px; min-width: 0; }
.load-num[title] > span{
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}

/* Полоса Trust Score должна быть блочной.
   Внутри .trust это работало само: там flex, а он блокирует потомков. В
   .score-box флекса нет, span оставался строчным — а к строчному элементу
   ширина и высота не применяются вовсе. Полоса раздувалась по содержимому и
   с радиусом 999px превращалась в зелёный блин поверх карточки. */
.trust-bar{ display: block; flex: none; }

/* «Забыли пароль?» — рядом с полем, а не в подвале формы: ищут её ровно в тот
   момент, когда пароль не подошёл, и глаз в этот момент на поле пароля. */
.forgot-link{ align-self: flex-end; font-size: 12.5px; font-weight: 650;
  color: var(--muted); margin-top: -4px; }
.forgot-link:hover{ color: var(--brand); text-decoration: underline; }


/* ===========================================================================
   Движение II — «жидкое стекло»
   ---------------------------------------------------------------------------
   Первый слой движения объяснял, откуда взялся элемент, и замолкал. Этого
   мало: интерфейс, который откликается только на появление, ощущается как
   распечатка. Здесь добавлено то, что отвечает на действие — на курсор, на
   нажатие, на прокрутку, — и то, что связывает страницы между собой.

   Три правила, которым подчинено всё ниже:
     1. Пружина вместо линейного разгона. Настоящие предметы не тормозят
        мгновенно, они чуть проскакивают цель и возвращаются.
     2. Движение привязано к жесту. Прокрутка и курсор — это ввод; отклик на
        них не длится «столько-то секунд», он идёт ровно настолько, насколько
        человек двинул.
     3. Ничего не отвлекает от таблицы. Всё постоянное — медленнее шести
        секунд и слабее пятнадцати процентов прозрачности.
   =========================================================================== */

/* --------------------------------------------------------------- токены */

/* Стекло как заливка. Раньше `--glass`, `--glass-strong` и `--glass-line`
   использовались в шапке, кнопках, полях и нижней панели, но нигде не были
   объявлены: браузер выбрасывал такое свойство целиком, и шапка оставалась
   полностью прозрачной — размывать было нечем. */
:root{
  --glass:        linear-gradient(180deg, rgba(255,255,255,.76), rgba(255,255,255,.58));
  --glass-strong: linear-gradient(180deg, rgba(255,255,255,.94), rgba(255,255,255,.78));
  --glass-line:   rgba(255,255,255,.90);

  /* Кривые. `--glide` — вход и выход без отскока, `--spring` — с коротким
     проскоком, `--bounce` — с заметным, только для мелочей вроде иконки. */
  --glide:  cubic-bezier(.22, 1, .36, 1);
  --spring: cubic-bezier(.34, 1.45, .5, 1);
  --bounce: cubic-bezier(.3, 1.7, .45, 1);

  --t-fast: .16s;
  --t-mid:  .34s;
  --t-slow: .62s;

  --sheen: rgba(255,255,255,.55);
}

/* Тёмные значения — те же два состояния, что и у остальных токенов выше:
   системная тёмная (пока светлая не выбрана руками) и выбранная руками. */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --glass:        linear-gradient(180deg, rgba(38,50,88,.72), rgba(16,24,48,.56));
    --glass-strong: linear-gradient(180deg, rgba(54,68,112,.60), rgba(28,38,70,.46));
    --glass-line:   rgba(255,255,255,.15);
    --sheen:        rgba(150,180,255,.30);
  }
}
:root[data-theme="dark"]{
    --glass:        linear-gradient(180deg, rgba(38,50,88,.72), rgba(16,24,48,.56));
    --glass-strong: linear-gradient(180deg, rgba(54,68,112,.60), rgba(28,38,70,.46));
    --glass-line:   rgba(255,255,255,.15);
    --sheen:        rgba(150,180,255,.30);
}

/* Кубическая кривая — только приближение пружины: она проскакивает один раз
   и всё. `linear()` описывает затухание честно, по точкам, поэтому предмет
   доезжает, качается и успокаивается — как вещь, а не как график. */
@supports (animation-timing-function: linear(0, 1)){
  :root{
    --spring: linear(0, 0.0233, 0.0842, 0.1709, 0.2733, 0.3829, 0.4931, 0.5989,
                     0.6966, 0.7839, 0.8594, 0.9228, 0.974, 1.0139, 1.0434,
                     1.0638, 1.0763, 1.0824, 1.0833, 1.0804, 1.0745, 1.0668,
                     1.058, 1.0488, 1.0397, 1.031, 1.0231, 1.0161, 1.0101,
                     1.0051, 1.0011, 0.998, 0.9958, 0.9943, 0.9934, 0.9931,
                     0.9931, 0.9934, 0.994, 0.9946, 0.9954, 0.9962, 1);
    --bounce: linear(0, 0.0375, 0.1364, 0.2764, 0.4387, 0.6068, 0.7674, 0.9105,
                     1.0296, 1.121, 1.1843, 1.2208, 1.2335, 1.2267, 1.2051,
                     1.1732, 1.1357, 1.0964, 1.0585, 1.0245, 0.996, 0.9739,
                     0.9583, 0.9491, 0.9455, 0.9466, 0.9514, 0.9586, 0.9672,
                     0.9764, 0.9853, 0.9934, 1.0002, 1.0056, 1.0094, 1.0117,
                     1.0127, 1.0125, 1.0115, 1.0099, 1.0079, 1.0058, 1);
  }
}

/* ------------------------------------------------- переход между страницами */
/* Переход между документами. Без него каждая ссылка — это белая вспышка и
   рывок: браузер выбрасывает старую страницу и рисует новую с нуля. Здесь
   старая уходит вглубь и размывается, новая приезжает снизу, а шапка и
   нижняя панель названы отдельно и потому не участвуют в переходе вовсе —
   они остаются на месте, как рама вокруг сменяемой картины. */
@view-transition{ navigation: auto; }

::view-transition-old(root){ animation: vtLeave .30s var(--glide) both; }
::view-transition-new(root){ animation: vtEnter .46s var(--glide) both; }

@keyframes vtLeave{
  to{ opacity: 0; transform: translate3d(0, -10px, 0) scale(.985); filter: blur(7px); }
}
@keyframes vtEnter{
  from{ opacity: 0; transform: translate3d(0, 14px, 0) scale(1.014); filter: blur(9px); }
}

.topbar{ view-transition-name: topbar; }
.tabbar{ view-transition-name: tabbar; }
.foot  { view-transition-name: foot;   }

/* ------------------------------------------------------------------- фон */
/* Свет за стеклом теперь ещё и сносится курсором. Смещение крошечное (полтора
   процента экрана), но именно оно превращает фон из картинки в глубину:
   слой под стеклом двигается не так, как слой над ним. */
@keyframes drift{
  0%, 100%{ transform: translate3d(var(--px, 0px), var(--py, 0px), 0) scale(1); }
  50%     { transform: translate3d(calc(var(--px, 0px) + 1.6%),
                                   calc(var(--py, 0px) - 1.6%), 0) scale(1.06); }
}
body::before{ animation: drift 24s ease-in-out infinite; }

/* Сетка второго слоя уезжает по мере прокрутки — привязана к жесту, а не ко
   времени: остановились — остановилась и она. */
@supports (animation-timeline: scroll()){
  body::after{
    animation: gridPan linear both;
    animation-timeline: scroll(root block);
  }
  @keyframes gridPan{
    to{ background-position: 0 -180px, -120px 0; opacity: .18; }
  }
}

/* ----------------------------------------------------------------- шапка */
.topbar{
  transition: box-shadow var(--t-slow) var(--glide),
              backdrop-filter var(--t-slow) var(--glide);
}

/* Полоса прочитанного. Один пиксель информации о том, сколько осталось —
   и единственный элемент, который движется ровно на столько, на сколько
   человек прокрутил. */
.progress{
  position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  transform: scaleX(var(--p, 0)); transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--brand), var(--violet) 45%, var(--cyan));
  box-shadow: 0 0 12px rgba(91,124,255,.6);
  pointer-events: none; border-radius: var(--pill);
}
@supports (animation-timeline: scroll()){
  .progress{
    animation: progressGrow linear both;
    animation-timeline: scroll(root block);
  }
  @keyframes progressGrow{ from{ transform: scaleX(0); } to{ transform: scaleX(1); } }

  /* Шапка подбирается на первых полутора экранах: становится ниже и плотнее,
     как только под ней появляется содержимое, которое надо от неё отделить. */
  .topbar-in{
    animation: barCondense linear both;
    animation-timeline: scroll(root block);
    animation-range: 0 160px;
  }
  @keyframes barCondense{ to{ height: 54px; } }
}

/* Жидкая таблетка в меню. Раньше подсветка просто перекрашивала фон нужной
   ссылки — на глаз это мигание в двух местах сразу. Теперь подложка одна и
   она переезжает: взгляд следит за предметом, а не ищет, где загорелось. */
.nav{ position: relative; }
.nav a{ position: relative; z-index: 1; }
.nav a:hover, .nav a.on{ background: transparent; }
.nav-pill{
  position: absolute; left: 0; top: 50%; z-index: 0;
  width: var(--w, 0px); height: 34px;
  transform: translate3d(var(--x, 0px), -50%, 0) scaleX(var(--sx, 1));
  background: var(--brand-tint); border: 1px solid var(--brand-line);
  border-radius: var(--pill); opacity: var(--o, 0);
  pointer-events: none;
  transition: transform .5s var(--spring), width .5s var(--spring),
              opacity var(--t-mid) var(--glide);
}

/* ------------------------------------------------------------ блик по стеклу */
/* Раньше эта точка отражения ходила за курсором по всем карточкам сразу.
   Убрано намеренно: на странице, где карточек десяток, свет зажигался под
   каждой, мимо которой проносишь мышь, и таблица начинала мигать вместо того,
   чтобы читаться. Слой остался — по нему проходит свет ровно один раз, когда
   на карточке дощёлкивает цифра. */
.glass::after{
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; opacity: 0;
  background: radial-gradient(240px 240px at var(--mx, 50%) var(--my, 40%),
                              var(--sheen), transparent 68%);
  mix-blend-mode: plus-lighter;
}

/* -------------------------------------------------------- наклон карточек */
/* Карточка кренится к курсору на пару градусов. Больше — и это уже аттракцион;
   столько — и она просто перестаёт быть наклейкой на фоне. */
.tilt{
  transform: perspective(1000px)
             rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg))
             translate3d(0, var(--lift, 0px), 0) scale(var(--sc, 1));
  transition: transform var(--t-slow) var(--glide),
              box-shadow var(--t-mid) var(--glide);
}
/* Наклон повторён и в :hover — иначе собственное правило карточки
   (`.co-card:hover`) со своим `transform: translateY(...)` перебило бы его по
   весу селектора ровно в тот момент, когда наклон и нужен. */
.tilt:hover{
  --lift: -4px; --sc: 1.012;
  transform: perspective(1000px)
             rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg))
             translate3d(0, var(--lift, 0px), 0) scale(var(--sc, 1));
  box-shadow: var(--shadow-lift);
}
/* Пока курсор внутри, наклон должен успевать за ним, а не догонять с
   полусекундным опозданием. Отпустили — возвращается уже мягко. */
.tilt.live{ transition: transform .12s linear, box-shadow var(--t-mid) var(--glide); }

/* ---------------------------------------------------------------- кнопки */
.btn{
  position: relative; overflow: hidden;
  transition: transform .44s var(--spring), box-shadow var(--t-mid) var(--glide),
              background var(--t-mid), color var(--t-mid);
}
/* Нажатие обязано быть быстрым: палец уже на экране, ждать отклика нельзя.
   Отпускание — пружиной. */
.btn:active{ transform: scale(.94); transition-duration: .09s; }

.btn-primary::after{
  content: ''; position: absolute; top: -20%; bottom: -20%; width: 42%;
  left: -60%; transform: skewX(-18deg); pointer-events: none; opacity: 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.5), transparent);
}
.btn-primary:hover::after{ animation: sheenSweep .85s var(--glide); }
@keyframes sheenSweep{
  from{ left: -60%; opacity: .9; }
  to  { left: 130%; opacity: 0; }
}

/* Круг от касания. Точка, из которой он расходится, — там, где палец, а не
   в центре кнопки: это единственное, что доказывает, что нажали именно вы. */
.ripple{
  position: absolute; left: var(--x); top: var(--y);
  width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%;
  background: rgba(255,255,255,.45); pointer-events: none;
  animation: rippleOut .62s var(--glide) forwards;
}
.btn-ghost .ripple, .load .ripple{ background: rgba(0,32,138,.16); }
@keyframes rippleOut{ to{ transform: scale(26); opacity: 0; } }

/* ------------------------------------------------------- заголовок и текст */
/* Заголовок набирается словами. Каждое выезжает из-под собственной кромки —
   отсюда `overflow: hidden` на обёртке: без неё слово не выезжает, а просто
   всплывает, и строка теряет край, от которого отталкивается. */
.hero h1 .w{
  display: inline-block; overflow: hidden; vertical-align: bottom;
  padding: .12em .04em .14em; margin: -.12em -.04em -.14em;
}
.hero h1 .w > i{
  display: inline-block; font-style: inherit;
  animation: wordUp .95s var(--spring) both;
  animation-delay: calc(var(--i, 0) * 52ms);
}
@keyframes wordUp{
  from{ opacity: 0; transform: translate3d(0, 108%, 0) rotate(3deg); filter: blur(6px); }
  to  { opacity: 1; transform: none; filter: none; }
}

/* Ключевое слово переливается фирменным градиентом. Медленно — семь секунд на
   проход: это подсветка смысла, а не бегущая строка. */
@supports ((-webkit-background-clip: text) or (background-clip: text)){
  .hero h1 em{
    background: linear-gradient(100deg, var(--brand) 18%, var(--violet) 38%,
                                var(--cyan) 52%, var(--brand-soft) 68%, var(--brand) 88%);
    background-size: 280% 100%;
    -webkit-background-clip: text; background-clip: text;
    color: transparent;
    animation: hueFlow 7s linear infinite;
  }
}
@keyframes hueFlow{
  from{ background-position: 0% 50%; }
  to  { background-position: 280% 50%; }
}

/* --------------------------------------------------------- появление блока */
/* Прежний вход был подъёмом на 16 пикселей. Теперь блок ещё и наводится на
   резкость: размытие снимает ощущение, что элемент лежал за краем экрана и
   его просто подвинули. */
@keyframes glideUp{
  from{ opacity: 0; transform: translate3d(0, 26px, 0) scale(.97); filter: blur(12px); }
  to  { opacity: 1; transform: none; filter: none; }
}
.reveal.in{
  animation: glideUp .85s var(--glide) both;
  animation-delay: calc(var(--i, 0) * 70ms);
}
.rise     { animation: glideUp .7s var(--glide) both; animation-delay: calc(var(--i, 0) * 60ms); }
.rise-blur{ animation: glideUp .9s var(--glide) both; animation-delay: calc(var(--i, 0) * 90ms); }
.pop      { animation: popIn .55s var(--bounce) both; animation-delay: calc(var(--i, 0) * 50ms); }
.tag      { animation: popIn .5s var(--bounce) both;  animation-delay: calc(var(--i, 0) * 55ms); }

/* Первый экран отъезжает вглубь по мере прокрутки — как крупный заголовок в
   системных приложениях, который не исчезает рывком, а уходит под шапку. */
@supports (animation-timeline: scroll()){
  .hero{
    animation: heroPark linear both;
    animation-timeline: scroll(root block);
    animation-range: 0 520px;
    transform-origin: 50% 0;
  }
  @keyframes heroPark{
    to{ opacity: .3; transform: translate3d(0, -34px, 0) scale(.975); filter: blur(4px); }
  }
}

/* --------------------------------------------------------- строки и цифры */
.load{ position: relative; overflow: hidden;
       transition: background var(--t-mid), border-color var(--t-mid),
                   transform .42s var(--spring), box-shadow var(--t-mid); }
.load:hover{ transform: none; box-shadow: none; }
.load .arrow{ display: inline-block; transition: transform .42s var(--spring); }
.load:hover .arrow{ transform: translateX(4px); }
.load-price{ transition: transform .42s var(--spring); }
.load:hover .load-price{ transform: scale(1.05); }

/* Счётчик доехал. Одна короткая отдача — цифра «встаёт» на место, и по ней
   видно, что она набралась, а не была нарисована сразу. */
.stat b.landed{ animation: numberLand .5s var(--bounce); }
@keyframes numberLand{
  from{ transform: scale(1.14); }
  to  { transform: scale(1); }
}
/* И блик проходит по карточке ровно один раз — в тот момент, когда цифра
   остановилась. Двигается та же точка отражения, что ходит за курсором:
   объявленная через `@property`, она становится числом, которое браузер умеет
   интерполировать, — без этого она бы просто перескочила из края в край. */
@property --mx{ syntax: '<percentage>'; inherits: true; initial-value: 50%; }
@property --my{ syntax: '<percentage>'; inherits: true; initial-value: 0%; }

.stat.landed::after{ animation: sheenAcross 1.15s var(--glide) .04s; }
@keyframes sheenAcross{
  0%  { --mx: -15%; --my: 40%; opacity: 0; }
  35% { opacity: .95; }
  100%{ --mx: 115%; --my: 40%; opacity: 0; }
}

/* --------------------------------------------------------------- мелочи */
.note{ animation: noteDrop .6s var(--spring) both; }
@keyframes noteDrop{
  from{ opacity: 0; transform: translate3d(0, -10px, 0) scale(.98); }
  to  { opacity: 1; transform: none; }
}

input:focus, select:focus, textarea:focus{
  box-shadow: 0 0 0 4px var(--brand-tint), 0 10px 26px rgba(0,32,138,.14);
  transform: translateY(-1px);
}
input, select, textarea{
  transition: border-color var(--t-mid), box-shadow var(--t-mid),
              transform .42s var(--spring);
}

.langs a{ transition: background var(--t-mid) var(--glide), color var(--t-mid),
                      transform .4s var(--spring); }
.langs a:active{ transform: scale(.9); }
.usertag{ transition: transform .44s var(--spring), box-shadow var(--t-mid); }
.usertag:hover{ transform: translateY(-2px); box-shadow: var(--shadow); }
.co-ava{ transition: transform .5s var(--spring), box-shadow var(--t-mid); }
.load:hover .co-ava{ transform: scale(1.12) rotate(-4deg); }
.badge{ animation: popIn .45s var(--bounce) both; }
.backlink{ transition: color var(--t-mid), transform .42s var(--spring); }
.role-card{ position: relative; overflow: hidden;
            transition: border-color var(--t-mid), background var(--t-mid),
                        transform .44s var(--spring), box-shadow var(--t-mid); }
.role-card:active{ transform: scale(.985); }
.brandmark svg{ transition: transform .6s var(--spring); }
.brandmark:hover svg{ transform: rotate(-8deg) scale(1.06); }

/* Нижняя панель: иконка раздела, в который вошли, коротко подпрыгивает.
   На телефоне это единственное подтверждение перехода — страница меняется
   целиком, и без него непонятно, сменился раздел или просто перерисовалось. */
@media (max-width: 720px){
  .tabbar a{ transition: color var(--t-mid), background var(--t-mid),
                         transform .42s var(--spring); }
  .tabbar a:active{ transform: scale(.9); }
  .tabbar a.on span{ animation: tabPop .7s var(--bounce) both; }
  @keyframes tabPop{
    from{ transform: translateY(5px) scale(.72); }
    to  { transform: none; }
  }
  /* Точка под активным разделом — подпись на телефоне мелкая, одного цвета
     мало. */
  .tabbar a.on::after{
    content: ''; position: absolute; bottom: 2px; width: 4px; height: 4px;
    border-radius: 50%; background: var(--brand);
    animation: popIn .5s var(--bounce) both .1s;
  }
  .tabbar a{ position: relative; }
}

/* ===========================================================================
   Уменьшенное движение
   ---------------------------------------------------------------------------
   Системная настройка сильнее любых наших намерений — и сильнее всего, что
   написано выше. Отдельная оговорка нужна для анимаций, привязанных к
   прокрутке: у них нет длительности, обнулять её бессмысленно, их надо
   выключать поимённо — иначе первый экран так и останется размытым на 30%.
   =========================================================================== */
@media (prefers-reduced-motion: reduce){
  .hero, .topbar-in, .progress, body::before, body::after,
  .hero h1 em, .hero h1 .w > i, .stat.landed::after, .btn-primary:hover::after{
    animation: none !important;
  }
  .progress{ display: none; }
  .hero{ opacity: 1 !important; transform: none !important; filter: none !important; }
  .hero h1 .w{ overflow: visible; }
  .tilt{ transform: none !important; }
  .nav-pill{ transition: none; }
  .stat.landed::after{ animation: none; }
  ::view-transition-old(root), ::view-transition-new(root){ animation: none !important; }
}

/* Строка найденной компании: слева кто, справа что можно сделать. */
.found-row{
  display:flex; align-items:center; justify-content:space-between; gap:14px;
  padding: 13px 15px; border-radius: var(--r-md); margin-bottom: 8px;
  border: 1px solid var(--border); background: var(--glass-bottom);
}
.found-row .btn{ flex: none; }
@media (max-width: 620px){
  .found-row{ flex-direction: column; align-items: stretch; }
  .found-row .btn{ width: 100%; }
}

/* Курс валют на главной ------------------------------------------------- */
/* Одна строка под цифрами: виджет из боковой колонки сюда не поставить —
   он вертикальный и съел бы весь первый экран. Чипы переиспользуют стили
   .rate-code / .rate-unit / .rate-delta, чтобы курс выглядел одинаково
   на главной и на бирже. */
.rates-strip{ display:flex; flex-wrap:wrap; align-items:center; gap:10px; margin-top:24px; }
.rates-label{ font-size:12.5px; font-weight:700; color:var(--muted); }
.rates-label small{ font-size:10.5px; font-weight:600; color:var(--faint); }
.rate-chip{ display:inline-flex; align-items:baseline; gap:6px; padding:9px 13px;
  border-radius:13px; }
.rate-chip b{ font-size:15px; font-weight:800; font-variant-numeric:tabular-nums; }
.rate-chip .rate-delta{ margin-left:2px; }

@media (max-width: 720px){
  /* На телефоне четыре чипа в строку не помещаются — раскладываем по два,
     подпись занимает свою строку целиком. */
  .rates-strip{ display:grid; grid-template-columns: repeat(2, 1fr); gap:8px; }
  .rates-label{ grid-column: 1 / -1; }
  .rate-chip{ justify-content:flex-start; }
}

/* Пары полей в формах: «откуда/куда», «вес/объём» — читаются вместе, значит
   и стоять должны вместе. На телефоне разъезжаются в столбик. */
.form-row{ display:grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 620px){ .form-row{ grid-template-columns: 1fr; } }
.sec-h .btn{ margin-left: auto; }

/* ------------------------------------------------------------- дополнения */

/* Заголовок ломается по смыслу, а не по остатку строки: последняя строка из
   одного слова — самое заметное, что бывает в крупном кегле. */
h1, h2, h3, .hero h1{ text-wrap: balance; }
p.lead, .why-card p, .auth-sub{ text-wrap: pretty; }

.progress{ z-index: 2; }

/* Иконка в карточке «почему» отклоняется вместе с карточкой — как предмет,
   который лежит на наклонённой плоскости, а не напечатан на ней. */
.why-card .ic{ transition: transform .55s var(--spring), box-shadow var(--t-mid); }
.why-card:hover .ic{
  transform: translateY(-3px) rotate(-6deg) scale(1.08);
  box-shadow: 0 10px 24px rgba(0, 32, 138, .18);
}

/* Полосы доверия наливаются из нуля. Ширину задаёт сервер, поэтому растёт не
   она, а масштаб по горизонтали: анимировать ширину — значит пересчитывать
   раскладку строки на каждом кадре. Очередь берётся из --i самой строки: она
   объявлена на `.load` и наследуется вниз до полосы. */
.trust-bar i, .star-bar i{ transform-origin: 0 50%; }
.load .trust-bar i, .stars-breakdown .star-bar i{
  animation: barFill .9s var(--glide) both;
  animation-delay: calc(.18s + var(--i, 0) * 28ms);
}
@keyframes barFill{ from{ transform: scaleX(0); } to{ transform: scaleX(1); } }

/* Фильтры разворачиваются, а не появляются целиком. На телефоне панель
   схлопнута при загрузке, и без этого содержимое просто мигает на месте. */
details.filters[open] > form{ animation: glideUp .5s var(--glide) both; }

@media (prefers-reduced-motion: reduce){
  .load .trust-bar i, .stars-breakdown .star-bar i,
  details.filters[open] > form, .why-card:hover .ic{
    animation: none !important; transform: none !important;
  }
}

/* Переключатель темы — рядом с языками: обе настройки про то, как человек
   хочет видеть сайт, и искать их в разных углах незачем. */
.theme-btn{
  flex: none; width: 34px; height: 34px; border-radius: var(--pill);
  display: grid; place-items: center; cursor: pointer; font-size: 15px;
  background: var(--brand-tint); border: 1px solid var(--brand-line);
  color: var(--brand); transition: transform var(--t), background var(--t);
}
.theme-btn:hover{ transform: translateY(-1px); }
.theme-btn:active{ transform: scale(.92); }
.theme-btn .sun{ display: none; }
:root[data-theme="dark"] .theme-btn .sun,
:root:not([data-theme="light"]) .theme-btn .sun{ display: block; }
:root[data-theme="dark"] .theme-btn .moon,
:root:not([data-theme="light"]) .theme-btn .moon{ display: none; }
@media (prefers-color-scheme: light){
  :root:not([data-theme="dark"]) .theme-btn .sun{ display: none; }
  :root:not([data-theme="dark"]) .theme-btn .moon{ display: block; }
}

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

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

main .glass:not(.reveal):not(.rise):not(.rise-blur):not(.rise-x):not(.pop){
  animation: glideUp .7s var(--glide) both;
  animation-delay: calc(var(--i, 0) * 70ms);
}
/* Стекло внутри стекла и внутри появляющегося блока едет вместе с ним: две
   анимации на вложенных предметах читаются как рассинхрон, а не как глубина. */
main .glass .glass,
main .reveal .glass,
main .rise .glass{ animation: none; }

/* Очередь без единой строчки JS: порядок среди соседей и есть порядок
   появления. Дальше восьмого — все вместе, иначе низ страницы ждёт секунду. */
main .glass:nth-child(2){ --i: 1; }
main .glass:nth-child(3){ --i: 2; }
main .glass:nth-child(4){ --i: 3; }
main .glass:nth-child(5){ --i: 4; }
main .glass:nth-child(6){ --i: 5; }
main .glass:nth-child(7){ --i: 6; }
main .glass:nth-child(n+8){ --i: 7; }

/* Заголовок раздела приезжает вместе со своей таблицей, а не появляется
   готовым над едущим содержимым. */
main .section-head:not(.reveal):not(.rise),
main > section:not(.hero) > h1,
main .empty{
  animation: glideUp .65s var(--glide) both;
}

/* Форма набирается по полю. Карточка входа уже едет целиком — поля внутри
   догоняют её, поэтому они короче и без размытия: два размытия друг в друге
   выглядят как расфокус, а не как глубина. */
@keyframes fieldIn{
  from{ opacity: 0; transform: translate3d(0, 12px, 0); }
  to  { opacity: 1; transform: none; }
}
.auth-card .field,
.auth-card .role-card,
.auth-card > .btn,
.auth-card .auth-foot,
.auth-card .check,
.side-form .field{
  --i: 0;
  animation: fieldIn .5s var(--glide) both;
  animation-delay: calc(.14s + var(--i, 0) * 55ms);
}
.auth-card .field:nth-of-type(2), .auth-card .role-card:nth-of-type(2){ --i: 1; }
.auth-card .field:nth-of-type(3), .auth-card .role-card:nth-of-type(3){ --i: 2; }
.auth-card .field:nth-of-type(4), .auth-card .role-card:nth-of-type(4){ --i: 3; }
.auth-card > .btn{ --i: 4; }
.auth-card .auth-foot{ --i: 5; }

/* Строки внутри карточки компании и груза — тем же порядком, что и на бирже. */
.mini-row, .kv, .spec, .review, .rate, .dist, .price-row{
  --i: 0;
  animation: fieldIn .5s var(--glide) both;
  animation-delay: calc(.12s + var(--i, 0) * 34ms);
}
.mini-row:nth-child(2), .kv:nth-child(2), .spec:nth-child(2),
.review:nth-child(2), .rate:nth-child(2), .price-row:nth-child(2){ --i: 1; }
.mini-row:nth-child(3), .kv:nth-child(3), .spec:nth-child(3),
.review:nth-child(3), .rate:nth-child(3), .price-row:nth-child(3){ --i: 2; }
.mini-row:nth-child(4), .kv:nth-child(4), .spec:nth-child(4),
.review:nth-child(4), .rate:nth-child(4), .price-row:nth-child(4){ --i: 3; }
.mini-row:nth-child(n+5), .kv:nth-child(n+5), .spec:nth-child(n+5),
.review:nth-child(n+5), .rate:nth-child(n+5), .price-row:nth-child(n+5){ --i: 4; }

@media (prefers-reduced-motion: reduce){
  main .glass, main .section-head, main > section:not(.hero) > h1, main .empty,
  .auth-card .field, .auth-card .role-card, .auth-card > .btn,
  .auth-card .auth-foot, .auth-card .check, .side-form .field,
  .mini-row, .kv, .spec, .review, .rate, .dist, .price-row{
    animation: none !important;
  }
}

/* --------------------------------------------------------------- админка */
.admin-nav{ display:flex; gap:6px; flex-wrap:wrap; margin-bottom:20px; }
.admin-nav a{ padding:8px 15px; border-radius:var(--pill); font-size:13.5px;
  font-weight:700; color:var(--muted); background:var(--glass-bottom);
  border:1px solid var(--border); transition: background var(--t), color var(--t); }
.admin-nav a:hover{ color:var(--brand); border-color:var(--brand-line); }
.admin-nav a.on{ background:var(--brand); color:#fff; border-color:transparent; }

/* Факты, на которые смотрят, принимая решение. Все сразу, без разворачивания:
   решение принимается один раз и должно опираться на всё, что есть. */
.admin-facts{ display:grid; gap:7px; margin-bottom:14px; }
.admin-facts > div{ display:grid; grid-template-columns: 120px 1fr; gap:12px;
  font-size:13px; align-items:baseline; }
.admin-facts span{ color:var(--faint); font-weight:700; font-size:11px;
  text-transform:uppercase; letter-spacing:.05em; }
.admin-facts b{ font-weight:650; word-break:break-word; }

.admin-actions{ display:flex; gap:8px; flex-wrap:wrap; align-items:center;
  padding-top:14px; border-top:1px solid var(--border); }
.admin-actions input{ flex:1; min-width:180px; }
.btn.danger{ color:var(--danger); border-color:rgba(179,38,30,.3); }
.btn.danger:hover{ background:var(--danger); color:#fff; border-color:transparent; }

.admin-user{ display:flex; align-items:center; gap:12px; flex-wrap:wrap;
  padding:11px 12px; border-radius:var(--r-sm); }
.admin-user:hover{ background:var(--brand-tint); }
.admin-user > div:first-child{ flex:1; min-width:150px; }
.admin-user form{ margin-left:auto; }
@media (max-width: 620px){
  .admin-facts > div{ grid-template-columns: 1fr; gap:2px; }
  .admin-actions{ flex-direction:column; align-items:stretch; }
  .admin-actions .btn{ width:100%; }
}

/* Правовые ссылки в подвале ---------------------------------------------- */
/* Оферта и политика обязаны быть достижимы с любой страницы, но подвал —
   не место, где на них смотрят: приглушены и мельче подписи. */
.foot-links{ display:flex; gap:14px; flex-wrap:wrap; }
.foot-links a{ font-size:12.5px; color:var(--faint); text-decoration:none; }
.foot-links a:hover{ color:var(--ink); }
@media (max-width: 720px){
  .foot-links{ width:100%; order:3; margin-top:6px; }
}
/* Владелец площадки — строкой под подписью: обязателен на каждой странице,
   но это справка, а не часть бренда. */
.foot-legal{ margin-top: 14px; font-size: 12px; color: var(--faint); line-height: 1.5; }

/* Постраничный вывод ----------------------------------------------------- */
.pager{ display:flex; align-items:center; justify-content:space-between;
  gap:12px; margin:22px 0 8px; }
.pager-count{ font-size:12.5px; color:var(--faint); font-variant-numeric:tabular-nums; }

/* Круглая кнопка-значок в шапке. Такая же по размеру, как переключатель темы:
   в ряду одинаковых элементов разнобой заметнее самой кнопки. */
.icon-btn{
  flex: none; width: 34px; height: 34px; border-radius: var(--pill);
  display: grid; place-items: center; font-size: 15px;
  background: var(--brand-tint); border: 1px solid var(--brand-line);
  color: var(--brand); transition: transform var(--t), background var(--t);
}
.icon-btn:hover{ transform: translateY(-1px); background: var(--brand); color: #fff; }
.icon-btn:active{ transform: scale(.92); }

/* Шапка не должна переполняться: элементов в ней стало больше, чем помещается,
   и её обрезало по правому краю вместе с кнопками. Разделы уступают первыми —
   они продублированы нижней панелью на телефоне и остаются в подвале. */
.topbar-in{ gap: 14px; flex-wrap: nowrap; }
.nav{ min-width: 0; overflow: hidden; }
@media (max-width: 1100px){ .nav a{ padding: 8px 10px; font-size: 13.5px; } }
@media (max-width: 940px){ .nav{ display: none; } }

/* Счётчик непрочитанного — точкой на значке, а не числом рядом: рядом оно
   растягивает кнопку, и шапка начинает разъезжаться от каждого письма. */
.icon-btn{ position: relative; }
.icon-dot{
  position: absolute; top: -4px; right: -4px; min-width: 17px; height: 17px;
  padding: 0 4px; border-radius: var(--pill);
  display: grid; place-items: center;
  font-size: 10.5px; font-weight: 800; line-height: 1;
  background: var(--danger); color: #fff;
  border: 2px solid var(--bg);
}

/* ------------------------------------------------- свободная машина: номер,
   направления, звонок

   Гос. номер набираем моноширинным и вразрядку — его сверяют по символу с
   тем, что написано на борту, и слитный пропорциональный шрифт для этого
   плохо годится. */
.plate{
  display:inline-flex; align-items:center; gap:6px;
  padding: 3px 9px; border-radius: 8px;
  background: var(--line); border: 1px solid var(--brand-line);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 12.5px; font-weight: 700; letter-spacing: .06em;
  color: var(--ink); white-space: nowrap;
}
.plate-lg{ font-size: 15px; padding: 6px 13px; letter-spacing: .1em; }

.dirs{ display:flex; gap:7px; flex-wrap:wrap; }
.dirs .tag{ font-size: 11.5px; padding: 3px 9px; }

/* Кнопка звонка — главное действие на карточке машины: человек пришёл сюда
   звонить, а не читать. Номер внутри кнопки, чтобы его было видно и без
   нажатия — с компьютера по tel: не позвонишь. */
.btn-call{ display:flex; flex-direction:column; align-items:center; gap:2px; }
.btn-call b{ font-size: 15px; letter-spacing: .02em; }
.btn-call small{ font-size: 11.5px; opacity: .85; font-weight: 700; }

.field small.hint{ font-size: 12px; color: var(--faint); line-height: 1.5; }
/* Кнопка в заголовке доски: остальное в строке выровнено по базовой линии
   текста, и без этого она съезжала вниз на высоту своих отступов. */
.section-head .btn{ align-self: center; }
