Стилизуй на CSS параграфы в Twine чтобы были более...

Erstellt am: 10. August 2026

Beantwortet mit GPT-5.6 Thinking von Chat01

Frage

Стилизуй на CSS параграфы в Twine чтобы были более цветными. Для tw-link лучше использовать black.

Gedanke

Worked for 4s

Antwort

Да — если это Twine / Harlowe, можно сделать параграфы более живыми через мягкие цветные фоны, акцентные линии и разные оттенки для соседних абзацев. А tw-link оставить чёрным.

Вставь это в Story → Stylesheet:

css
/* Основной текст */ tw-passage { color: #2b2b2b; font-size: 1.08em; line-height: 1.7; } /* Стилизация параграфов */ tw-passage p { padding: 14px 18px; margin: 16px 0; border-radius: 10px; border-left: 5px solid #ff7a90; background: linear-gradient( 135deg, rgba(255, 210, 220, 0.45), rgba(255, 240, 200, 0.35) ); box-shadow: 0 3px 10px rgba(0, 0, 0, 0.06); transition: transform 0.2s ease, box-shadow 0.2s ease; } /* Разные цвета для абзацев */ tw-passage p:nth-of-type(3n + 1) { border-left-color: #ff6b81; background: linear-gradient( 135deg, rgba(255, 190, 205, 0.45), rgba(255, 225, 195, 0.3) ); } tw-passage p:nth-of-type(3n + 2) { border-left-color: #7d8cff; background: linear-gradient( 135deg, rgba(205, 215, 255, 0.45), rgba(225, 205, 255, 0.3) ); } tw-passage p:nth-of-type(3n + 3) { border-left-color: #52c7a5; background: linear-gradient( 135deg, rgba(195, 245, 225, 0.45), rgba(215, 240, 255, 0.3) ); } /* Небольшой эффект при наведении */ tw-passage p:hover { transform: translateY(-2px); box-shadow: 0 5px 14px rgba(0, 0, 0, 0.1); } /* Ссылки Twine */ tw-link { color: black; font-weight: 600; text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 3px; transition: opacity 0.15s ease, background-color 0.15s ease; } tw-link:hover { color: black; background-color: rgba(255, 220, 80, 0.65); opacity: 0.8; } /* Уже посещённые ссылки тоже чёрные */ tw-link.visited { color: black; }

Получится скорее цветной UI-карточный стиль, но без кислотных цветов: розовые, фиолетово-синие и мятные абзацы будут чередоваться, а ссылки останутся чёрными и хорошо заметными.

Если хочется именно более яркий визуальный стиль для визуальной новеллы — с цветным текстом, glow-эффектами и более красивыми tw-link как кнопками — я могу дать второй вариант CSS.

Frage

Придумай ещё цвет для tw-story а то blue выглядит очень плохо

Gedanke

Worked for a few seconds

Antwort

Для tw-story я бы взял не чистый blue, а более спокойный фон, чтобы цветные параграфы не спорили с ним.

Лучше всего сюда подойдёт тёмный фиолетово-синий:

css
tw-story { background-color: #25243a; }

Ещё хорошие варианты:

css
/* Тёплый тёмно-фиолетовый */ background-color: #30263d; /* Глубокий серо-синий */ background-color: #293241; /* Тёмный сливовый */ background-color: #35283b; /* Мягкий тёмно-зелёный */ background-color: #263832; /* Светлый кремовый, если нужен светлый дизайн */ background-color: #f5efe6;

Для твоего текущего розово-мятно-фиолетового оформления я бы выбрал #30263d:

css
tw-story { background: #30263d; }

Он достаточно тёмный, но не выглядит как стандартный синий экран, а пастельные карточки на нём будут хорошо выделяться.

Frage

Придумай как сделать выбор диалогов как кнопки

Gedanke

Worked for a few seconds

Antwort

Можно сделать выборы как полноценные кнопки диалога: светлые карточки, чёрный текст, рамка и небольшой эффект нажатия. Для твоего тёмного tw-story это будет смотреться хорошо.

css
/* Кнопки выбора */ tw-link { display: block; width: 100%; box-sizing: border-box; margin: 10px 0; padding: 14px 18px; color: black; background: #f4d6e8; border: 2px solid #d99bc1; border-radius: 12px; font-weight: 600; text-decoration: none; text-align: left; cursor: pointer; transition: transform 0.15s ease, background 0.15s ease, box-shadow 0.15s ease; } /* Наведение */ tw-link:hover { color: black; background: #f8c8e1; transform: translateX(5px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18); } /* Нажатие */ tw-link:active { transform: translateX(5px) scale(0.98); } /* Посещённые варианты тоже не становятся фиолетовыми */ tw-link.visited { color: black; }

В самом Twine можно тогда писать обычные варианты:

twine
[[Спросить: «Что здесь произошло?»->Question]] [[Промолчать и осмотреть комнату->LookAround]] [[Уйти, пока не стало хуже->Leave]]

И получится примерно такой принцип:

text
┌─────────────────────────────────────────┐ │ Спросить: «Что здесь произошло?» │ └─────────────────────────────────────────┘ ┌─────────────────────────────────────────┐ │ Промолчать и осмотреть комнату │ └─────────────────────────────────────────┘ ┌─────────────────────────────────────────┐ │ Уйти, пока не стало хуже │ └─────────────────────────────────────────┘

Ещё интереснее будет чередовать цвета вариантов, чтобы выбор выглядел живее:

css
tw-link:nth-of-type(3n + 1) { background: #f4d6e8; border-color: #d99bc1; } tw-link:nth-of-type(3n + 2) { background: #d9e4ff; border-color: #9eafe0; } tw-link:nth-of-type(3n + 3) { background: #d5eee4; border-color: #91c9b3; } tw-link:nth-of-type(3n + 1):hover { background: #f7c6df; } tw-link:nth-of-type(3n + 2):hover { background: #cbd9ff; } tw-link:nth-of-type(3n + 3):hover { background: #c3e8d9; }

Я бы ещё добавил перед каждым вариантом маленький символ — тогда они будут ощущаться именно как варианты ответа:

css
tw-link::before { content: "›"; margin-right: 10px; font-size: 1.25em; font-weight: bold; }

Такой вариант особенно хорошо сочетается с твоим фоном #30263d: тёмный фон + пастельные кнопки + чёрный текст.

Frage

Сделай по-братски кнопку выхода из игры при нажатии на esc и чтобы она при наведении курсора "убегала" от него

Gedanke

Worked for 5s

Antwort

Можно 😄 Сделаем так: при нажатии Esc появляется затемнение с кнопкой «Выйти из игры», но как только курсор приближается — кнопка прыгает в другое место.

В Story → JavaScript вставь:

javascript
(function () { const overlay = document.createElement("div"); overlay.id = "exit-overlay"; const box = document.createElement("div"); box.id = "exit-box"; const title = document.createElement("div"); title.id = "exit-title"; title.textContent = "Точно хочешь выйти?"; const button = document.createElement("button"); button.id = "exit-button"; button.textContent = "Выйти из игры"; box.appendChild(title); box.appendChild(button); overlay.appendChild(box); document.body.appendChild(overlay); function showExit() { overlay.classList.add("active"); moveButton(); } function hideExit() { overlay.classList.remove("active"); } document.addEventListener("keydown", function (event) { if (event.key === "Escape") { if (overlay.classList.contains("active")) { hideExit(); } else { showExit(); } } }); function moveButton() { const padding = 30; const maxX = window.innerWidth - button.offsetWidth - padding; const maxY = window.innerHeight - button.offsetHeight - padding; const x = Math.max( padding, Math.random() * (maxX - padding) ); const y = Math.max( padding, Math.random() * (maxY - padding) ); button.style.left = x + "px"; button.style.top = y + "px"; } /* Убегает при наведении */ button.addEventListener("mouseenter", moveButton); /* И ещё раньше — когда мышь подходит близко */ document.addEventListener("mousemove", function (event) { if (!overlay.classList.contains("active")) return; const rect = button.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; const distance = Math.hypot( event.clientX - centerX, event.clientY - centerY ); if (distance < 120) { moveButton(); } }); button.addEventListener("click", function () { /* * Браузеры обычно запрещают сайту закрывать вкладку, * если она не была открыта через JavaScript. */ window.close(); /* Если вкладка не закрылась — убираем игру */ setTimeout(function () { document.body.innerHTML = ` <div class="game-over-screen"> <h1>Игра закрыта.</h1> <p>Ну почти.</p> </div> `; }, 150); }); })();

А в Story → Stylesheet:

css
/* Затемнение при Esc */ #exit-overlay { position: fixed; inset: 0; z-index: 999999; background: rgba(20, 15, 28, 0.88); backdrop-filter: blur(6px); opacity: 0; visibility: hidden; transition: opacity 0.25s ease, visibility 0.25s ease; } #exit-overlay.active { opacity: 1; visibility: visible; } /* Надпись */ #exit-title { position: fixed; top: 22%; left: 50%; transform: translateX(-50%); color: #f7eafa; font-size: 1.7em; font-weight: bold; text-align: center; pointer-events: none; } /* Та самая мерзкая кнопка */ #exit-button { position: fixed; padding: 15px 25px; color: black; background: #f4d6e8; border: 2px solid #d99bc1; border-radius: 14px; font-size: 1em; font-weight: bold; cursor: pointer; box-shadow: 0 5px 18px rgba(0, 0, 0, 0.25); transition: left 0.12s ease, top 0.12s ease, transform 0.12s ease, background 0.12s ease; } #exit-button:hover { color: black; background: #ffc4df; transform: rotate(-3deg) scale(1.05); } /* Фальшивый экран после выхода */ .game-over-screen { position: fixed; inset: 0; display: flex; flex-direction: column; justify-content: center; align-items: center; background: #30263d; color: #f7eafa; font-family: inherit; text-align: center; } .game-over-screen h1 { margin-bottom: 5px; } .game-over-screen p { opacity: 0.65; }

Самое забавное тут то, что кнопка начинает убегать ещё до наведения, когда курсор оказывается ближе чем на 120px.

Если хочешь сделать её ещё более издевательской, поменяй:

javascript
if (distance < 120)

на:

javascript
if (distance < 200)

Тогда поймать её будет практически невозможно.

И да: настоящее window.close() браузер обычно блокирует для обычной вкладки. Поэтому я добавил запасной вариант — после успешного клика игра просто превращается в экран «Игра закрыта. Ну почти.».

Frage

Поменяй вместо затемнения игры, эффект фокуса.

Gedanke

Worked for a couple of seconds

Antwort

Да, лучше сделать эффект расфокуса игры, будто камера фокусируется на меню выхода. Вместо затемнения фон будет просто размываться.

Замени стили #exit-overlay на эти:

css
#exit-overlay { position: fixed; inset: 0; z-index: 999999; /* Фон прозрачный — никакого затемнения */ background: rgba(255, 255, 255, 0.01); /* Эффект расфокуса игры */ backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); opacity: 0; visibility: hidden; transition: opacity 0.3s ease, visibility 0.3s ease, backdrop-filter 0.3s ease; } #exit-overlay.active { opacity: 1; visibility: visible; }

Я бы ещё сделал сам текст немного более «в фокусе», чтобы он визуально выступал над размытой игрой:

css
#exit-title { position: fixed; top: 22%; left: 50%; transform: translateX(-50%); color: white; font-size: 1.7em; font-weight: bold; text-align: center; text-shadow: 0 2px 5px rgba(0, 0, 0, 0.4), 0 0 18px rgba(255, 255, 255, 0.25); pointer-events: none; }

А если хочется прям эффекта глубины резкости, можно сделать чуть интереснее:

css
#exit-overlay { position: fixed; inset: 0; z-index: 999999; background: transparent; backdrop-filter: blur(10px) saturate(0.75); -webkit-backdrop-filter: blur(10px) saturate(0.75); opacity: 0; visibility: hidden; transition: opacity 0.35s ease, visibility 0.35s ease; } #exit-overlay.active { opacity: 1; visibility: visible; }

Тогда при Esc сама игра становится слегка размытой и менее насыщенной, а надпись и убегающая кнопка остаются идеально резкими. По-моему, для такого меню это выглядит намного приятнее, чем просто чёрное затемнение.

Frage

Лучше, сделай чтобы она "уплывала" не быстро и скажем вокруг курсора была

Gedanke

Worked for a couple of seconds

Antwort

Да, так будет приятнее: не телепортировать кнопку, а сделать зону отталкивания вокруг курсора. Когда мышь подходит близко, кнопка плавно «уплывает» от неё, а не скачет по экрану.

В JavaScript замени старые moveButton() и обработчик mousemove на это:

javascript
let buttonX = window.innerWidth / 2; let buttonY = window.innerHeight / 2; let targetX = buttonX; let targetY = buttonY; const escapeRadius = 180; // Радиус вокруг курсора const pushStrength = 7; // Насколько сильно кнопка отплывает const smoothness = 0.045; // Чем меньше — тем медленнее движение function resetButtonPosition() { buttonX = window.innerWidth / 2 - button.offsetWidth / 2; buttonY = window.innerHeight * 0.55; targetX = buttonX; targetY = buttonY; button.style.left = buttonX + "px"; button.style.top = buttonY + "px"; } /* Кнопка плавно отталкивается от курсора */ document.addEventListener("mousemove", function (event) { if (!overlay.classList.contains("active")) return; const rect = button.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; const dx = centerX - event.clientX; const dy = centerY - event.clientY; const distance = Math.hypot(dx, dy); /* Если курсор вошёл в "зону страха" кнопки */ if (distance < escapeRadius) { /* * Чем ближе курсор — * тем сильнее кнопка отплывает. */ const force = (escapeRadius - distance) / escapeRadius; const safeDistance = Math.max(distance, 1); const directionX = dx / safeDistance; const directionY = dy / safeDistance; targetX += directionX * pushStrength * force; targetY += directionY * pushStrength * force; } }); /* Плавная анимация */ function animateButton() { buttonX += (targetX - buttonX) * smoothness; buttonY += (targetY - buttonY) * smoothness; /* Не даём кнопке уплыть за экран */ const padding = 25; const maxX = window.innerWidth - button.offsetWidth - padding; const maxY = window.innerHeight - button.offsetHeight - padding; buttonX = Math.max( padding, Math.min(buttonX, maxX) ); buttonY = Math.max( padding, Math.min(buttonY, maxY) ); targetX = Math.max( padding, Math.min(targetX, maxX) ); targetY = Math.max( padding, Math.min(targetY, maxY) ); button.style.left = buttonX + "px"; button.style.top = buttonY + "px"; requestAnimationFrame(animateButton); } animateButton();

И функцию showExit() поменяй на:

javascript
function showExit() { overlay.classList.add("active"); setTimeout(function () { resetButtonPosition(); }, 20); }

Также удали старое:

javascript
button.addEventListener("mouseenter", moveButton);

и старую функцию:

javascript
function moveButton() { ... }

В CSS у кнопки лучше убрать анимацию left и top, потому что теперь плавность контролирует JavaScript:

css
#exit-button { position: fixed; padding: 15px 25px; color: black; background: #f4d6e8; border: 2px solid #d99bc1; border-radius: 14px; font-size: 1em; font-weight: bold; cursor: pointer; box-shadow: 0 5px 18px rgba(0, 0, 0, 0.25); transition: transform 0.2s ease, background 0.2s ease; }

Теперь механика получается такая: курсор имеет вокруг себя невидимый круг примерно 180 px, и когда кнопка оказывается внутри него, она начинает медленно отплывать в противоположную сторону.

Можно настроить характер:

javascript
const escapeRadius = 180; const pushStrength = 7; const smoothness = 0.045;

Например, для совсем ленивой, раздражающей кнопки:

javascript
const escapeRadius = 150; const pushStrength = 4; const smoothness = 0.025;

Она будет такая: «ладно-ладно, я ухожу…» и очень медленно отплывать от курсора. 😄

Frage

Можешь просто по братски соединить чтобы было всё ок и плавное "уплывание" кнопки выхода вокруг курсора и эффект фокуса

Gedanke

Worked for 8s

Antwort

Да 😄 Вот уже цельный вариант, чтобы ничего не собирать по кусочкам: Esc открывает меню, игра плавно расфокусируется, а кнопка выхода мягко уплывает от курсора, без телепортаций.

Story → JavaScript

javascript
(function () { /* ========================= СОЗДАЁМ МЕНЮ ВЫХОДА ========================= */ const overlay = document.createElement("div"); overlay.id = "exit-overlay"; const title = document.createElement("div"); title.id = "exit-title"; title.textContent = "Точно хочешь выйти?"; const button = document.createElement("button"); button.id = "exit-button"; button.textContent = "Выйти из игры"; overlay.appendChild(title); overlay.appendChild(button); document.body.appendChild(overlay); /* ========================= НАСТРОЙКИ ДВИЖЕНИЯ ========================= */ // Насколько далеко кнопка "чувствует" курсор const escapeRadius = 190; // Сила отталкивания const pushStrength = 1.8; // Плавность движения // меньше = медленнее и плавнее const smoothness = 0.075; // Отступ от краёв экрана const screenPadding = 30; let buttonX = 0; let buttonY = 0; let targetX = 0; let targetY = 0; let mouseX = -1000; let mouseY = -1000; let menuOpen = false; /* ========================= НАЧАЛЬНАЯ ПОЗИЦИЯ ========================= */ function resetButtonPosition() { buttonX = window.innerWidth / 2 - button.offsetWidth / 2; buttonY = window.innerHeight * 0.57; targetX = buttonX; targetY = buttonY; button.style.left = buttonX + "px"; button.style.top = buttonY + "px"; } /* ========================= ОТКРЫТИЕ / ЗАКРЫТИЕ ========================= */ function showExitMenu() { menuOpen = true; overlay.classList.add("active"); requestAnimationFrame(function () { resetButtonPosition(); }); } function hideExitMenu() { menuOpen = false; overlay.classList.remove("active"); // Чтобы при следующем открытии // старая позиция мыши не пугала кнопку mouseX = -1000; mouseY = -1000; } /* ESC открывает и закрывает меню */ document.addEventListener("keydown", function (event) { if (event.key === "Escape") { event.preventDefault(); if (menuOpen) { hideExitMenu(); } else { showExitMenu(); } } }); /* ========================= СЛЕДИМ ЗА КУРСОРОМ ========================= */ document.addEventListener("mousemove", function (event) { mouseX = event.clientX; mouseY = event.clientY; }); /* ========================= ПЛАВНОЕ "УПЛЫВАНИЕ" ========================= */ function animate() { if (menuOpen) { const centerX = buttonX + button.offsetWidth / 2; const centerY = buttonY + button.offsetHeight / 2; /* Расстояние между курсором и кнопкой */ const dx = centerX - mouseX; const dy = centerY - mouseY; const distance = Math.hypot(dx, dy); /* * Если курсор входит в невидимый круг * вокруг кнопки — она начинает отплывать. */ if (distance < escapeRadius) { const safeDistance = Math.max(distance, 1); const directionX = dx / safeDistance; const directionY = dy / safeDistance; /* * Чем курсор ближе, * тем сильнее отталкивание. */ const force = 1 - distance / escapeRadius; targetX += directionX * pushStrength * force * 12; targetY += directionY * pushStrength * force * 12; } /* ========================= НЕ ДАЁМ УПЛЫТЬ ЗА ЭКРАН ========================= */ const maxX = window.innerWidth - button.offsetWidth - screenPadding; const maxY = window.innerHeight - button.offsetHeight - screenPadding; targetX = Math.max( screenPadding, Math.min(targetX, maxX) ); targetY = Math.max( screenPadding, Math.min(targetY, maxY) ); /* ========================= ПЛАВНО ДОГОНЯЕМ ЦЕЛЬ ========================= */ buttonX += (targetX - buttonX) * smoothness; buttonY += (targetY - buttonY) * smoothness; button.style.left = buttonX + "px"; button.style.top = buttonY + "px"; } requestAnimationFrame(animate); } animate(); /* ========================= ИЗМЕНЕНИЕ РАЗМЕРА ОКНА ========================= */ window.addEventListener("resize", function () { if (menuOpen) { resetButtonPosition(); } }); /* ========================= НАЖАТИЕ НА КНОПКУ ========================= */ button.addEventListener("click", function () { window.close(); /* * Браузер обычно не разрешает сайту * самостоятельно закрывать обычную вкладку. * Поэтому делаем запасной экран. */ setTimeout(function () { document.body.innerHTML = ` <div class="game-over-screen"> <h1>Игра закрыта.</h1> <p>Ну почти.</p> </div> `; }, 150); }); })();

Story → Stylesheet

css
/* ========================= ЭФФЕКТ ФОКУСА ========================= */ #exit-overlay { position: fixed; inset: 0; z-index: 999999; /* * Практически прозрачный фон. * Затемнения нет. */ background: rgba(255, 255, 255, 0.01); /* * Игра сзади становится * расфокусированной. */ backdrop-filter: blur(9px) saturate(0.75); -webkit-backdrop-filter: blur(9px) saturate(0.75); opacity: 0; visibility: hidden; pointer-events: none; transition: opacity 0.35s ease, visibility 0.35s ease; } #exit-overlay.active { opacity: 1; visibility: visible; pointer-events: auto; } /* ========================= ЗАГОЛОВОК ========================= */ #exit-title { position: fixed; top: 25%; left: 50%; transform: translateX(-50%); color: white; font-size: 1.8em; font-weight: bold; text-align: center; text-shadow: 0 2px 6px rgba(0, 0, 0, 0.45), 0 0 20px rgba(255, 255, 255, 0.15); pointer-events: none; user-select: none; } /* ========================= КНОПКА ВЫХОДА ========================= */ #exit-button { position: fixed; padding: 15px 26px; color: black; background: #f4d6e8; border: 2px solid #d99bc1; border-radius: 14px; font-family: inherit; font-size: 1em; font-weight: 600; cursor: pointer; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25); /* * left/top здесь специально * НЕ анимируем через CSS. * * Плавность делает JavaScript, * поэтому движение получается * гораздо естественнее. */ transition: background 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease; } #exit-button:hover { color: black; background: #f8c5df; box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3); transform: scale(1.03); } #exit-button:active { transform: scale(0.97); } /* ========================= ЭКРАН "ВЫХОДА" ========================= */ .game-over-screen { position: fixed; inset: 0; display: flex; flex-direction: column; justify-content: center; align-items: center; background: #30263d; color: #f7eafa; font-family: inherit; text-align: center; } .game-over-screen h1 { margin-bottom: 5px; } .game-over-screen p { opacity: 0.65; }

Главное здесь — кнопка теперь вообще не прыгает. У курсора есть невидимая зона примерно 190px, и когда он приближается, кнопка начинает как будто физически от него отплывать.

Если хочется ещё более ленивое и издевательское движение, поменяй только:

javascript
const escapeRadius = 210; const pushStrength = 1.3; const smoothness = 0.045;

Тогда она будет буквально медленно ускользать из-под мышки, а не панически убегать.

Frage

Оформи пж по братски формы для параграфов

Gedanke

Worked for 4s

Antwort

Конечно 😄 Я бы сделал параграфы не просто цветными прямоугольниками, а с разными мягкими формами, чтобы текст выглядел как элементы визуальной новеллы.

Попробуй такой вариант в Story → Stylesheet:

css
/* ========================= ОБЩИЙ СТИЛЬ ПАРАГРАФОВ ========================= */ tw-passage p { position: relative; margin: 18px 0; padding: 16px 20px; color: #2b2530; background: #f4d6e8; border: 2px solid rgba(255, 255, 255, 0.35); line-height: 1.65; box-shadow: 0 6px 18px rgba(0, 0, 0, 0.14); transition: transform 0.25s ease, box-shadow 0.25s ease; } /* ========================= 1 — МЯГКАЯ КАРТОЧКА ========================= */ tw-passage p:nth-of-type(4n + 1) { background: #f4d6e8; border-radius: 22px 8px 22px 8px; } /* ========================= 2 — СРЕЗАННЫЕ УГЛЫ ========================= */ tw-passage p:nth-of-type(4n + 2) { background: #d9e4ff; border-radius: 8px; clip-path: polygon( 14px 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, 0 100%, 0 14px ); } /* ========================= 3 — ПОЛУКРУГЛАЯ ФОРМА ========================= */ tw-passage p:nth-of-type(4n + 3) { background: #d5eee4; border-radius: 26px 26px 8px 26px; } /* ========================= 4 — ДИАЛОГОВАЯ КАРТОЧКА ========================= */ tw-passage p:nth-of-type(4n + 4) { background: #f4e4bd; border-radius: 12px 24px 24px 24px; } /* ========================= ЛЁГКИЙ ЭФФЕКТ НАВЕДЕНИЯ ========================= */ tw-passage p:hover { transform: translateY(-2px) scale(1.005); box-shadow: 0 9px 24px rgba(0, 0, 0, 0.18); }

Мне особенно нравится форма с асимметричными скруглениями:

css
border-radius: 22px 8px 22px 8px;

Она сразу убирает ощущение обычного HTML-блока.

Можно ещё добавить слева маленькую декоративную метку:

css
tw-passage p::before { content: ""; position: absolute; left: -5px; top: 18px; width: 8px; height: 28px; background: rgba(255, 255, 255, 0.8); border-radius: 20px; }

А если хочешь именно диалоговые облачка, можно сделать хвостик:

css
tw-passage p.dialogue { border-radius: 20px; } tw-passage p.dialogue::after { content: ""; position: absolute; left: 25px; bottom: -10px; width: 20px; height: 20px; background: inherit; transform: rotate(45deg); border-radius: 3px; }

Тогда визуально получится что-то вроде:

text
╭──────────────────────────────╮ │ — Ты уверен, что нам сюда? │ │ │ │ Кажется, это плохая идея. │ ╰───────◇──────────────────────╯

Для твоего тёмного #30263d я бы оставил пастельные карточки + необычную форму + небольшую тень — это будет гораздо приятнее, чем куча ярких цветов без структуры.

Diesen Q&A teilen