/* «Досрок» — продуктовые расширения дизайн-системы.
   Токены и компоненты (.ds-*) лежат в tokens/ и components.css и совпадают
   с эталоном в docs/design-system; здесь — то, что нужно приложению сверх
   набора системы: скип-линк, зона тостов, попапы поиска и нормы, адаптив.
   Правила читают только токены — сырых #hex здесь быть не должно. */

/* ---- Ссылка «перейти к содержимому» ---- */
.skip-link{position:absolute;z-index:200;left:var(--sp-3);top:var(--sp-3);padding:var(--sp-25) var(--sp-4);border-radius:var(--r-m);background:var(--accent);color:var(--on-accent);font-size:var(--fs-body);font-weight:500;translate:0 -200%}
.skip-link:focus-visible{translate:0 0;text-decoration:none}

/* Прокрутка страницы заблокирована, пока открыто окно или боковая карточка */
body.is-locked{overflow:hidden}

/* ---- Появление слоёв: только transform и opacity ---- */
.ds-modal-panel{animation:modal-in var(--dur-2) var(--ease-out)}
@keyframes modal-in{from{scale:0.98;opacity:0.5}to{scale:1;opacity:1}}
.ds-modal-panel[hidden]{display:none}
.ds-menu[hidden]{display:none}
.ds-drawer{animation:drawer-in var(--dur-3) var(--ease-out)}
@keyframes drawer-in{from{translate:30px 0;opacity:0.4}to{translate:0 0;opacity:1}}

/* ---- Зона тостов: столбик над нижним краем, тосты в потоке зоны ---- */
.toast-zone{position:fixed;z-index:100;left:50%;bottom:var(--sp-6);translate:-50% 0;display:flex;flex-direction:column;gap:var(--sp-25);align-items:center;width:min(35rem,calc(100vw - 24px))}
.toast-zone .ds-toast{position:static;translate:none;width:100%;max-width:none;animation:toast-in var(--dur-3) var(--ease-out)}
@keyframes toast-in{from{translate:0 12px;opacity:0}to{translate:0 0;opacity:1}}
.toast-msg{flex:1;min-width:0}
.toast-hint{font-size:var(--fs-2xs);opacity:0.72;white-space:nowrap}
.ds-toast-undo:focus-visible{outline:2px solid var(--on-dark-quiet);outline-offset:2px}
/* Полоса отсчёта: scaleX вместо width — width пересчитывал бы раскладку
   каждый кадр все 10 секунд. Длительность приходит из app.js через
   --motion-keep-dur; класс .motion-keep защищает её от глобального
   отключения анимаций (base.css): полоса — сообщение о времени. */
.ds-toast-bar{width:100%;transform-origin:left center;animation:toast-bar var(--motion-keep-dur,10s) linear forwards}
@keyframes toast-bar{from{transform:scaleX(1)}to{transform:scaleX(0)}}

/* ---- Результаты поиска в шапке ---- */
.search-pop{position:absolute;z-index:75;top:calc(100% + 6px);left:0;width:28.75rem;max-width:84vw;padding:var(--sp-1);background:var(--surface);border:1px solid var(--line);border-radius:var(--r-m);box-shadow:var(--shadow-pop);max-height:60vh;overflow-y:auto}
.search-pop[hidden]{display:none}
.search-pop .sp-group{padding:var(--sp-2) var(--sp-2) var(--sp-1)}
.search-pop .sp-item{display:block;padding:var(--sp-2);border-radius:var(--r-s);color:var(--ink)}
.search-pop .sp-item:hover{background:var(--surface-sunken);text-decoration:none}
.search-pop .sp-item .sp-sub{font-size:var(--fs-xs);color:var(--ink-3)}

/* ---- Всплывающая карточка нормы: документ, а не меню — острые углы ---- */
.norm-pop{position:absolute;z-index:130;width:400px;max-width:calc(100vw - 40px);padding:var(--sp-4) var(--sp-5);background:var(--surface);border:1px solid var(--line-strong);border-top:3px double var(--ink);box-shadow:var(--shadow-pop)}
.norm-pop h4{margin:0 0 var(--sp-15);font-family:var(--font-doc);font-size:var(--fs-lg);font-weight:700;line-height:var(--lh-tight)}
.norm-pop .norm-formula{margin:0 0 var(--sp-25);padding:var(--sp-2) var(--sp-25);background:var(--surface-sunken);font-family:var(--font-mono);font-size:var(--fs-sm);line-height:1.5;overflow-wrap:anywhere}
.norm-pop .norm-text{font-family:var(--font-doc);font-style:italic;font-size:var(--fs-sm);line-height:1.55;color:var(--ink-2);border-left:3px solid var(--line-strong);padding-left:var(--sp-3);margin:0 0 var(--sp-3)}
.norm-src{font-size:var(--fs-xs)}
.norm-foot{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-25)}

