# Design Book `marketing-light-5` — Components Инвентарь компонентов, извлечённых с editorial marketing archetype (Webflow-based). HTML-сниппеты используют токены `--ml5-*` из [`tokens.css`](tokens.css). Ключевая эстетика: **editorial whisper** — cream ivory тело, slate-dark текст, мягчайшие тени (rgba 0.01/0.02/0.04), подчёркивания как «редакторская правка», single-source clay #d97757 для редких акцентов. --- ## 1. Pill Button (Primary / Secondary / Tertiary / Nav-variant) Универсальная pill-кнопка с `border-radius: 100vw` (токен `--ml5-radius-round`). Три visual-роли + nav-variant, который меняет hover-поведение на clay-акцент. Текст всегда сохраняет сдержанный вес `500` (не bold) — в книге нет агрессивных CTA. ```html Start free Read the story Model details Download app ``` ```css /* Базовый pill */ .ml5-btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--ml5-space-2); padding: var(--ml5-space-3) var(--ml5-space-5); font-family: var(--ml5-font-sans); font-size: var(--ml5-font-size-detail-m); /* 1rem */ font-weight: var(--ml5-font-weight-medium); /* 500 */ line-height: 1; letter-spacing: 0; color: var(--ml5-color-ivory-light); background-color: var(--ml5-color-slate-dark); border: 1px solid var(--ml5-color-slate-dark); border-radius: var(--ml5-radius-round); /* 100vw */ text-decoration: none; cursor: pointer; user-select: none; transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease; } .ml5-btn:hover { background-color: var(--ml5-color-slate-medium); border-color: var(--ml5-color-slate-medium); } .ml5-btn:active { background-color: var(--ml5-color-slate-light); } .ml5-btn:focus-visible { outline: var(--ml5-focus-width) solid var(--ml5-color-slate-dark); outline-offset: var(--ml5-focus-offset-outer); } .ml5-btn:disabled, .ml5-btn[aria-disabled="true"] { opacity: 0.4; pointer-events: none; } /* --- Secondary (ghost outline) --- */ .ml5-btn--secondary { background-color: transparent; color: var(--ml5-color-slate-dark); } .ml5-btn--secondary:hover { background-color: var(--ml5-color-slate-dark); color: var(--ml5-color-ivory-light); } /* --- Tertiary (faded border) --- */ .ml5-btn--tertiary { background-color: transparent; color: var(--ml5-color-slate-dark); border-color: var(--ml5-color-slate-faded-10); } .ml5-btn--tertiary:hover { background-color: var(--ml5-color-ivory-medium); border-color: var(--ml5-color-slate-faded-20); } /* --- Nav-variant (в шапке) --- */ .ml5-btn--nav:hover { background-color: var(--ml5-color-clay); /* #d97757 — signature accent */ border-color: var(--ml5-color-clay); color: var(--ml5-color-ivory-light); } /* Инверсия на тёмном фоне */ .ml5-on-dark .ml5-btn { background-color: var(--ml5-color-ivory-light); color: var(--ml5-color-slate-dark); border-color: var(--ml5-color-ivory-light); } .ml5-on-dark .ml5-btn:hover { background-color: var(--ml5-color-ivory-medium); } .ml5-on-dark .ml5-btn--secondary { background-color: transparent; color: var(--ml5-color-ivory-light); border-color: var(--ml5-color-ivory-faded-20); } .ml5-on-dark .ml5-btn--secondary:hover { background-color: var(--ml5-color-ivory-light); color: var(--ml5-color-slate-dark); } ``` ### States Matrix | State | Primary | Secondary (ghost) | Tertiary | Nav-variant | |-----------------|-----------------------------------------|------------------------------------------------|---------------------------------------------|------------------------------------------| | Default | bg slate-dark, text ivory | bg transparent, border slate-dark, text slate | bg transparent, border slate-faded-10 | bg slate-dark, text ivory | | Hover | bg slate-medium | bg slate-dark, text ivory | bg ivory-medium, border slate-faded-20 | **bg clay #d97757** | | Active | bg slate-light | bg slate-medium | bg ivory-dark | bg clay + brightness(0.95) | | Focus-visible | outline 2px slate-dark, offset 0.25rem | outline 2px slate-dark | outline 2px slate-dark | outline 2px clay | | Disabled | opacity 0.4, pointer-events none | opacity 0.4 | opacity 0.4 | opacity 0.4 | **Anti-patterns:** - Не использовать `font-weight: 700` — это нарушит editorial-whisper тональность (96% weight 400/500). - Не добавлять `text-transform: uppercase` — CTA остаются sentence-case («Start free», не «START FREE»). - Не ставить тень на кнопке. В этой системе тени живут только на карточках (см. §3). - Не смешивать clay hover с primary вариантом — clay зарезервирован за `.ml5-btn--nav`. - Не делать выступающий `border-radius: 8px` на pill — радиус `100vw` — единственный для кнопок. --- ## 2. Editorial H1 with Underline-as-Editing Сигнатурный приём: в H1 ключевые слова («research», «products») обёрнуты в `` с `text-decoration: underline`. Это декорация, не ссылка. В DOM H1 дублируется (`.ml5-h1--mirror`) для reveal-анимации underline (один слой без линии → второй поверх с линией `fadein`). ```html

