- theme: store accent separately for light/dark (theme-core/controls)
- en contacts: WhatsApp card instead of VK (wa.me link)
- Activity: add GitHub card (logo webp) in both locales
- mp-card__image border uses --line to match card (less contrast)
- drop contact-card--brand-ya (yandex chat) from contact-section ru/en
- update cookie-policy contacts enumeration to drop Yandex (ru/en)
- rebuild public/
- add .en.html overrides for 16 case pages + resume via apinex translator
- translate remaining partials (projects-related, mini-projects-*, fab-stack-home-contact,
fab-stack-resume, content-edit-fab-stack, cookie-notice)
- enhance translate.mjs to protect <script>/<style> from translation
- second pass: translate attribute values (aria-label/alt/title/placeholder/content/
data-hint-default) and visible text DeepL skipped in html mode
- make logo language-aware (NM / НМ) via i18n
- remove {{> lang-switch}} from header-home/case/minimal
- add {{> lang-switch}} to footer
- restyle .lang-switch as compact text group 'RU / EN' (active = accent),
drop pill borders/background for a minimal look
- build-pages.mjs: add pagePrefix (locale-root-relative, no en offset)
- use pagePrefix for nav links: logo, back-home, footer design-system/
cookie-policy/, FAB #contact, cookie-notice link, cookie-policy body
link, case-page #skills/#projects anchors (assetPrefix pointed to site
root and leaked en pages to ru)
- docs/translation.md: document assetPrefix vs pagePrefix
- docs/translation.md: build-time ru/en architecture, build-pages mechanics,
apinex translator API + scripts/translate.mjs usage, page translation
workflow, adding a new language
- AGENTS.md: link docs/translation.md in key-files table
- scripts/translate.mjs: wraps apinex.bond /v1/tools/translator (free)
- protects {{tokens}} and <code> from translation in HTML mode
- supports --text/--file/--batch/--list-languages, auto HTML detection
- npm run translate alias
- case-media-slider: обрамление+hover как у карточек, стрелки только при наведении (fade-in),
группа пред/след-пилюля в правом нижнем углу, disabled-кнопки видны (не скрываются),
убран border-radius у img/figcaption (скругление у viewport), неактивные слайды не скрываются
visibility (нет 'дырки' при перелистывании), настраиваемая ширина --wide/--content/--natural
- image-load-placeholder: исключён .case-media-slider (нет блика/серого фона)
- icon-press: универсальный эффект 'продавливания' иконки при нажатии (.icon-press + :active/.is-pressed),
применён к слайдеру и всем кнопкам просмотрщика
data-mp-cells-sm=2 для карточек related — в диапазоне 4 колонок
(≈1080–1355px вьюпорта) карточки занимают по 2 колонки и парятся,
устраняя пустую колонку справа. В десктопном 6-колоночном диапазоне
сохраняется data-mp-cells=3.
Убран инклюд {{> footer-spacer}} (пустая <section class="section section--surface"
aria-hidden> как прокладка перед футером) на главной и во всех 16 кейсах.
Пересобраны страницы (build:pages).
Added display, width, height, background:currentColor, and full
mask-size/mask-repeat/mask-position properties to match the
original fab-primary__ico pattern.
- Secondary button wrapped in theme-panel-fab-wrap (above primary)
- Primary button outside wrap (below secondary)
- Added glass-neutral class to both buttons
- Matches the pattern from fab-stack-home-contact.html
- Added secondary FAB button 'Печать' with printer icon (window.print)
- Created printer.svg icon for the print button
- Added .fab-secondary__ico--print CSS class
- Fixed html2pdf color-mix() issue: buildCleanClone() creates a deep clone
with all computed styles inlined, all stylesheets removed, and
pseudo-elements converted to real DOM elements before passing to html2pdf
- Two separate handlers: pdfBtn for download, printBtn for print dialog
html2canvas (bundled in html2pdf.js) can't parse CSS color-mix()
function regardless of onclone workarounds. Using window.print()
which leverages the browser's native renderer with full CSS support.
In Chrome/Edge the print dialog defaults to 'Save as PDF' destination.
- Delete all CSS rules via sheet.deleteRule(0) loop (not just clear textContent)
- Remove all <style> and <link rel=stylesheet> elements from clone
- Convert ::before/::after pseudo-elements into real DOM elements with inline styles
- All computed styles inlined on every element in the clone
- This ensures html2canvas never encounters color-mix() in any stylesheet
Previous flattenColors approach failed because html2canvas reads CSS
rules from stylesheets, not computed styles. Now in the onclone callback:
1. Walk all elements, get computed styles from original doc
2. Set every property as inline style on cloned elements
3. Remove all <style> tags and <link rel=stylesheet> from clone
This ensures html2canvas never encounters raw color-mix() in stylesheets.
html2canvas can't parse CSS color-mix() function. Before rendering,
walk the DOM tree and inline computed styles (with color-mix resolved
by the browser) as inline styles. Restore originals after save.