/* Редактор формул — нижняя шторка поверх экрана.

   Каркас взят у обычных шторок приложения (.sheet-modal / .panel в app.css):
   тот же затемнённый фон, тот же скруглённый верх, те же цвета. Отдельный
   файл нужен потому, что внутри шторки лежит своя механика — предпросмотр,
   палитра кнопок и подъём над клавиатурой, — а панель обязана быть колонкой
   с прокруткой только у палитры: предпросмотр и «Готово» видно всегда. */

.formula-modal {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background: rgba(8, 10, 14, .5);
  backdrop-filter: blur(3px);
  display: none;
  align-items: flex-end;
  /* Выше обычных шторок (40): формулу зовут из доски и из листа, где уже
     открыт свой попап, и она должна лечь поверх. Но ниже тоста (60) —
     сообщение об ошибке обязано быть видно и поверх редактора. */
  z-index: 55;
}
.formula-modal.open { display: flex; }

.formula-panel {
  background: var(--ground);
  color: var(--text);
  width: 100%;
  max-height: 100%;
  border-radius: 22px 22px 0 0;
  padding: 8px 16px calc(14px + var(--sab));
  /* Светлый кант по верхнему краю: шторка лежит на затемнённом экране, и без
     него её край в тёмной теме просто исчезает. */
  box-shadow: var(--shadow-lg), inset 0 1px 0 rgba(255, 255, 255, .12);
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.formula-grab {
  width: 38px;
  height: 4px;
  border-radius: 2px;
  background: var(--hint);
  opacity: .35;
  margin: 4px auto 8px;
  flex: none;
}

.formula-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
  flex: none;
}
.formula-head h3 {
  margin: 0;
  font-family: var(--serif);
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -.01em;
  flex: 1;
  min-width: 0;
}
.formula-x {
  width: 44px;
  height: 44px;
  margin-right: -8px;
  border: 0;
  border-radius: 12px;
  background: transparent;
  color: var(--text-soft);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  display: grid;
  place-items: center;
  flex: none;
  transition: background .15s ease, transform .12s ease;
}
.formula-x:active { background: var(--chip); transform: scale(.94); }
@media (hover: hover) and (pointer: fine) {
  .formula-x:hover { background: var(--chip); color: var(--text); }
}

/* Предпросмотр: лист бумаги, как сам конспект, чтобы формула выглядела
   ровно так, как ляжет в текст. Мягкий свет сверху и утопленный кант — тот
   же приём, что у .sheet: бумага не должна читаться как поле ввода. */
.formula-preview {
  /* Ужимается последним и только до min-height: когда вылезла клавиатура и
     высокая формула не влезает, лучше подрезать её с прокруткой, чем
     вытолкнуть «Готово» за нижний край экрана. */
  flex: 0 1 auto;
  background-color: var(--paper);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, .5), rgba(255, 255, 255, 0) 60px);
  border: 0;
  box-shadow: inset 0 0 0 1px var(--line), 0 1px 0 rgba(255, 255, 255, .04);
  border-radius: var(--radius);
  color: var(--ink);
  min-height: 98px;
  padding: 14px 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Длинное уравнение шире окошка предпросмотра. При обычном center его
     начало уезжает за левый край, и прокруткой до него уже не добраться —
     первокурсник видит середину формулы и хвост. safe center центрирует,
     пока формула влезает, и прижимает к началу, когда не влезла. То же
     сверху: высокая матрица не должна терять верхнюю строку. */
  align-items: safe center;
  justify-content: safe center;
  text-align: center;
  overflow: auto;
  font-size: 18px;
}
html.dark .formula-preview {
  background-image: linear-gradient(180deg, rgba(255, 255, 255, .05), rgba(255, 255, 255, 0) 60px);
}
.formula-preview .katex { font-size: 1.5em; }
.formula-preview .katex-display { margin: 0; }
.formula-preview .katex-display > .katex { font-size: 1.6em; }

.formula-empty { color: var(--hint); font-size: 14px; }

/* Разобрать не вышло — не красная ошибка KaTeX, а спокойная строчка и
   подсветка куска, на котором разбор споткнулся. */
.formula-broken { width: 100%; }
.formula-broken b {
  display: block;
  color: var(--text-soft);
  font-size: 14px;
  font-weight: 600;
}
.formula-broken code {
  display: block;
  margin-top: 8px;
  font: 13px/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  color: var(--ink-soft);
  word-break: break-all;
  text-align: left;
}
.formula-broken mark {
  background: var(--exam);
  color: var(--exam-text);
  box-shadow: 0 0 0 1px var(--exam-line);
  border-radius: 4px;
  padding: 0 2px;
}