AI research and products that put safety at the frontier

AI research and products that put safety at the frontier

``` ```css .ml5-h1 { font-family: var(--ml5-font-sans); font-size: var(--ml5-font-size-display-xxl); /* clamp(2.75rem, … , 4.5rem) */ font-weight: var(--ml5-font-weight-bold); /* 700 — только в H1 */ line-height: var(--ml5-line-height-1-1); /* 1.1 */ letter-spacing: var(--ml5-letter-spacing-0-02em); /* -.02em */ color: var(--ml5-color-slate-dark); text-align: left; text-wrap: balance; margin: 0; } .ml5-h1__underline { text-decoration: underline; text-decoration-thickness: 0.06em; /* 3-5px на больших кеглях */ text-underline-offset: 0.1em; text-decoration-color: var(--ml5-color-slate-dark); text-decoration-skip-ink: none; /* альтернатива: text-decoration-style: wavy; */ } /* Mirror-слой для reveal */ .ml5-h1--mirror { position: absolute; inset: 0; pointer-events: none; animation: ml5-fadein 0.8s cubic-bezier(0.77, 0, 0.175, 1) 0.2s both; } .ml5-h1--mirror .ml5-h1__underline { animation: ml5-underline-draw 0.6s cubic-bezier(0.77, 0, 0.175, 1) 0.5s both; } @keyframes ml5-fadein { from { opacity: 0; } to { opacity: 1; } } @keyframes ml5-underline-draw { from { text-decoration-color: transparent; } to { text-decoration-color: var(--ml5-color-slate-dark); } } /* Ответственная раскладка */ @media (prefers-reduced-motion: reduce) { .ml5-h1--mirror, .ml5-h1--mirror .ml5-h1__underline { animation: none; } } ``` ### States Matrix | State | Поведение | |------------------|------------------------------------------------------------------| | Default | H1 sans 700, underline 0.06em thickness, offset 0.1em | | On scroll-in | `.ml5-h1--mirror` opacity 0 → 1, underline draws in | | Hover (если CTA) | Не применимо: H1 — не ссылка | | Dark mode | `color: var(--ml5-color-ivory-light)`, underline такого же цвета | | prefers-reduced-motion | mirror видим сразу без анимации | **Anti-patterns:** - Не оборачивать в `` — подчёркивание здесь не «ссылка», а редакторский знак. Если нужен линк в H1 — делать отдельный класс `ml5-h1__link`. - Не использовать `border-bottom` вместо `text-decoration` — при переносе строки border уедет в неправильное место. - Не применять к H2/H3 — приём эксклюзивен для H1 hero. - Не выставлять `text-decoration-thickness` в px — использовать em, иначе ломается при масштабе. --- ## 3. Release Card (Editorial) Cream-карточка для «Latest releases» — трёхколоночная сетка с DATE (uppercase detail-xs), CATEGORY (detail-xs), serif H3 и meta-ссылкой. Hover запускает **whisper-shadow** — дорожную карту этой книги: три наложенных тени с rgba 0.01 / 0.02 / 0.04 (буквально шёпот). ```html

Latest releases

