/* Оформлення сторінки портфоліо. Правити не обов'язково — але якщо хочете свої кольори, міняйте змінні в :root нижче. */ :root { --ink: #1f2a33; --ink-soft: #56646f; --accent: #003964; --line: #e0e6ea; --bg: #ffffff; --bg-soft: #fbfcfd; --warn: #f15b43; --bleed: 0rem; } /* Пороги рахуються так: розкладка впирається в 66rem, тож блок виступає за неї безпечно, поки ширина вікна ≥ 1008px + 2 × виступ. */ @media (min-width: 1200px) { :root { --bleed: 5rem; } } @media (min-width: 1400px) { :root { --bleed: 9rem; } } * { box-sizing: border-box; } html { -webkit-text-size-adjust: 100%; } body { margin: 0; background: var(--bg); color: var(--ink); font: 17px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; } /* ── розкладка: бічна панель + вміст ───────────────────────────── */ .layout { display: grid; grid-template-columns: 15rem minmax(0, 1fr); gap: 2rem; max-width: 66rem; margin: 0 auto; padding: 0 1.5rem; } .content { min-width: 0; } .side { min-width: 0; position: sticky; top: 0; align-self: start; max-height: 100vh; overflow-y: auto; padding: 3.5rem 0 2rem; } .side-name { display: block; font-size: 1.15rem; font-weight: 650; line-height: 1.25; color: var(--accent); text-decoration: none; } .side-role { margin: 0.3rem 0 1.6rem; font-size: 0.85rem; color: var(--ink-soft); } .side-nav a { display: block; padding: 0.4rem 0; font-size: 0.95rem; color: var(--ink-soft); text-decoration: none; border-left: 2px solid transparent; padding-left: 0.8rem; margin-left: -0.8rem; } .side-nav a:hover { color: var(--accent); } .side-nav a.here { color: var(--accent); font-weight: 600; border-left-color: var(--accent); } .side-works { margin-top: 1.2rem; } /* Рамка-роздільник потрібна тільки тоді, коли вище є список сторінок. */ .side-nav + .side-works { padding-top: 1.2rem; border-top: 1px solid var(--line); } .side-works a { display: block; padding: 0.35rem 0 0.35rem 0.8rem; margin-left: -0.8rem; font-size: 0.85rem; line-height: 1.35; color: var(--ink-soft); text-decoration: none; border-left: 2px solid transparent; } .side-works a:hover { color: var(--accent); } .side-works a.here { color: var(--accent); border-left-color: var(--accent); } /* ── шапка ─────────────────────────────────────────────────────── */ .page-head { padding: 3.5rem 0 2.5rem; border-bottom: 1px solid var(--line); } .page-head h1 { margin: 0; font-size: 2.4rem; line-height: 1.15; letter-spacing: -0.02em; color: var(--accent); } .tagline { margin: 0.6rem 0 0; color: var(--ink-soft); font-size: 1.05rem; } /* ── роботи ────────────────────────────────────────────────────── */ main { padding: 0; } .work { scroll-margin-top: 1.5rem; padding: 2rem 0; border-bottom: 1px solid var(--line); } .work:last-of-type { border-bottom: 0; } /* Заголовок роботи — він же кнопка «згорнути». */ .work > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 0.6rem; padding: 0.3rem 0; user-select: none; } .work > summary::-webkit-details-marker { display: none; } .work > summary::before { content: ""; flex: 0 0 auto; width: 0.5rem; height: 0.5rem; border-right: 2px solid var(--ink-soft); border-bottom: 2px solid var(--ink-soft); transform: rotate(-45deg); transition: transform 0.15s; } .work[open] > summary::before { transform: rotate(45deg); } .work > summary:hover::before { border-color: var(--accent); } .work-title { font-size: 1.4rem; font-weight: 650; line-height: 1.25; color: var(--accent); } .work-body { padding-top: 0.6rem; } /* Кнопка «згорнути всі» в бічній панелі. */ .side-fold { margin-top: 1.2rem; padding: 0; border: 0; background: none; font: inherit; font-size: 0.8rem; color: var(--ink-soft); cursor: pointer; text-align: left; } .side-fold:hover { color: var(--accent); } /* Міру тримає текст, а не блок: рядок довший за 34rem читати важче. Графік, поставлений у тексті роботи, цієї межі не має — він займає всю ширину колонки. */ .note { margin: 0 0 1.4rem; color: var(--ink-soft); } .note > p, .note > ul, .note > ol, .note > blockquote, .note > h2, .note > h3, .note > h4, .note > table { max-width: 34rem; } .note b, .note strong { color: var(--ink); font-weight: 600; } .note p { margin: 0 0 0.7rem; } .note p:last-child { margin-bottom: 0; } .note + .note { margin-top: 1.2rem; } /* Рядок «це приклад» — видимий, але не на місці опису роботи. */ .note.swap { max-width: 34rem; margin-top: -0.9rem; padding-left: 0.8rem; border-left: 2px solid var(--line); font-size: 0.85rem; } /* Позначка прикладу. Приберете приклад — приберете і її. */ .tag { display: inline-block; padding: 0.15em 0.5em; border: 1px solid var(--line); border-radius: 999px; background: var(--bg); font-size: 0.6em; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-soft); vertical-align: middle; } /* Контейнер графіка. Широкий графік прокручується всередині себе, а не розтягує сторінку. */ .viz { max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; } /* Робота на всю ширину:
. Дашборди Tableau ширші за текстову колонку, і в ній їх обрізає. */ /* Ширший блок для дашбордів: вилазить за колонку тексту рівно на --bleed з кожного боку. Класичний трюк «на всю ширину вікна» тут не працює: колонка стоїть праворуч від панелі, тобто не по центру вікна, і центрування зсуває блок за правий край. */ .work.wide .note > .chart, .work.wide .note > .chart-row, .chart.wide { /* Виступ тільки вправо. Ліворуч стоїть липка бічна панель, і симетричний виступ наїжджав би на неї. */ width: calc(100% + var(--bleed)); max-width: none; /* інакше .viz{max-width:100%} тримає в колонці */ } @media (max-width: 720px) { .work.wide .note > .chart, .work.wide .note > .chart-row, .chart.wide { width: 100%; } } /* vega-embed робить свій контейнер inline-block, і той обгортається під ширину графіка, вилазячи з колонки. Повертаємо блок. */ .viz.vega-embed { display: block; } /* ── графік, поставлений у тексті роботи ───────────────────────── */ /* Рядок ![Підпис](specs/файл.json) браузер спершу читає як картинку. Ховаємо її, поки embed.js не поставив на це місце графік: інакше на секунду блимає значок «зображення не завантажилось». Так само з блоком ```vega-lite```: це специфікація, а не текст для читача. */ main img[src$=".json"], main img[src*="public.tableau.com"], main [class*="language-vega-lite"] { display: none; } main pre:has(> code[class*="language-vega-lite"]) { display: none; } .chart { margin: 0 0 1.4rem; } .chart .viz { width: 100%; } /* Скріншот, поставлений у тексті роботи, як звичайна картинка. */ .note img { display: block; max-width: 100%; height: auto; border: 1px solid var(--line); border-radius: 8px; } .chart figcaption { margin: 0.5rem 0 0; font-size: 0.85rem; color: var(--ink-soft); } /* Два графіки в одному ряду. Ставте їх поруч тоді, коли читач має їх порівняти: око порівнює те, що бачить разом. На вузькому екрані ряд розпадається на два графіки один під одним. */ .chart-row { display: flex; gap: 1.4rem; margin: 0 0 1.4rem; } /* Колонка з підписом унизу: графіки в ряду різної висоти, а підписи мають стояти на одному рівні. */ .chart-row .chart { display: flex; flex-direction: column; flex: 1 1 0; min-width: 0; margin: 0; } .chart-row .chart figcaption { margin-top: auto; padding-top: 0.5rem; } @media (max-width: 720px) { .chart-row { display: block; } .chart-row .chart { margin: 0 0 1.4rem; } .chart-row .chart:last-child { margin-bottom: 0; } } .viz-frame { display: block; width: 100%; min-height: 400px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg-soft); } .viz-link { margin: 0.6rem 0 0; font-size: 0.85rem; } .viz-link a { color: var(--ink-soft); } .viz-link a:hover { color: var(--accent); } /* ── підказки замість графіка ──────────────────────────────────── */ .viz-msg { padding: 2rem 1.5rem; border-radius: 8px; background: var(--bg-soft); font-size: 0.95rem; } .viz-msg b { display: block; color: var(--accent); margin-bottom: 0.35rem; } .viz-msg span { color: var(--ink-soft); } .viz-msg--warn { border: 1px solid var(--warn); border-left-width: 4px; } .viz-msg--warn b { color: var(--warn); } /* ── підвал ────────────────────────────────────────────────────── */ .page-foot { padding: 2.5rem 0 4rem; border-top: 1px solid var(--line); color: var(--ink-soft); font-size: 0.9rem; } .page-foot p { margin: 0; } @media (max-width: 720px) { /* minmax(0,…), не 1fr: інакше колонка розтягується під найширший вміст — вбудований графік — і сторінка їде вбік. */ .layout { grid-template-columns: minmax(0, 1fr); gap: 0; } .side { position: static; max-height: none; padding: 2rem 0 1rem; border-bottom: 1px solid var(--line); } .side-role { margin-bottom: 1rem; } .side-nav { display: flex; gap: 1.2rem; } .side-nav a { border-left: 0; padding-left: 0; margin-left: 0; } .side-nav a.here { border-bottom: 2px solid var(--accent); } .side-works { display: none; } .page-head { padding-top: 2rem; } .page-head h1 { font-size: 1.9rem; } .work { padding: 2rem 0; } }