/* Колокольчик в шапке (blox60 #1). Кнопка — близнец шестерёнки настроек (.set-btn): обе стоят в
   .hdr-right на тёмной шапке и обязаны читаться как одна пара, поэтому геометрия и полупрозрачный
   контур повторены дословно, а не «примерно похожи».
   Панель — тот же лист, что .set-menu: --card + --sheet-pop, без рамки (край задаёт тень). */
.notif{position:relative;display:flex;align-items:center}
.nb-btn{width:38px;height:38px;border-radius:var(--r-sm);border:1px solid rgba(255,255,255,.35);
  background:rgba(255,255,255,.12);color:var(--on-dark);cursor:pointer;position:relative;
  display:flex;align-items:center;justify-content:center}
@media (hover:hover){.nb-btn:hover{background:rgba(255,255,255,.22)}}
.nb-btn:active{transform:scale(.96)}
.nb-btn .ic{width:20px;height:20px}

.nb-menu{display:none;position:absolute;top:calc(100% + 8px);right:0;z-index:50;
  width:max-content;min-width:min(320px,calc(100vw - 24px));max-width:min(420px,calc(100vw - 24px));
  max-height:calc(100vh - 96px);overflow-y:auto;
  background:var(--card);border-radius:var(--r-lg);box-shadow:var(--sheet-pop);
  padding:8px;flex-direction:column;gap:4px}
.nb-menu.open{display:flex}

.nb-head{display:flex;align-items:center;justify-content:space-between;gap:8px;
  padding:4px 8px 6px;font-size:var(--fs-xs);font-weight:800;color:var(--muted);
  text-transform:uppercase;letter-spacing:.04em}
.nb-all{border:0;background:none;padding:2px 4px;cursor:pointer;font:inherit;text-transform:none;
  letter-spacing:0;color:var(--accent-ink);font-weight:700}
@media (hover:hover){.nb-all:hover{text-decoration:underline}}

.nb-list{display:flex;flex-direction:column;gap:2px}
/* Строка — КНОПКА: у неё одно действие (открыть объект), и она обязана отвечать на клавиатуру
   и на тап так же, как любая другая кнопка платформы. */
.nb-row{display:grid;grid-template-columns:auto 1fr;gap:10px;align-items:start;text-align:left;
  width:100%;border:0;background:none;padding:9px 8px;border-radius:var(--r-sm);cursor:pointer;
  font:inherit;color:var(--ink)}
@media (hover:hover){.nb-row:hover{background:var(--fill-soft)}}
.nb-row:active{transform:scale(.99)}
.nb-ico{color:var(--muted);display:flex;align-items:center;padding-top:2px}
.nb-body{display:flex;flex-direction:column;gap:2px;min-width:0}
.nb-title{font-size:var(--fs-sm);font-weight:600;line-height:var(--lh-tight)}
.nb-meta{font-size:var(--fs-xs);color:var(--muted);font-weight:600}
/* НЕПРОЧИТАННОЕ — точка слева и акцентный значок. Заливкой строку не метим: десяток новых
   уведомлений превратил бы список в сплошное цветное поле, и метка перестала бы значить «новое». */
.nb-row--new .nb-ico{color:var(--accent-ink)}
.nb-row--new .nb-title{font-weight:800}
.nb-row--new .nb-title::after{content:'';display:inline-block;width:7px;height:7px;margin-left:6px;
  border-radius:50%;background:var(--accent);vertical-align:middle}

.nb-empty{padding:14px 10px;text-align:center;color:var(--muted);font-size:var(--fs-sm)}

/* Подвал ленты — привязка телеграма (blox60 #1, шаг 4). Отделён линией, а не фоном: это не
   уведомление и не должно читаться как ещё одна строка списка. */
.nb-foot{border-top:1px solid var(--line);margin-top:4px;padding:8px 8px 4px}
.nb-foot:empty{display:none}
.nb-tgrow{display:flex;align-items:center;justify-content:space-between;gap:8px}
.nb-tgbtn{border:0;background:none;padding:4px 2px;cursor:pointer;font:inherit;font-weight:700;
  font-size:var(--fs-sm);color:var(--accent-ink);display:inline-flex;align-items:center;gap:6px}
@media (hover:hover){.nb-tgbtn:hover{text-decoration:underline}}
.nb-tgok{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-sm);font-weight:700;
  color:var(--ok-ink)}
.nb-tgnote{font-size:var(--fs-xs);color:var(--muted);text-align:center}
/* Раскрытая карточка привязки: QR слева, объяснение справа — на телефоне столбиком, иначе
   картинка ужимает текст до двух слов в строке. */
.nb-tgbox{display:flex;gap:10px;align-items:center;padding:8px 2px 2px}
/* А ЗАКРЫТАЯ — закрыта. Атрибут `hidden` прячет элемент правилом `display:none` из таблицы
   БРАУЗЕРА, у которого нет класса, — поэтому `.nb-tgbox{display:flex}` выше его перебивал, и
   карточка с QR висела раскрытой всегда, а кнопка «Подключить телеграм» была мёртвой: она честно
   переключала атрибут, которого никто не слушал. Поймано снимком детского колокольчика
   (blox60 #3); дефект родом из #1 и до сих пор так же висел у учителей. */
.nb-tgbox[hidden]{display:none}
/* Белое поле вокруг QR («тихая зона», без неё камера не читает код) вшито в САМУ картинку —
   qrencode -m 3, см. routes/notifications.js. Подложкой в CSS его задать нельзя: бумага схемы
   тёплая, а в тёмной схеме и вовсе тёмная, и код перестал бы читаться ночью. */
.nb-qr{width:112px;height:112px;flex:0 0 auto;border-radius:var(--r-sm)}
.nb-tgtext{font-size:var(--fs-xs);color:var(--muted);line-height:var(--lh)}
.nb-tgtext a{color:var(--accent-ink);font-weight:700;word-break:break-all}
@media (max-width:420px){ .nb-tgbox{flex-direction:column;align-items:flex-start} }

/* УКАЗАТЕЛЬ НА КВАДРАТ (blox60 #3). Уведомление ребёнка ведёт на конкретную работу, а день — это
   лента похожих карточек. Подсветка живёт пару секунд и гаснет: это жест «вот она», а не новое
   состояние карточки — своё состояние (красная рама возврата) у неё уже есть и спорить с ним
   нельзя. Тень, а не заливка, по той же причине: заливка перекрасила бы сам квадрат. */
@keyframes nb-focus-pulse{
  0%{box-shadow:0 0 0 0 var(--accent)}
  30%{box-shadow:0 0 0 4px var(--accent)}
  100%{box-shadow:0 0 0 0 var(--accent)}
}
.rect.nb-focus{animation:nb-focus-pulse 1.3s ease-out 2}
@media (prefers-reduced-motion:reduce){
  .rect.nb-focus{animation:none;box-shadow:0 0 0 3px var(--accent)}
}