.formula-input {
  flex: none;
  width: 100%;
  box-sizing: border-box;
  margin-top: 10px;
  padding: 12px 13px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--card);
  color: var(--text);
  /* 16px, а не 15: у поля с меньшим кеглем iOS сам наезжает масштабом, и
     шторка прыгает при каждом касании ввода. */
  font: 16px/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  min-height: 46px;
  max-height: 118px;
  resize: none;
  overflow-y: auto;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.formula-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
  outline: none;
}

.formula-row {
  display: flex;
  align-items: stretch;
  gap: 8px;
  margin-top: 10px;
  flex: none;
}
.formula-seg {
  display: flex;
  flex: 1;
  min-width: 0;
  gap: 2px;
  padding: 3px;
  background: var(--ground-deep);
  border-radius: 12px;
}
.formula-seg button {
  /* Именно 1 1 auto, а не 1: при равных долях «Отдельной строкой» не влезало
     в свою половину на 390 px и обрывалось многоточием — читалось «Отдельной
     строк…», и чем это отличается от соседней кнопки, было непонятно. Доля по
     содержимому отдаёт длинному названию столько, сколько ему нужно: обе
     подписи целиком помещаются и на узком телефоне. */
  flex: 1 1 auto;
  min-width: 0;
  padding: 0 10px;
  min-height: 38px;
  border: 0;
  border-radius: 9px;
  background: transparent;
  color: var(--text-soft);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
  transition: background .16s ease, color .16s ease;
}
.formula-seg button[aria-selected="true"] {
  background: var(--card);
  color: var(--text);
  box-shadow: var(--shadow-sm);
}
.formula-seg button:active { transform: scale(.97); }

/* «Следующее пустое место»: одна стрелка ⇥ ни о чём не говорит человеку,
   который открыл редактор впервые. Подпись под знаком стоит 10 px высоты и
   снимает вопрос: кнопка гоняет курсор по пустым скобкам шаблона. */
.formula-jump {
  min-width: 62px;
  min-height: 44px;
  flex: none;
  padding: 4px 8px 5px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--card);
  color: var(--text-soft);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  box-shadow: var(--shadow-sm);
  transition: background .15s ease, color .15s ease, transform .12s ease;
}
.formula-jump::after {
  content: "пусто";
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.formula-jump:active { background: var(--accent-soft); color: var(--accent); transform: scale(.96); }
@media (hover: hover) and (pointer: fine) {
  .formula-jump:hover { color: var(--text); border-color: var(--accent); }
}

/* Вкладки палитры.

   Раньше строка ездила пальцем, и пятая вкладка была подрезана краем экрана:
   догадаться, что там есть продолжение, было неоткуда — обрезанный чип у
   самой рамки читается как дефект вёрстки, а не как приглашение прокрутить.
   Поэтому вкладки переносятся на вторую строку и на телефоне тоже: две
   строки стоят 50 px, зато спрятанного не остаётся вовсе. */
.formula-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 12px;
  flex: none;
}
.formula-tab {
  /* Растягиваются по строке: доли по содержимому, но остаток делится между
     чипами строки. Так последняя строка всегда полная, и «Матрицы и системы»,
     которым не хватило места наверху, встают полосой во всю ширину — это
     читается как решение, а не как обрыв ленты. Приём заодно не зависит от
     числа разделов: сколько бы их ни стало, орфана не будет. */
  flex: 1 1 auto;
  min-height: 44px;
  padding: 0 15px;
  border: 1px solid var(--line);
  border-radius: 22px;
  background: var(--card);
  color: var(--text-soft);
  font-size: 13.5px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: background .16s ease, color .16s ease, border-color .16s ease, transform .12s ease;
}
.formula-tab:active { transform: scale(.96); }
.formula-tab[aria-selected="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-text);
  box-shadow: var(--shadow-sm);
}
@media (hover: hover) and (pointer: fine) {
  .formula-tab:not([aria-selected="true"]):hover { border-color: var(--accent); color: var(--text); }
}

.formula-keys {
  flex: 1 1 auto;
  min-height: 92px;
  overflow-y: auto;
  margin-top: 10px;
  padding-bottom: 4px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
  gap: 7px;
  align-content: start;
}
.formula-key {
  min-height: 52px;
  padding: 4px 6px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--card);
  color: var(--text);
  font-size: 15px;
  cursor: pointer;
  /* Внутренняя нижняя грань делает из плитки клавишу: света сверху, тени
     снизу. На плоском прямоугольнике палитра выглядит списком, а не набором
     кнопок, по которым можно барабанить. */
  box-shadow: var(--shadow-sm), inset 0 -1px 0 var(--line);
  display: grid;
  place-items: center;
  overflow: hidden;
  transition: background .13s ease, transform .1s ease;
}
.formula-key:active {
  background: var(--accent-soft);
  transform: scale(.94);
  box-shadow: none;
}
@media (hover: hover) and (pointer: fine) {
  .formula-key:hover { background: var(--accent-soft); }
}
.formula-key .katex { font-size: 1.12em; }
.formula-key.wide { grid-column: span 2; }