/* ---- Короткая подсказка у пометки (замена title=) ---- */
.hint-pop{position:absolute;z-index:131;max-width:min(22rem,calc(100vw - var(--sp-12)));padding:var(--sp-2) var(--sp-3);background:var(--toast-bg);color:var(--on-dark);border-radius:var(--r-s);font-size:var(--fs-sm);line-height:1.4;box-shadow:var(--shadow-pop)}

/* ---- Текстовая кнопка-ссылка ---- */
.btn-link{display:inline-flex;align-items:center;gap:var(--sp-15);border:0;background:none;padding:0;color:var(--accent);font-size:inherit;font-weight:500;cursor:pointer}
.btn-link:hover{text-decoration:underline;text-underline-offset:3px}
.btn-link:active{color:var(--accent-deep)}
.btn-link:disabled,.btn-link[disabled]{opacity:0.45;cursor:not-allowed;text-decoration:none}
.btn-link svg{width:15px;height:15px}

/* ---- Метка типа элемента списка (вид входящего, вид события) ---- */
.item-kind{display:inline-flex;align-items:center;gap:var(--sp-1);font-size:var(--fs-2xs);font-weight:600;letter-spacing:var(--ls-caps);text-transform:uppercase;color:var(--ink-2)}

/* ---- Дополнения к компонентам системы ---- */
/* Групповая строка первой в карточке не дублирует рамку карточки */
.ds-card > .ds-group-row:first-child{border-top:0}
/* Ряд из двух клавиш (G 1) в пункте навигации ведёт себя как одиночная */
.ds-nav-item .ds-kbd-row{margin-left:auto;opacity:0;transition:opacity var(--dur-1) var(--ease-out)}
.ds-nav-item:hover .ds-kbd-row{opacity:1}
.ds-nav-item.is-active .ds-kbd-row{display:none}
.ds-nav-item .ds-kbd-row .ds-kbd{margin-left:0;opacity:1}
.ds-nav-badge+.ds-kbd-row{margin-left:var(--sp-1)}
.ds-tab .ds-count{margin-left:var(--sp-1)}
.ds-section-head .ds-count,.ds-eyebrow .ds-count{background:none;min-width:0;padding:0;font-weight:500;color:var(--ink-3)}
.tab-panel[hidden]{display:none}
.ds-empty strong{color:var(--ink)}
.ds-rc-aside{margin-left:auto;flex:none;font-size:var(--fs-xs);color:var(--ink-3);white-space:nowrap}
.ds-radio-card{position:relative}
.ds-btn-caption{text-align:center;max-width:200px}

/* Недоступные состояния: одинаково на любой странице */
.ds-btn:disabled,.ds-btn[disabled]{opacity:0.5;cursor:not-allowed;transform:none}
.ds-iconbtn:disabled,.ds-iconbtn[disabled]{opacity:0.45;cursor:not-allowed}
.ds-input:disabled,.ds-select:disabled{background:var(--surface-dim);color:var(--ink-3);cursor:not-allowed}
.ds-toggle input:disabled{cursor:not-allowed;opacity:0.45}

/* ---- Мелкие утилиты вместо инлайновых style в скриптах ---- */
.banner-gap{margin-top:var(--sp-4)}
.banner-gap-sm{margin-top:var(--sp-3)}
.banner-stack{margin-bottom:var(--sp-2)}
.banner-stack-lg{margin-bottom:var(--sp-3)}
.kv-gap{margin-top:var(--sp-4)}
.kv-tight{margin-bottom:var(--sp-4)}
.kv-wide{grid-template-columns:11.875rem minmax(0,1fr)}
.drawer-lede{margin:0 0 var(--sp-3);font-size:var(--fs-sm)}
.drawer-p{margin:0 0 var(--sp-3)}
.drawer-note{margin:0;font-size:var(--fs-sm)}
.drawer-cap{font-size:var(--fs-xs)}
.help-card{margin-bottom:var(--sp-3)}
.help-card-title{font-weight:500;margin-bottom:var(--sp-05)}
.help-card-sub{font-size:var(--fs-sm)}
.help-note{font-size:var(--fs-xs);margin-top:var(--sp-3)}

/* Выполненная строка. Одно правило на весь продукт: раньше скрипты
   писали opacity и line-through инлайном, каждый по-своему. */
[data-task-row].is-done,
.ds-ledger tr.ds-row-done td{opacity:0.58}
[data-task-row].is-done .task-title{text-decoration:line-through}