``` ```css .ml5-releases__grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--ml5-space-6); /* ~2rem */ padding: 0; margin: 0; list-style: none; } .ml5-release-card { grid-column: span 4; /* 12/3 = 4 col per card */ background-color: var(--ml5-color-ivory-medium); border-radius: var(--ml5-radius-large); /* 16px */ transition: box-shadow 0.2s ease, transform 0.2s ease; } @media (max-width: 767px) { .ml5-release-card { grid-column: span 12; } } .ml5-release-card__link { display: flex; flex-direction: column; gap: var(--ml5-space-5); padding: var(--ml5-space-6); color: var(--ml5-color-slate-dark); text-decoration: none; height: 100%; } .ml5-release-card__meta { display: flex; gap: var(--ml5-space-4); align-items: baseline; } .ml5-release-card__date, .ml5-release-card__category { font-family: var(--ml5-font-sans); font-size: var(--ml5-font-size-detail-xs); /* 0.75rem */ font-weight: var(--ml5-font-weight-medium); letter-spacing: 0.02em; text-transform: uppercase; color: var(--ml5-color-slate-light); } .ml5-release-card__title { font-family: var(--ml5-font-serif); font-size: var(--ml5-font-size-display-l); /* 3rem clamp */ font-weight: var(--ml5-font-weight-regular); /* 400 на serif */ line-height: var(--ml5-line-height-1-1); letter-spacing: 0; color: var(--ml5-color-slate-dark); margin: 0; text-wrap: balance; } .ml5-release-card__cta { display: inline-flex; align-items: center; gap: var(--ml5-space-2); margin-top: auto; font-family: var(--ml5-font-sans); font-size: var(--ml5-font-size-detail-m); font-weight: var(--ml5-font-weight-medium); color: var(--ml5-color-slate-dark); text-decoration: underline; text-underline-offset: 0.1em; transition: text-underline-offset 0.2s ease, color 0.2s ease; } /* --- Hover: whisper-shadow --- */ .ml5-release-card:hover { box-shadow: rgba(0, 0, 0, 0.01) 0px 2px 2px 0px, rgba(0, 0, 0, 0.02) 0px 4px 4px 0px, rgba(0, 0, 0, 0.04) 0px 16px 24px 0px; } .ml5-release-card:hover .ml5-release-card__title, .ml5-release-card:hover .ml5-release-card__cta { color: var(--ml5-color-slate-medium); } .ml5-release-card:hover .ml5-release-card__cta { text-underline-offset: 0.2em; /* editorial nudge */ } .ml5-release-card__link:focus-visible { outline: var(--ml5-focus-width) solid var(--ml5-color-slate-dark); outline-offset: -2px; border-radius: var(--ml5-radius-large); } ``` ### States Matrix | State | Изменения | |-----------------|----------------------------------------------------------------------------| | Default | bg ivory-medium, без тени, title serif 400 | | Hover | whisper-shadow (три слоя rgba 0.01/0.02/0.04), title/cta → slate-medium | | Hover (cta) | text-underline-offset 0.1em → 0.2em | | Focus-visible | outline 2px slate-dark inset -2px (карточка целиком как link target) | | Active | Без отдельного стиля (переход по ссылке быстрый) | **Anti-patterns:** - Не добавлять `transform: translateY(-4px)` — книга запрещает лифт. Только shadow-whisper. - Не использовать `font-weight: 700` на title — serif 400 намеренно «книжный». - Не делать полный uppercase на title — только мета-строка. - Не уменьшать тень до одного слоя — сигнатура именно в трёх наложенных rgba. --- ## 4. Dark Inset Inversion Block (Flagship Initiative) Тёмная карточка-инверсия внутри cream body. Используется **однократно на viewport** — ядро editorial-контраста. Фон slate-dark #141413, внутри может жить organic SVG (biomimicry, сетка) как бэкграунд. Text — ivory-light, H2 — serif 400 display-xl. ```html
A research collaboration

Flagship Initiative

Exploring the intersection of AI safety and biological systems — what nature can teach us about alignment.

