Оттиск штампа при загрузке и при успехе формы, заполнение ленты недели по IntersectionObserver, мигающие точки при отправке. Только CSS и transform/opacity; анимации включает скрипт в head, поэтому без JS и при prefers-reduced-motion всё сразу в финале. Липкая CTA на мобиле: «Заказать кофе», прячется у формы, при фокусе в ней и при открытой клавиатуре. Ритм секций плотнее.
589 lines
13 KiB
CSS
589 lines
13 KiB
CSS
@import 'tailwindcss';
|
|
|
|
/* Токены — DESIGN.md. Палитра Tailwind отключена: только цвета «Кварты». */
|
|
@theme {
|
|
--color-*: initial;
|
|
--color-cream: #f3ebdd;
|
|
--color-paper: #fbf7f0;
|
|
--color-kraft: #dcc7a1;
|
|
--color-roast: #1e120c;
|
|
--color-ink: #2a1810;
|
|
--color-muted: #5e4636;
|
|
--color-placeholder: #7a6352;
|
|
--color-rule-soft: #c9b595;
|
|
--color-cherry: #b3221b;
|
|
--color-cherry-deep: #8f1a14;
|
|
--color-cherry-on-dark: #e8604f;
|
|
--color-muted-on-dark: #bfa88a;
|
|
--color-ok: #2e5e3a;
|
|
--color-transparent: transparent;
|
|
--color-current: currentColor;
|
|
|
|
--radius-*: initial;
|
|
--radius-none: 0px;
|
|
--radius-hair: 2px;
|
|
--shadow-*: initial;
|
|
|
|
--text-display: clamp(2.75rem, 1.6rem + 5.2vw, 6rem);
|
|
--text-display--line-height: 0.92;
|
|
--text-display--letter-spacing: -0.035em;
|
|
--text-headline: clamp(2rem, 1.4rem + 2.8vw, 3.5rem);
|
|
--text-headline--line-height: 1;
|
|
--text-headline--letter-spacing: -0.03em;
|
|
--text-title: clamp(1.5rem, 1.3rem + 0.6vw, 1.875rem);
|
|
--text-title--line-height: 1.05;
|
|
--text-title--letter-spacing: -0.02em;
|
|
--text-lead: clamp(1.125rem, 1rem + 0.5vw, 1.375rem);
|
|
--text-lead--line-height: 1.45;
|
|
--text-body: 1.0625rem;
|
|
--text-body--line-height: 1.55;
|
|
--text-small: 0.875rem;
|
|
--text-small--line-height: 1.45;
|
|
--text-ui: 0.9375rem;
|
|
--text-ui--line-height: 1.3;
|
|
--text-tag: 0.75rem;
|
|
--text-tag--line-height: 1.3;
|
|
--text-tag--letter-spacing: 0.08em;
|
|
--text-price: clamp(1.375rem, 1.2rem + 0.8vw, 2rem);
|
|
--text-price--line-height: 1;
|
|
--text-price--letter-spacing: -0.02em;
|
|
--text-date: clamp(1.75rem, 1.2rem + 2.2vw, 3.25rem);
|
|
--text-date--line-height: 1;
|
|
--text-date--letter-spacing: -0.04em;
|
|
|
|
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
|
|
--ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
|
|
--ease-in-quart: cubic-bezier(0.5, 0, 0.75, 0);
|
|
|
|
--container-page: 1280px;
|
|
}
|
|
|
|
@theme inline {
|
|
--font-sans: var(--font-golos), system-ui, sans-serif;
|
|
--font-mono: var(--font-martian), ui-monospace, monospace;
|
|
}
|
|
|
|
@layer base {
|
|
html {
|
|
background: var(--color-cream);
|
|
color: var(--color-ink);
|
|
scroll-padding-top: 16px;
|
|
-webkit-text-size-adjust: 100%;
|
|
}
|
|
body {
|
|
font-family: var(--font-sans);
|
|
font-size: var(--text-body);
|
|
line-height: 1.55;
|
|
background: var(--color-cream);
|
|
-webkit-tap-highlight-color: transparent;
|
|
font-synthesis: none;
|
|
}
|
|
::selection {
|
|
background: var(--color-cherry);
|
|
color: var(--color-paper);
|
|
}
|
|
:focus-visible {
|
|
outline: 2px solid var(--color-ink);
|
|
outline-offset: 3px;
|
|
}
|
|
.on-dark :focus-visible {
|
|
outline-color: var(--color-cream);
|
|
}
|
|
input,
|
|
textarea {
|
|
caret-color: var(--color-cherry);
|
|
}
|
|
a {
|
|
text-decoration-thickness: 1px;
|
|
text-underline-offset: 3px;
|
|
}
|
|
h1,
|
|
h2,
|
|
h3 {
|
|
text-wrap: balance;
|
|
}
|
|
p {
|
|
text-wrap: pretty;
|
|
}
|
|
}
|
|
|
|
@layer components {
|
|
/* моно-шрифт: ширина через wdth-ось Martian Mono */
|
|
.mono {
|
|
font-family: var(--font-mono);
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
.mono-narrow {
|
|
font-family: var(--font-mono);
|
|
font-stretch: 87.5%;
|
|
font-variation-settings: 'wdth' 87.5;
|
|
}
|
|
.tag {
|
|
font-family: var(--font-mono);
|
|
font-size: var(--text-tag);
|
|
line-height: 1.3;
|
|
letter-spacing: 0.08em;
|
|
font-weight: 500;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.page-x {
|
|
padding-inline: 20px;
|
|
}
|
|
@media (min-width: 1024px) {
|
|
.page-x {
|
|
padding-inline: 48px;
|
|
}
|
|
}
|
|
.container-page {
|
|
margin-inline: auto;
|
|
max-width: var(--container-page);
|
|
}
|
|
.section-y {
|
|
padding-block: 48px;
|
|
}
|
|
@media (min-width: 1024px) {
|
|
.section-y {
|
|
padding-block: 80px;
|
|
}
|
|
}
|
|
|
|
/* Кнопки */
|
|
.btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 10px;
|
|
min-height: 52px;
|
|
padding: 0 24px;
|
|
font-family: var(--font-sans);
|
|
font-size: 1rem;
|
|
font-weight: 700;
|
|
line-height: 1.2;
|
|
text-align: center;
|
|
border-radius: 0;
|
|
cursor: pointer;
|
|
user-select: none;
|
|
transition:
|
|
background-color 120ms ease-out,
|
|
color 120ms ease-out,
|
|
border-color 120ms ease-out,
|
|
transform 60ms linear;
|
|
}
|
|
.btn:active:not(:disabled) {
|
|
transform: translateY(1px);
|
|
}
|
|
.btn-primary {
|
|
background: var(--color-cherry);
|
|
color: var(--color-paper);
|
|
}
|
|
.btn-primary:active:not(:disabled) {
|
|
background: var(--color-cherry-deep);
|
|
}
|
|
.btn-secondary {
|
|
background: transparent;
|
|
color: var(--color-ink);
|
|
box-shadow: inset 0 0 0 1.5px var(--color-ink);
|
|
padding: 0 20px;
|
|
}
|
|
.btn-on-dark {
|
|
background: transparent;
|
|
color: var(--color-cream);
|
|
box-shadow: inset 0 0 0 1.5px var(--color-cream);
|
|
padding: 0 20px;
|
|
}
|
|
@media (hover: hover) {
|
|
.btn-primary:hover:not(:disabled) {
|
|
background: var(--color-cherry-deep);
|
|
}
|
|
.btn-secondary:hover:not(:disabled) {
|
|
background: var(--color-ink);
|
|
color: var(--color-cream);
|
|
}
|
|
.btn-on-dark:hover:not(:disabled) {
|
|
background: var(--color-cream);
|
|
color: var(--color-roast);
|
|
}
|
|
}
|
|
.btn:disabled:not([aria-busy]) {
|
|
background: var(--color-rule-soft);
|
|
color: var(--color-ink);
|
|
box-shadow: none;
|
|
cursor: not-allowed;
|
|
}
|
|
.btn[aria-busy='true'] {
|
|
cursor: progress;
|
|
}
|
|
.busy-dots {
|
|
display: inline-flex;
|
|
gap: 4px;
|
|
}
|
|
.busy-dots i {
|
|
width: 4px;
|
|
height: 4px;
|
|
background: currentColor;
|
|
}
|
|
|
|
/* Поля формы */
|
|
.field-label {
|
|
font-size: var(--text-ui);
|
|
font-weight: 600;
|
|
line-height: 1.3;
|
|
}
|
|
.field {
|
|
display: block;
|
|
width: 100%;
|
|
min-height: 52px;
|
|
padding: 12px 14px;
|
|
background: var(--color-paper);
|
|
color: var(--color-ink);
|
|
font-size: 1.0625rem;
|
|
line-height: 1.45;
|
|
border: 1.5px solid var(--color-muted);
|
|
border-radius: 0;
|
|
transition: border-color 120ms ease-out;
|
|
}
|
|
.field::placeholder {
|
|
color: var(--color-placeholder);
|
|
opacity: 1;
|
|
}
|
|
.field:focus {
|
|
border-color: var(--color-ink);
|
|
box-shadow: inset 0 0 0 0.5px var(--color-ink);
|
|
}
|
|
.field:focus-visible {
|
|
outline-offset: 2px;
|
|
}
|
|
.field[data-invalid] {
|
|
border-color: var(--color-cherry);
|
|
box-shadow: inset 0 0 0 0.5px var(--color-cherry);
|
|
}
|
|
textarea.field {
|
|
min-height: 112px;
|
|
resize: vertical;
|
|
}
|
|
.field-error {
|
|
display: flex;
|
|
gap: 6px;
|
|
align-items: flex-start;
|
|
font-size: var(--text-small);
|
|
font-weight: 500;
|
|
line-height: 1.45;
|
|
color: var(--color-cherry-deep);
|
|
}
|
|
.talon {
|
|
position: relative;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
min-height: 48px;
|
|
padding: 0 16px;
|
|
font-size: var(--text-ui);
|
|
font-weight: 600;
|
|
box-shadow: inset 0 0 0 1.5px var(--color-muted);
|
|
cursor: pointer;
|
|
transition:
|
|
background-color 120ms ease-out,
|
|
color 120ms ease-out;
|
|
}
|
|
.talon::before {
|
|
content: '';
|
|
width: 10px;
|
|
height: 10px;
|
|
flex: none;
|
|
box-shadow: inset 0 0 0 1.5px currentColor;
|
|
}
|
|
.talon[data-checked] {
|
|
background: var(--color-ink);
|
|
color: var(--color-cream);
|
|
box-shadow: inset 0 0 0 1.5px var(--color-ink);
|
|
}
|
|
.talon[data-checked]::before {
|
|
background: var(--color-cherry);
|
|
box-shadow: none;
|
|
}
|
|
.talon:has(:focus-visible) {
|
|
outline: 2px solid var(--color-ink);
|
|
outline-offset: 2px;
|
|
}
|
|
[data-invalid] .talon:not([data-checked]) {
|
|
box-shadow: inset 0 0 0 2px var(--color-cherry);
|
|
}
|
|
@media (hover: hover) {
|
|
.talon:not([data-checked]):hover {
|
|
background: var(--color-cream);
|
|
}
|
|
}
|
|
|
|
/* Этикетка: лента-наклейка, срезанная краем */
|
|
.ribbon {
|
|
position: absolute;
|
|
top: 34px;
|
|
right: -62px;
|
|
width: 220px;
|
|
padding: 6px 0;
|
|
background: var(--color-cherry);
|
|
color: var(--color-paper);
|
|
text-align: center;
|
|
transform: rotate(45deg);
|
|
pointer-events: none;
|
|
}
|
|
.perforation {
|
|
background-image: linear-gradient(to right, var(--color-ink) 0 6px, transparent 6px 10px);
|
|
background-size: 10px 1px;
|
|
background-repeat: repeat-x;
|
|
height: 1px;
|
|
}
|
|
}
|
|
|
|
/* Штамп */
|
|
@layer components {
|
|
.stamp {
|
|
display: inline-block;
|
|
transform: rotate(var(--stamp-rotate, -6deg));
|
|
opacity: 0.92;
|
|
}
|
|
.stamp-text {
|
|
font-family: var(--font-mono);
|
|
font-weight: 700;
|
|
font-stretch: 112.5%;
|
|
font-variation-settings: 'wdth' 112.5;
|
|
letter-spacing: 0.04em;
|
|
}
|
|
}
|
|
|
|
/* Лента недели: 390 — столбиком, ≥1024 — строкой */
|
|
@layer components {
|
|
.week-days {
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1fr) 128px;
|
|
column-gap: 12px;
|
|
}
|
|
.week-day {
|
|
grid-column: 1;
|
|
display: grid;
|
|
grid-template-columns: 64px minmax(0, 1fr);
|
|
column-gap: 12px;
|
|
align-items: center;
|
|
min-height: 60px;
|
|
padding-block: 10px;
|
|
position: relative;
|
|
}
|
|
.week-head {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 2px;
|
|
}
|
|
.week-letter {
|
|
font-size: 0.875rem;
|
|
font-weight: 800;
|
|
letter-spacing: 0.04em;
|
|
line-height: 1;
|
|
}
|
|
.week-date {
|
|
font-size: var(--text-date);
|
|
font-weight: 700;
|
|
line-height: 1;
|
|
letter-spacing: -0.04em;
|
|
}
|
|
.week-rule {
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
height: 1px;
|
|
background: var(--color-ink);
|
|
transform-origin: left;
|
|
}
|
|
.week-mark {
|
|
position: absolute;
|
|
left: 0;
|
|
width: 64px;
|
|
bottom: -1px;
|
|
height: 4px;
|
|
background: var(--color-cherry);
|
|
transform-origin: left;
|
|
}
|
|
.week-note {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 2px;
|
|
}
|
|
.week-bracket {
|
|
grid-column: 2;
|
|
grid-row: 5 / 8;
|
|
display: flex;
|
|
gap: 10px;
|
|
padding-block: 12px;
|
|
}
|
|
.week-bracket-line {
|
|
flex: none;
|
|
width: 8px;
|
|
border: 2px solid var(--color-cherry);
|
|
border-left: 0;
|
|
transform-origin: top;
|
|
}
|
|
.week-bracket-note {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
align-self: center;
|
|
}
|
|
|
|
@media (min-width: 1024px) {
|
|
.week-days {
|
|
grid-template-columns: repeat(7, minmax(0, 1fr));
|
|
column-gap: 0;
|
|
}
|
|
.week-day {
|
|
grid-column: auto;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
padding: 0;
|
|
min-height: 0;
|
|
}
|
|
.week-head {
|
|
position: relative;
|
|
gap: 10px;
|
|
padding: 0 16px 20px;
|
|
border-left: 1px solid var(--color-rule-soft);
|
|
}
|
|
.week-day:first-child .week-head {
|
|
border-left: 0;
|
|
padding-left: 0;
|
|
}
|
|
.week-letter {
|
|
font-size: 1rem;
|
|
}
|
|
.week-mark {
|
|
left: 16px;
|
|
right: 16px;
|
|
width: auto;
|
|
}
|
|
.week-note {
|
|
padding: 16px 16px 0;
|
|
}
|
|
.week-bracket {
|
|
grid-column: 5 / 8;
|
|
grid-row: 2;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
padding: 28px 16px 0;
|
|
}
|
|
.week-bracket-line {
|
|
width: auto;
|
|
height: 10px;
|
|
border: 2px solid var(--color-cherry);
|
|
border-top: 0;
|
|
transform-origin: left;
|
|
}
|
|
.week-bracket-note {
|
|
align-self: auto;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Моушн (DESIGN.md → «Моушн»). Без JS и при reduced-motion — сразу финальное состояние. */
|
|
@keyframes stamp-in {
|
|
from {
|
|
opacity: 0;
|
|
transform: rotate(calc(var(--stamp-rotate, -6deg) - 3deg)) scale(1.18);
|
|
}
|
|
to {
|
|
opacity: 0.92;
|
|
transform: rotate(var(--stamp-rotate, -6deg)) scale(1);
|
|
}
|
|
}
|
|
@keyframes busy-dot {
|
|
0%,
|
|
100% {
|
|
opacity: 0.3;
|
|
}
|
|
33% {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
@keyframes fade-in {
|
|
from {
|
|
opacity: 0;
|
|
}
|
|
}
|
|
|
|
@media (prefers-reduced-motion: no-preference) {
|
|
[data-motion] .stamp[data-stamp='load'] {
|
|
animation: stamp-in 380ms var(--ease-out-expo) 250ms both;
|
|
}
|
|
.stamp[data-stamp='event'] {
|
|
animation: stamp-in 380ms var(--ease-out-expo) 80ms both;
|
|
}
|
|
.busy-dots i {
|
|
animation: busy-dot 480ms steps(1) infinite;
|
|
}
|
|
.busy-dots i:nth-child(2) {
|
|
animation-delay: 160ms;
|
|
}
|
|
.busy-dots i:nth-child(3) {
|
|
animation-delay: 320ms;
|
|
}
|
|
[data-lead-notice] > * {
|
|
animation: fade-in 160ms ease-out;
|
|
}
|
|
|
|
/* лента недели */
|
|
[data-motion] .week .week-rule {
|
|
transition: transform 600ms var(--ease-out-quart);
|
|
}
|
|
[data-motion] .week .week-mark {
|
|
transition: transform 320ms var(--ease-out-quart) 300ms;
|
|
}
|
|
[data-motion] .week .week-note {
|
|
transition:
|
|
opacity 320ms var(--ease-out-quart) 300ms,
|
|
transform 320ms var(--ease-out-quart) 300ms;
|
|
}
|
|
[data-motion] .week .week-day:nth-child(5) .week-mark,
|
|
[data-motion] .week .week-day:nth-child(5) .week-note {
|
|
transition-delay: 480ms;
|
|
}
|
|
[data-motion] .week .week-bracket-line {
|
|
transition: transform 500ms var(--ease-out-quart) 680ms;
|
|
}
|
|
[data-motion] .week .week-bracket-note {
|
|
transition: opacity 240ms ease-out 1000ms;
|
|
}
|
|
[data-motion] .week:not([data-inview]) .week-rule,
|
|
[data-motion] .week:not([data-inview]) .week-mark {
|
|
transform: scaleX(0);
|
|
}
|
|
[data-motion] .week:not([data-inview]) .week-note {
|
|
opacity: 0;
|
|
transform: translateY(6px);
|
|
}
|
|
[data-motion] .week:not([data-inview]) .week-bracket-line {
|
|
transform: scaleY(0);
|
|
}
|
|
[data-motion] .week:not([data-inview]) .week-bracket-note {
|
|
opacity: 0;
|
|
}
|
|
@media (min-width: 1024px) {
|
|
[data-motion] .week:not([data-inview]) .week-bracket-line {
|
|
transform: scaleX(0);
|
|
}
|
|
}
|
|
|
|
/* липкая CTA */
|
|
.sticky-cta {
|
|
transition: transform 180ms var(--ease-in-quart);
|
|
}
|
|
.sticky-cta[data-visible] {
|
|
transition: transform 240ms var(--ease-out-quart);
|
|
}
|
|
}
|
|
|
|
.sticky-cta:not([data-visible]) {
|
|
transform: translateY(100%);
|
|
visibility: hidden;
|
|
transition-property: transform, visibility;
|
|
}
|