.formula-foot {
  display: flex;
  gap: 10px;
  margin-top: 12px;
  flex: none;
}
.formula-foot button {
  min-height: 52px;
  border: 0;
  border-radius: 13px;
  font-size: 15.5px;
  font-weight: 600;
  cursor: pointer;
  transition: transform .12s ease, filter .15s ease;
}
.formula-cancel {
  flex: 1;
  background: var(--card);
  color: var(--text);
  box-shadow: inset 0 0 0 1px var(--line);
}
.formula-ok {
  flex: 1.5;
  background: var(--accent);
  color: var(--accent-text);
  box-shadow: var(--shadow-md);
}
.formula-foot button:active { transform: scale(.99); }
@media (hover: hover) and (pointer: fine) {
  .formula-ok:hover { filter: brightness(1.06); }
}

/* Клавиатура телефона съедает половину экрана. Шторка ужимается вместе с
   ней: заголовок и предпросмотр становятся ниже, но формулу видно всегда. */
.formula-modal.tight .formula-grab { margin: 2px auto 4px; }
.formula-modal.tight .formula-head { margin-bottom: 6px; }
.formula-modal.tight .formula-head h3 { font-size: 16px; }
.formula-modal.tight .formula-preview { min-height: 62px; padding: 8px 10px; font-size: 16px; }
.formula-modal.tight .formula-keys { min-height: 58px; }
.formula-modal.tight .formula-tabs { margin-top: 8px; }
.formula-modal.tight .formula-foot { margin-top: 8px; }
.formula-modal.tight .formula-foot button { min-height: 46px; }
/* Поле ввода растёт под текст, но с клавиатурой ему нельзя занимать треть
   видимого экрана: потолок ниже, а лишнее уезжает под собственную прокрутку.
   Высоту после смены режима пересчитывает grow() из fit(). */
.formula-modal.tight .formula-input { max-height: 76px; }

/* Маленький телефон с поднятой клавиатурой: видимого экрана остаётся ~420 px.
   Здесь ужимаемся ещё раз — до одной строки поля и одной строки палитры.
   Вкладки в этом режиме снова становятся одной ездящей строкой: две строки
   чипов стоят 50 px, а их тут просто нет. Чтобы обрезанный чип у края не
   выглядел дефектом, справа лежит мягкая маска — видно, что лента длиннее
   экрана. Кнопки при этом остаются не мельче 44 px: пальцем попадать всё
   равно надо. */
.formula-modal.squeeze .formula-panel { padding-top: 6px; padding-bottom: calc(10px + var(--sab)); }
.formula-modal.squeeze .formula-grab { display: none; }
.formula-modal.squeeze .formula-head { margin-bottom: 4px; }
.formula-modal.squeeze .formula-preview { min-height: 54px; padding: 6px 10px; }
.formula-modal.squeeze .formula-input { max-height: 46px; margin-top: 8px; }
.formula-modal.squeeze .formula-row { margin-top: 8px; }
.formula-modal.squeeze .formula-keys { min-height: 52px; margin-top: 8px; }
.formula-modal.squeeze .formula-foot { margin-top: 6px; }
.formula-modal.squeeze .formula-tabs {
  margin-top: 6px;
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  scroll-padding-inline: 16px;
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
}
.formula-modal.squeeze .formula-tabs::-webkit-scrollbar { display: none; }
/* В ездящей ленте чипы обязаны сохранять свою ширину, иначе flex сожмёт их
   в одну строку и прокручивать станет нечего. */
.formula-modal.squeeze .formula-tab { flex: 0 0 auto; }

/* Ноутбук: шторка превращается в окно по центру — так же, как остальные
   попапы приложения на широком экране (desktop.css). */
@media (min-width: 860px) {
  .formula-modal { align-items: center; justify-content: center; }
  .formula-panel {
    width: 560px;
    max-height: 86vh;
    border-radius: 18px;
    padding: 10px 22px 22px;
  }
  .formula-grab { display: none; }
  .formula-panel .formula-head { margin-top: 8px; }
  .formula-keys { grid-template-columns: repeat(auto-fill, minmax(60px, 1fr)); }
  .formula-input { max-height: 150px; }
}