``` ```css .ml5-invert { padding: var(--ml5-section-space-main) var(--ml5-site-margin); } .ml5-invert__inner { position: relative; max-width: var(--ml5-site-width); margin: 0 auto; padding: clamp(3rem, 1.8rem + 5vw, 5rem); background-color: var(--ml5-color-slate-dark); color: var(--ml5-color-ivory-light); border-radius: var(--ml5-radius-large); /* 16px */ overflow: hidden; isolation: isolate; } .ml5-invert__bg { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0.08; color: var(--ml5-color-ivory-faded-20); z-index: 0; pointer-events: none; } .ml5-invert__content { position: relative; z-index: 1; display: flex; flex-direction: column; gap: var(--ml5-space-5); max-width: 48rem; } .ml5-invert__eyebrow { font-family: var(--ml5-font-sans); font-size: var(--ml5-font-size-detail-xs); font-weight: var(--ml5-font-weight-medium); letter-spacing: 0.02em; text-transform: uppercase; color: var(--ml5-color-cloud-medium); } .ml5-invert__title { font-family: var(--ml5-font-serif); font-size: var(--ml5-font-size-display-xl); /* 4rem clamp */ font-weight: var(--ml5-font-weight-regular); line-height: var(--ml5-line-height-1-05); letter-spacing: 0; color: var(--ml5-color-ivory-light); margin: 0; } .ml5-invert__body { font-family: var(--ml5-font-serif); font-size: var(--ml5-font-size-paragraph-m); font-weight: var(--ml5-font-weight-regular); line-height: var(--ml5-line-height-1-4); color: var(--ml5-color-ivory-faded-20); max-width: 40rem; margin: 0; } .ml5-invert__actions { margin-top: var(--ml5-space-3); } /* В тёмном контексте primary btn должна инвертироваться. Добавляем класс ml5-on-dark на .ml5-invert__inner, если нужно */ .ml5-invert__inner .ml5-btn { background-color: var(--ml5-color-ivory-light); color: var(--ml5-color-slate-dark); border-color: var(--ml5-color-ivory-light); } .ml5-invert__inner .ml5-btn:hover { background-color: var(--ml5-color-ivory-medium); } ``` ### States Matrix | State | Изменения | |-----------------------|---------------------------------------------------------------| | Default | bg slate-dark, text ivory-light, SVG bg opacity 0.08 | | Scroll-in | opacity 0 → 1, translateY(24px) → 0, ease-out 0.8s | | Button hover (внутри) | bg ivory-medium (инверсия primary) | | Focus-visible (btn) | outline 2px ivory-light | | Mobile | padding сжимается до `clamp(2rem, 5vw, 3rem)` | **Anti-patterns:** - Не дублировать на одной странице — один dark-invert на viewport-экран, иначе теряется «editorial accent». - Не класть глянцевые градиенты — фон всегда solid slate-dark. - Не использовать `font-weight: 700` на title — serif 400. - Не ставить `border-radius: 24+` — в этой книге карточки держатся на `--ml5-radius-large` = 16px. --- ## 5. Navigation Bar + Mega-Menu (Dropdown Desktop / Hamburger Mobile) Фиксированный `4.25rem` nav (от `--nav--height`), прозрачный на hero → solid ivory на scroll. Desktop: hover/click на `Products`/`Learn` раскрывает dropdown с grid-layout и preview-картинкой. Mobile: hamburger → full-screen drawer с `clip-path` curtain-down анимацией (keyframes `menuOpen`/`menuClose`). ```html
``` ```css .ml5-nav { position: fixed; top: 0; left: 0; right: 0; z-index: var(--ml5-z-header); /* 1000 */ height: var(--ml5-nav-height); /* 4.25rem */ background-color: transparent; transition: background-color 0.2s ease, box-shadow 0.2s ease; } .ml5-nav[data-scrolled="true"] { background-color: var(--ml5-color-ivory-light); box-shadow: rgba(0, 0, 0, 0.01) 0px 2px 2px 0px, rgba(0, 0, 0, 0.02) 0px 4px 4px 0px; } .ml5-nav__inner { display: flex; align-items: center; justify-content: space-between; gap: var(--ml5-space-6); height: 100%; max-width: var(--ml5-site-width); margin: 0 auto; padding: 0 var(--ml5-site-margin); } .ml5-nav__menu { display: flex; align-items: center; gap: var(--ml5-space-2); } .ml5-nav__link { display: inline-flex; align-items: center; gap: var(--ml5-space-2); padding: var(--ml5-space-2) var(--ml5-space-3); font-family: var(--ml5-font-sans); font-size: var(--ml5-font-size-detail-m); /* 1rem */ font-weight: var(--ml5-font-weight-regular); /* 400 */ color: var(--ml5-color-slate-dark); background: none; border: 0; cursor: pointer; text-decoration: none; white-space: nowrap; transition: color 0.2s ease, text-underline-offset 0.2s ease; } .ml5-nav__link:hover { text-decoration: underline; text-underline-offset: 0.2em; /* signature hover */ text-decoration-color: var(--ml5-color-slate-dark); } .ml5-nav__caret { transition: transform 0.2s cubic-bezier(0.77, 0, 0.175, 1); } .ml5-nav__link[aria-expanded="true"] .ml5-nav__caret { transform: rotate(180deg); } .ml5-nav__actions { display: flex; align-items: center; gap: var(--ml5-space-5); } .ml5-nav__action-link { font-family: var(--ml5-font-sans); font-size: var(--ml5-font-size-detail-m); font-weight: var(--ml5-font-weight-regular); color: var(--ml5-color-slate-dark); text-decoration: none; transition: color 0.2s ease; } .ml5-nav__action-link:hover { text-decoration: underline; text-underline-offset: 0.2em; } /* Hamburger (mobile) */ .ml5-nav__hamburger { display: none; width: 24px; height: 24px; flex-direction: column; justify-content: center; gap: var(--ml5-hamburger-gap); /* 0.4rem */ padding: 0; background: none; border: 0; cursor: pointer; } .ml5-nav__hamburger-line { display: block; width: 100%; height: 1px; background-color: var(--ml5-color-slate-dark); transition: transform 0.2s ease; } .ml5-nav__hamburger[aria-expanded="true"] .ml5-nav__hamburger-line:nth-child(1) { transform: translateY(calc(var(--ml5-hamburger-gap) / 2 + 0.5px)) rotate(45deg); } .ml5-nav__hamburger[aria-expanded="true"] .ml5-nav__hamburger-line:nth-child(2) { transform: translateY(calc(var(--ml5-hamburger-gap) / -2 - 0.5px)) rotate(-45deg); } @media (max-width: 991px) { .ml5-nav__menu, .ml5-nav__actions { display: none; } .ml5-nav__hamburger { display: flex; } } /* Full-screen drawer + curtain keyframes */ .ml5-nav__drawer { position: fixed; inset: var(--ml5-nav-height) 0 0 0; background-color: var(--ml5-color-ivory-light); overflow-y: auto; padding: var(--ml5-space-6) var(--ml5-site-margin); clip-path: polygon(0 0, 100% 0, 100% 0, 0 0); animation: ml5-menu-open 400ms cubic-bezier(0.77, 0, 0.175, 1) forwards; } .ml5-nav__drawer[data-closing="true"] { animation: ml5-menu-close 400ms cubic-bezier(0.77, 0, 0.175, 1) forwards; } @keyframes ml5-menu-open { from { clip-path: polygon(0 0, 100% 0, 100% 0, 0 0); } to { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); } } @keyframes ml5-menu-close { from { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); } to { clip-path: polygon(0 0, 100% 0, 100% 0, 0 0); } } ``` ### States Matrix | State | Изменения | |----------------------------|---------------------------------------------------------------| | Default (hero overlay) | bg transparent, links slate-dark | | Scrolled (`data-scrolled`) | bg ivory-light, whisper-shadow (2 слоя) | | Link hover | text underline, offset 0.2em | | Dropdown open | caret rotate 180°, dropdown opacity 0→1 200ms cubic | | Hamburger open | drawer clip-path curtain 400ms, lines cross 45° | | Focus-visible (link) | outline 2px slate-dark, offset 0.25rem | | Drawer close | reversed curtain, 400ms | **Anti-patterns:** - Не включать `background-color` в transition на hover ссылок — signature именно в underline-offset, не в подсветке. - Не использовать `font-weight: 500` в навигации — **regular 400** (в отличие от большинства сайтов). - Не ставить иконки рядом с ссылками — nav чисто текстовый (кроме caret-chevron). - `.ml5-btn--nav` — единственная кнопка с clay hover. Не применять clay к `.ml5-nav__link`. --- ## 6. Footer Mega-Menu (Slate-dark + 8 Column Groups) Большой финальный блок. Фон slate-dark, текст ivory-light. `footer_grid` — 12 колонок с gap `~3.4rem`. 8 тематических групп (Product / Products / Models / Solutions / Platform / Resources / Company / Legal). Внизу small-print + cookie choices + language switcher. ```html ``` ```css .ml5-footer { background-color: var(--ml5-color-slate-dark); color: var(--ml5-color-ivory-light); padding: var(--ml5-section-space-medium) var(--ml5-site-margin) var(--ml5-space-6); } .ml5-footer__inner { max-width: var(--ml5-site-width); margin: 0 auto; } .ml5-footer__grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: 3.4rem; padding-bottom: var(--ml5-space-9); border-bottom: 1px solid var(--ml5-color-ivory-faded-10); } .ml5-footer__group { grid-column: span 3; display: flex; flex-direction: column; gap: var(--ml5-space-4); } @media (max-width: 991px) { .ml5-footer__group { grid-column: span 6; } } @media (max-width: 479px) { .ml5-footer__group { grid-column: span 12; } } .ml5-footer__heading { font-family: var(--ml5-font-sans); font-size: var(--ml5-font-size-detail-xs); font-weight: var(--ml5-font-weight-medium); text-transform: uppercase; letter-spacing: 0.02em; color: var(--ml5-color-cloud-medium); margin: 0; } .ml5-footer__list { display: flex; flex-direction: column; gap: var(--ml5-space-3); margin: 0; padding: 0; list-style: none; } .ml5-footer__link { font-family: var(--ml5-font-sans); font-size: var(--ml5-font-size-detail-m); font-weight: var(--ml5-font-weight-regular); color: var(--ml5-color-ivory-light); text-decoration: none; transition: text-underline-offset 0.2s ease, text-decoration-color 0.2s ease; } .ml5-footer__link:hover { text-decoration: underline; text-underline-offset: 0.25em; /* чуть больше чем в nav */ text-decoration-color: var(--ml5-color-ivory-light); } .ml5-footer__link:focus-visible { outline: var(--ml5-focus-width) solid var(--ml5-color-ivory-light); outline-offset: var(--ml5-focus-offset-outer); } .ml5-footer__bottom { display: flex; flex-wrap: wrap; gap: var(--ml5-space-5); align-items: center; justify-content: space-between; padding-top: var(--ml5-space-6); font-size: var(--ml5-font-size-detail-s); color: var(--ml5-color-cloud-medium); } .ml5-footer__legal { display: flex; gap: var(--ml5-space-5); } ``` ### States Matrix | State | Изменения | |-------------------------|-------------------------------------------------------------| | Default | bg slate-dark, links ivory-light, headings cloud-medium | | Link hover | underline, offset **0.25em** (больше чем nav 0.2em) | | Link focus-visible | outline 2px ivory-light | | Mobile (991-) | 4 cols → 2 (span 6) | | Mobile (479-) | 2 cols → 1 (span 12) | | Language switcher hover | underline + offset 0.25em | **Anti-patterns:** - Не уменьшать gap ниже `2rem` — разреженная сетка — часть editorial-прочтения. - Не раскрашивать headings — только cloud-medium (средне-серый). - Не использовать разные weights в колонках — regular 400 везде. - Не ставить иконки соцсетей в body footer — если нужны, отдельная секция над `footer__bottom`. --- ## 7. Cookie Consent Banner (Dark Modal) Плавающий тёмный баннер, привязан к правому нижнему углу. Повторяет dark-invert эстетику (§4): slate-dark bg, ivory-light текст, radius `--ml5-radius-large` = 16px. Три CTA: Reject / Customize / Accept — в порядке возрастания веса (tertiary → secondary → primary). ```html ``` ```css .ml5-cookie { position: fixed; right: 16px; bottom: 16px; max-width: 480px; width: calc(100% - 32px); z-index: 2000; animation: ml5-fadein 0.3s ease-out; } .ml5-cookie__inner { position: relative; padding: var(--ml5-space-6); background-color: var(--ml5-color-slate-dark); color: var(--ml5-color-ivory-light); border-radius: var(--ml5-radius-large); /* 16px */ box-shadow: rgba(0, 0, 0, 0.01) 0px 2px 2px 0px, rgba(0, 0, 0, 0.02) 0px 4px 4px 0px, rgba(0, 0, 0, 0.04) 0px 16px 24px 0px; } .ml5-cookie__title { font-family: var(--ml5-font-sans); font-size: var(--ml5-font-size-detail-xl); /* 1.25rem */ font-weight: var(--ml5-font-weight-medium); margin: 0 0 var(--ml5-space-3) 0; color: var(--ml5-color-ivory-light); } .ml5-cookie__body { font-family: var(--ml5-font-serif); font-size: var(--ml5-font-size-detail-s); font-weight: var(--ml5-font-weight-regular); line-height: var(--ml5-line-height-1-4); color: var(--ml5-color-ivory-faded-20); margin: 0 0 var(--ml5-space-5) 0; } .ml5-cookie__actions { display: flex; flex-wrap: wrap; gap: var(--ml5-space-3); align-items: center; } /* В dark-контексте primary btn инвертируется; tertiary/secondary уже корректные */ .ml5-cookie .ml5-btn { background-color: var(--ml5-color-ivory-light); color: var(--ml5-color-slate-dark); border-color: var(--ml5-color-ivory-light); } .ml5-cookie .ml5-btn:hover { background-color: var(--ml5-color-ivory-medium); } .ml5-cookie .ml5-btn--secondary { background-color: transparent; color: var(--ml5-color-ivory-light); border-color: var(--ml5-color-ivory-faded-20); } .ml5-cookie .ml5-btn--secondary:hover { background-color: var(--ml5-color-ivory-light); color: var(--ml5-color-slate-dark); } .ml5-cookie .ml5-btn--tertiary { background-color: transparent; color: var(--ml5-color-cloud-medium); border-color: transparent; padding-left: 0; padding-right: 0; } .ml5-cookie .ml5-btn--tertiary:hover { color: var(--ml5-color-ivory-light); text-decoration: underline; text-underline-offset: 0.2em; } .ml5-cookie__close { position: absolute; top: var(--ml5-space-4); right: var(--ml5-space-4); width: 24px; height: 24px; padding: 0; background: none; border: 0; color: var(--ml5-color-cloud-medium); cursor: pointer; } .ml5-cookie__close:hover { color: var(--ml5-color-ivory-light); } @media (max-width: 479px) { .ml5-cookie { right: 8px; bottom: 8px; } .ml5-cookie__actions { flex-direction: column; align-items: stretch; } } ``` ### States Matrix | State | Изменения | |-----------------------|------------------------------------------------| | Default | entry fadein 0.3s, shadow whisper | | Accept hover | bg ivory-medium | | Customize hover | bg ivory-light, text slate-dark (inversion) | | Reject hover | text cloud-medium → ivory-light, underline 0.2em | | Close (dismiss) | fadeout 0.2s | | Mobile (479-) | actions column, full-width buttons | **Anti-patterns:** - Не центрировать баннер — всегда правый нижний угол, не modal overlay. - Не делать «Accept» красным или зелёным — primary остаётся primary (ivory на dark). - Не блокировать скролл страницы — баннер живёт сбоку, не перекрывает контент. - Не прятать «Reject» (dark-pattern). Все 3 кнопки равно-доступны. --- ## 8. Nav Dropdown Mega-Menu (Desktop) Разворачивается по hover/click на trigger-линке в шапке. Контент: **2-колоночная сетка** — левая колонка preview-картинка/промо, правая — список ссылок с подписями. Анимация opacity 0→1 за 200ms cubic-bezier. ```html ``` ```css .ml5-nav__dropdown { position: absolute; top: 100%; left: 0; right: 0; background-color: var(--ml5-color-ivory-light); border-top: 1px solid var(--ml5-color-slate-faded-10); box-shadow: rgba(0, 0, 0, 0.01) 0px 2px 2px 0px, rgba(0, 0, 0, 0.02) 0px 4px 4px 0px, rgba(0, 0, 0, 0.04) 0px 16px 24px 0px; opacity: 0; pointer-events: none; transition: opacity 0.2s cubic-bezier(0.77, 0, 0.175, 1); } .ml5-nav__item--dropdown[data-open="true"] .ml5-nav__dropdown, .ml5-nav__item--dropdown:hover .ml5-nav__dropdown { opacity: 1; pointer-events: auto; } .ml5-nav__dropdown-inner { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); gap: var(--ml5-space-7); max-width: var(--ml5-site-width); margin: 0 auto; padding: var(--ml5-space-6) var(--ml5-site-margin); /* из parse-css-rules: padding 20/20/20/40 в Webflow-оригинале */ } .ml5-nav__dropdown-feature { display: grid; grid-template-rows: auto auto auto 1fr; gap: var(--ml5-space-2); padding: var(--ml5-space-5); background-color: var(--ml5-color-ivory-medium); border-radius: var(--ml5-radius-large); color: var(--ml5-color-slate-dark); text-decoration: none; transition: box-shadow 0.2s ease; } .ml5-nav__dropdown-feature:hover { box-shadow: rgba(0, 0, 0, 0.01) 0px 2px 2px 0px, rgba(0, 0, 0, 0.02) 0px 4px 4px 0px, rgba(0, 0, 0, 0.04) 0px 16px 24px 0px; } .ml5-nav__dropdown-img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; border-radius: var(--ml5-radius-main); /* 8px */ } .ml5-nav__dropdown-feature-eyebrow { font-size: var(--ml5-font-size-detail-xs); font-weight: var(--ml5-font-weight-medium); letter-spacing: 0.02em; text-transform: uppercase; color: var(--ml5-color-clay); /* единственный акцент */ } .ml5-nav__dropdown-feature-title { font-family: var(--ml5-font-serif); font-size: var(--ml5-font-size-display-s); font-weight: var(--ml5-font-weight-regular); line-height: var(--ml5-line-height-1-1); } .ml5-nav__dropdown-feature-desc { font-family: var(--ml5-font-serif); font-size: var(--ml5-font-size-detail-m); font-weight: var(--ml5-font-weight-regular); color: var(--ml5-color-slate-medium); } .ml5-nav__dropdown-list { display: grid; grid-template-columns: 1fr 1fr; gap: var(--ml5-space-2) var(--ml5-space-5); list-style: none; padding: 0; margin: 0; white-space: nowrap; } .ml5-nav__dropdown-link { display: flex; flex-direction: column; gap: 2px; padding: var(--ml5-space-3) var(--ml5-space-4); border-radius: var(--ml5-radius-main); color: var(--ml5-color-slate-dark); text-decoration: none; transition: background-color 0.2s ease, text-underline-offset 0.2s ease; } .ml5-nav__dropdown-link-title { font-family: var(--ml5-font-sans); font-size: var(--ml5-font-size-detail-m); font-weight: var(--ml5-font-weight-medium); } .ml5-nav__dropdown-link-desc { font-family: var(--ml5-font-sans); font-size: var(--ml5-font-size-detail-s); font-weight: var(--ml5-font-weight-regular); color: var(--ml5-color-slate-light); } .ml5-nav__dropdown-link:hover .ml5-nav__dropdown-link-title { text-decoration: underline; text-underline-offset: 0.2em; text-decoration-color: var(--ml5-color-slate-dark); } ``` ### States Matrix | State | Изменения | |--------------------------|-----------------------------------------------------------------| | Closed | opacity 0, pointer-events none | | Opening (hover/click) | opacity 0 → 1, 200ms cubic-bezier(0.77, 0, 0.175, 1) | | Closing (mouse-leave) | opacity → 0 с delay 200ms (чтобы не терялся на зазоре) | | Link hover | title underline + offset 0.2em | | Feature hover | whisper-shadow | | Focus-visible | outline 2px slate-dark внутри link-блока | **Anti-patterns:** - Не превращать в 3+ колонки — 2 колонки (промо + список) — подпись книги. - Не использовать цветной background hover для ссылок — только underline (editorial жест). - Не закрывать dropdown мгновенно — делать 200ms задержку, иначе теряется на движении между trigger и контентом. - Не ставить уровень вложенности глубже 2 — без sub-sub меню. --- ## 9. Chip / Tab Pill (для фильтров) Полноценный «таб-пилюля» с border-radius round. Используется в listing-страницах (News, Research) как фильтр категорий. Класс `.ml5-chip.is-tab` из оригинала. Hover-состояние вытекает из token `button-primary-hover`. ```html ``` ```css .ml5-chips { display: flex; flex-wrap: wrap; gap: var(--ml5-space-3); padding: 0; margin: 0; list-style: none; } .ml5-chip { padding: var(--ml5-space-2) var(--ml5-space-4); font-family: var(--ml5-font-sans); font-size: var(--ml5-font-size-detail-s); font-weight: var(--ml5-font-weight-regular); color: var(--ml5-color-slate-dark); background-color: transparent; border: 1px solid var(--ml5-color-slate-faded-10); border-radius: var(--ml5-radius-round); cursor: pointer; white-space: nowrap; transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease; } .ml5-chip:hover { background-color: var(--ml5-color-slate-medium); color: var(--ml5-color-ivory-light); border-color: var(--ml5-color-slate-medium); } .ml5-chip:focus-visible { outline: var(--ml5-focus-width) solid var(--ml5-color-slate-dark); outline-offset: var(--ml5-focus-offset-outer); } .ml5-chip--active, .ml5-chip[aria-pressed="true"] { background-color: var(--ml5-color-slate-dark); color: var(--ml5-color-ivory-light); border-color: var(--ml5-color-slate-dark); } .ml5-chip--active:hover, .ml5-chip[aria-pressed="true"]:hover { background-color: var(--ml5-color-slate-medium); border-color: var(--ml5-color-slate-medium); } ``` ### States Matrix | State | Изменения | |--------------------|------------------------------------------------------| | Default | bg transparent, border slate-faded-10, text slate-dark | | Hover | bg slate-medium, text ivory | | Active / pressed | bg slate-dark, text ivory | | Active + hover | bg slate-medium | | Focus-visible | outline 2px slate-dark offset 0.25rem | | Disabled | opacity 0.4, pointer-events none | **Anti-patterns:** - Не делать цветным (`color: clay`) — чипы нейтральные, акцент только на активном. - Не использовать `border-radius: 8px` — pill (100vw) — условие. - Не ставить иконки внутри — текст only. - Максимум 6-7 чипов в ряду; больше — `overflow-x: auto` + snap. --- ## 10. Article-list Item (для Research / News listing) Full-width строка с editorial-разметкой: дата слева, serif title посередине (span flex-grow), автор и chevron справа. Нижняя граница `slate-faded-10` — тонкая линия между записями. Hover: color → slate-medium (без underline — подпись этой книги в list-режиме). ```html ``` ```css .ml5-article-list { list-style: none; padding: 0; margin: 0; border-top: 1px solid var(--ml5-color-slate-faded-10); } .ml5-article-list__item { border-bottom: 1px solid var(--ml5-color-slate-faded-10); } .ml5-article-list__link { display: grid; grid-template-columns: 160px 1fr auto 24px; gap: var(--ml5-space-5); align-items: baseline; padding: var(--ml5-space-6) 0; color: var(--ml5-color-slate-dark); text-decoration: none; transition: color 0.2s ease; } .ml5-article-list__date { font-family: var(--ml5-font-sans); font-size: var(--ml5-font-size-detail-s); font-weight: var(--ml5-font-weight-regular); color: var(--ml5-color-slate-light); } .ml5-article-list__title { font-family: var(--ml5-font-serif); font-size: var(--ml5-font-size-display-s); /* 1.5rem */ font-weight: var(--ml5-font-weight-regular); /* 400 */ line-height: var(--ml5-line-height-1-3); margin: 0; text-wrap: balance; } .ml5-article-list__author { font-family: var(--ml5-font-sans); font-size: var(--ml5-font-size-detail-s); font-weight: var(--ml5-font-weight-regular); color: var(--ml5-color-slate-light); white-space: nowrap; } .ml5-article-list__chevron { color: var(--ml5-color-slate-light); transition: transform 0.2s ease, color 0.2s ease; align-self: center; } /* --- Hover --- */ .ml5-article-list__link:hover { color: var(--ml5-color-slate-medium); } .ml5-article-list__link:hover .ml5-article-list__chevron { transform: translateX(4px); color: var(--ml5-color-slate-dark); } .ml5-article-list__link:focus-visible { outline: var(--ml5-focus-width) solid var(--ml5-color-slate-dark); outline-offset: var(--ml5-focus-offset-outer); } /* Mobile: дата уходит в первую строку, title — во вторую */ @media (max-width: 767px) { .ml5-article-list__link { grid-template-columns: 1fr auto; grid-template-areas: "date chevron" "title title" "author author"; gap: var(--ml5-space-2); } .ml5-article-list__date { grid-area: date; } .ml5-article-list__title { grid-area: title; font-size: var(--ml5-font-size-display-xs); } .ml5-article-list__author { grid-area: author; } .ml5-article-list__chevron { grid-area: chevron; } } ``` ### States Matrix | State | Изменения | |-----------------|------------------------------------------------| | Default | text slate-dark, chevron slate-light | | Hover | text slate-medium, chevron slate-dark + translateX(4px) | | Focus-visible | outline 2px slate-dark | | Mobile | grid стекается вертикально (date/title/author) | **Anti-patterns:** - Не добавлять `text-decoration: underline` на hover title — здесь только color shift. Underline живёт в nav/footer. - Не ставить box-shadow на строку — list-режим намеренно «плоский». - Не использовать border-left для visual accent — только border-bottom единого токена. - Не хардкодить date format — `