/* ---- Узкие экраны. Система настольная; телефону — рабочий минимум ---- */
@media (max-width:980px){
  .ds-app{grid-template-columns:minmax(0,1fr)}
  .ds-aside{position:static;height:auto;flex-direction:row;align-items:center;gap:var(--sp-1);overflow-x:auto;padding:var(--sp-25) var(--sp-3);border-right:0;border-bottom:1px solid var(--line)}
  .ds-brand{padding:0 var(--sp-25) 0 var(--sp-1);font-size:1.1rem}
  .ds-nav{flex-direction:row}
  .ds-nav-item{padding:var(--sp-2) var(--sp-25);white-space:nowrap;width:auto}
  .ds-aside-foot{display:none}
  .ds-topbar{flex-wrap:wrap;padding:var(--sp-3) var(--sp-4)}
  .ds-search{width:100%;max-width:none;order:3}
  .ds-sync{display:none}
  .ds-content{padding:var(--sp-2) var(--sp-4) var(--sp-12)}
}
/* Телефон. Кнопки в шапке раздела не ломаются на две строки,
   заголовок не вылезает за край длинным номером дела. */
@media (max-width:560px){
  .ds-topbar{gap:var(--sp-25);padding:var(--sp-25) var(--sp-3)}
  .ds-content{padding:var(--sp-2) var(--sp-3) var(--sp-10)}
  .ds-page-head{gap:var(--sp-25);margin:var(--sp-25) 0 var(--sp-3)}
  .ds-page-title{font-size:1.25rem;overflow-wrap:anywhere;min-width:0}
  .ds-page-actions{margin-left:0;width:100%}
  .ds-page-actions .ds-btn{flex:1 1 auto;min-width:0}
  .skip-link{left:var(--sp-25);top:var(--sp-25)}
}

/* ---- Смена раздела без перезагрузки (router.js) ---- */
/* Окна и скрипты раздела лежат в общем узле, но в разметке ведут себя так,
   будто их родителя нет: раскладку страницы он не трогает. */
.page-extras{display:contents}

/* Фокус, перенесённый роутером ради экранного диктора, рамку не рисует:
   человек его не наводил. Скип-ссылке рамка нужна — она приходит на
   #content без этой пометки, и правило её не касается. */
.ds-content[data-quiet-focus]:focus{outline:none}

/* Перекрёстное затухание при смене раздела. Меняется только содержимое,
   поэтому переход читается как «раздел сменился», а не как «страница
   перезагрузилась». Быстрее --dur-2 глаз не успевает, дольше --dur-3 —
   уже ожидание. */
@media (prefers-reduced-motion:no-preference){
  ::view-transition-old(root),::view-transition-new(root){animation-duration:var(--dur-2)}
}

/* ---- Скелет раздела ----
   Показывается, только если ответ не пришёл за ~120 мс: пустое место
   на экране — тоже сообщение, и оно должно быть о работе, а не о поломке. */
.sk{display:flex;flex-direction:column;gap:var(--sp-3);padding-top:var(--sp-2)}
.sk-b{background:var(--surface-sunken);border-radius:var(--r-s);animation:sk-breathe 1.6s var(--ease-in-out) infinite}
.sk-head{display:flex;flex-direction:column;gap:var(--sp-2);margin-bottom:var(--sp-1)}
.sk-title{height:1.75rem;width:min(17.5rem,60%);border-radius:var(--r-m)}
.sk-sub{height:0.875rem;width:min(25rem,80%)}
.sk-toolbar{display:flex;gap:var(--sp-2);flex-wrap:wrap}
.sk-chip{height:2rem;width:7.5rem;border-radius:var(--r-m)}
.sk-rows{display:flex;flex-direction:column;gap:var(--sp-2)}
.sk-row{height:3.5rem;border-radius:var(--r-m)}
.sk-card{height:6.5rem;border-radius:var(--r-m)}
.sk-panel{height:13.75rem;border-radius:var(--r-m)}
.sk-banner{height:4rem;border-radius:var(--r-m)}
.sk-cols{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--sp-3)}
.sk-cols-side{grid-template-columns:minmax(0,2fr) minmax(0,1fr)}
.sk-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:var(--sp-1)}
.sk-cell{height:5.5rem}
@media (max-width:980px){
  .sk-cols,.sk-cols-side{grid-template-columns:minmax(0,1fr)}
  .sk-cell{height:3.5rem}
}
/* Дыхание, а не бегущий блик: блик читался бы как «что-то происходит
   прямо сейчас на этом месте», хотя место просто ещё не заполнено. */
@keyframes sk-breathe{0%,100%{opacity:1}50%{opacity:0.5}}

/* ---- Печать ---- */
@media print{
  .skip-link,.toast-zone{display:none!important}
  body{background:var(--surface)}
}
