Тема магазина по макету Figma

Каталог, карточка товара, корзина, оформление заказа и блог на WooCommerce.

Стили разложены по слоям: токены из Figma, база, компоненты, страницы,
брейкпоинты. Цвета, типографика, радиусы и отступы взяты из Variables и
текстовых стилей макета, ниже по слоям хардкода нет.

Иконки — Phosphor, вставляются инлайном как SVG, символами ничего не рисуется.
Стили WooCommerce отключены, вёрстка своя, !important не используется.
This commit is contained in:
f1den committed 2026-07-30 22:38:49 +03:00
commit 29d10ce4cf
72 files changed
+7465

No files matched your search

+186
View File
@@ -0,0 +1,186 @@
/*
* Base layer: font faces, reset, document defaults and the type scale.
* Only element selectors and utility classes live here.
*/
@font-face {
font-family: Inter;
src: url("../fonts/Inter.ttf") format("truetype");
font-style: normal;
font-weight: 100 900;
font-display: swap;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
[hidden] {
display: none;
}
html {
scroll-behavior: smooth;
scrollbar-width: none;
}
html::-webkit-scrollbar {
width: 0;
height: 0;
}
body {
display: flex;
min-height: 100vh;
min-height: 100dvh;
margin: 0;
flex-direction: column;
color: var(--text-main);
background: var(--bg-main);
font: var(--body-m);
-webkit-font-smoothing: antialiased;
}
body.menu-open {
overflow: hidden;
}
a {
color: inherit;
text-decoration: none;
}
img,
svg {
display: block;
max-width: 100%;
}
img {
height: auto;
}
button,
input,
select,
textarea {
color: inherit;
font: inherit;
}
button {
cursor: pointer;
}
/* ------------------------------------------------------------ type scale --- */
h1,
.h1 {
margin: 0;
font: var(--h1);
letter-spacing: var(--ls-tight);
}
h2,
.h2 {
margin: 0;
font: var(--h2);
letter-spacing: var(--ls-tight);
}
h3,
.h3 {
margin: 0;
font: var(--h3);
letter-spacing: var(--ls-tight);
}
h4,
.h4 {
margin: 0;
font: var(--h4);
letter-spacing: var(--ls-tight);
}
h5,
.h5 {
margin: 0;
font: var(--h5);
letter-spacing: var(--ls-tight-s);
}
.lead {
font: var(--lead);
}
.control-m {
font: var(--control-m);
}
.control-s {
font: var(--control-s);
}
.caption {
font: var(--caption);
}
.upper-l,
.upper-m,
.upper-s {
letter-spacing: var(--ls-upper);
text-transform: uppercase;
}
.upper-l {
font: var(--upper-l);
}
.upper-m {
font: var(--upper-m);
}
.upper-s {
font: var(--upper-s);
}
.accent-m {
font: var(--accent-m);
}
/* --------------------------------------------------------------- layout --- */
.container {
width: min(calc(100% - var(--container-gutter) * 2), var(--container));
margin-inline: auto;
}
.site-main {
display: block;
min-height: 0;
flex: 1 0 auto;
}
.screen-reader-text {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
border: 0;
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
transition-duration: 1ms !important;
animation-duration: 1ms !important;
scroll-behavior: auto !important;
}
}
+104
View File
@@ -0,0 +1,104 @@
/*
* Blog listing and article
*/
/* Blog and article */
.blog-page {
padding-bottom: 0;
}
.blog-page .page-heading {
margin-bottom: 24px;
}
.blog-page-spacer {
height: 64px;
}
.article-layout {
padding-bottom: 48px;
}
.article-layout .page-heading {
margin-bottom: 24px;
font: var(--h2);
letter-spacing: var(--ls-tight);
}
.article-prose {
width: 752px;
max-width: 100%;
}
.article-lead {
margin: 0 0 48px;
font: var(--lead);
}
.article-media,
.article-media-wide,
.prose .article-media {
display: block;
width: 1088px;
max-width: 100%;
height: 620px;
min-height: 0;
margin: 0;
border-radius: 0;
background: var(--border-secondary);
object-fit: cover;
}
.article-caption {
width: 1088px;
max-width: 100%;
margin: 8px 0 24px;
color: var(--text-caption);
font: var(--caption);
}
.article-layout .prose h2 {
margin: 32px 0 8px;
font: var(--h3);
letter-spacing: var(--ls-tight);
}
.article-layout .prose h3 {
margin: 24px 0 8px;
font: var(--h4);
letter-spacing: var(--ls-tight);
}
.article-layout .prose p {
margin: 0 0 16px;
}
.article-layout .prose ol,
.article-layout .prose ul {
margin: 0 0 24px;
padding-left: 36px;
}
.article-layout .prose li {
margin-bottom: 16px;
padding-left: 4px;
}
.article-layout .prose ul {
padding-left: 36px;
list-style: none;
}
.article-layout .prose ul li {
position: relative;
}
.article-layout .prose ul li::before {
position: absolute;
top: 0.7em;
left: -28px;
width: 16px;
height: 2px;
background: currentColor;
content: "";
}
+742
View File
@@ -0,0 +1,742 @@
/*
* Cart and checkout
*/
/* Cart / checkout */
.cart-page {
min-height: 460px;
padding-top: 16px;
padding-bottom: 48px;
}
.cart-page .page-heading {
margin-bottom: 28px;
}
.checkout-page {
/* The design height is a floor, not a cap: validation messages under the
fields make the page taller, and a fixed height would let the content run
under the footer instead. */
min-height: 1068px;
padding-top: 16px;
padding-bottom: 48px;
}
.checkout-page .page-heading {
margin-bottom: 44px;
}
.cart-layout,
.checkout-layout {
display: grid;
align-items: start;
}
.cart-layout {
grid-template-columns: minmax(0, 1fr) 432px;
gap: 40px;
}
.checkout-layout {
grid-template-columns: minmax(0, 1fr) 436px;
gap: 24px;
}
.cart-items {
display: grid;
gap: 16px;
}
.cart-item {
display: grid;
min-height: 152px;
padding: 16px;
grid-template-columns: 160px minmax(0, 1fr) 104px 144px 48px;
align-items: center;
gap: 16px;
border-radius: 16px;
box-shadow: inset 0 0 0 1px var(--border-main);
}
.cart-item-copy {
display: flex;
min-width: 0;
flex-direction: column;
gap: 4px;
}
.cart-item-title {
color: var(--text-main);
font: var(--control-m);
}
.cart-item-sku {
color: var(--text-caption);
font: var(--control-s);
}
.cart-item-price {
text-align: right;
font: var(--h5);
letter-spacing: var(--ls-tight-s);
}
.cart-item-price del {
display: block;
color: var(--text-caption);
font: var(--control-s);
}
.cart-item-price ins {
text-decoration: none;
}
.cart-item-quantity {
height: 48px;
}
/* Holds an inline SVG, so it has to centre its own child — the icon used to
be an absolutely positioned span. */
.cart-item-remove {
display: grid;
width: 48px;
height: 48px;
place-items: center;
border-radius: var(--br-btn-m);
color: var(--text-main);
background: var(--bg-secondary);
}
.cart-item-remove:hover,
.cart-item-remove:focus-visible {
background: var(--bg-button-light-hover);
}
.cart-item-remove .icon {
--icon-size: 20px;
}
.cart-table {
width: 100%;
border-collapse: collapse;
}
.cart-table th,
.cart-table td {
padding: 16px 12px;
border-bottom: 1px solid var(--border-main);
text-align: left;
}
.cart-product {
display: flex;
align-items: center;
gap: 14px;
}
.cart-thumb {
position: relative;
width: 160px;
height: 120px;
flex: 0 0 auto;
overflow: hidden;
border-radius: 8px;
background: var(--bg-select-unit-selected);
}
.cart-thumb .product-badge {
position: absolute;
z-index: 1;
top: 8px;
left: 8px;
}
.cart-thumb img {
width: 100%;
height: 100%;
object-fit: cover;
}
.order-card {
align-self: start;
padding: 24px;
border-radius: 16px;
background: var(--bg-secondary);
}
.cart-order-card {
display: flex;
width: 432px;
max-width: 100%;
min-height: 272px;
flex-direction: column;
background: var(--bg-main);
box-shadow: 0 16px 48px rgb(0 0 0 / 10%);
}
.cart-order-card .order-row {
display: grid;
grid-template-columns: auto minmax(16px, 1fr) auto;
align-items: center;
column-gap: 8px;
}
.cart-order-card .order-row::after {
grid-column: 2;
grid-row: 1;
border-top: 1px dashed var(--border-secondary);
content: "";
}
.cart-order-card .order-row > :first-child {
grid-column: 1;
}
.cart-order-card .order-row > :last-child {
grid-column: 3;
text-align: right;
}
.woocommerce .cart-order-card .button {
height: 56px;
margin-top: auto;
min-height: 56px;
}
.cart-page.is-updating {
opacity: 0.7;
transition: opacity 100ms ease-in-out;
}
.order-card h3 {
margin: 0 0 20px;
font: var(--h5);
letter-spacing: var(--ls-tight-s);
}
.order-row {
display: flex;
min-height: 32px;
padding: 4px 0;
justify-content: space-between;
gap: 20px;
font: var(--control-m);
}
/* In the design only the amount jumps to Header #4; the "Итого" label stays
on Control M like every other summary row. */
.order-row.total {
min-height: 40px;
margin-top: 4px;
padding: 8px 0 0;
align-items: baseline;
}
.order-row.total strong {
font: var(--h4);
letter-spacing: var(--ls-tight);
}
.order-card .button,
.order-card #place_order {
width: 100%;
margin-top: 16px;
}
.checkout-fields {
display: flex;
width: 432px;
max-width: 100%;
flex-direction: column;
}
.checkout-input {
display: block;
width: 432px;
max-width: 100%;
/* Height comes from the input so the field can grow by its error message
instead of clipping it. */
margin-bottom: 8px;
}
/*
* Checkout fields follow the Figma text-field: h-input-L tall, br-control-L
* radius, the border-input state ladder, and a label that stays with the field
* instead of vanishing as soon as you type. Empty, it sits centred at
* Control M; filled or focused, it shrinks to Caption and moves to the top
* with the value underneath.
*/
.checkout-input input {
width: 100%;
height: var(--h-input-l);
padding: 33px 20px 15px;
border: 1px solid var(--border-input);
border-radius: var(--br-control-l);
outline: 0;
color: var(--text-main);
background: var(--bg-main);
font: var(--control-m);
transition: border-color var(--motion-fast);
}
.checkout-input input::placeholder {
color: var(--text-caption);
}
.checkout-input input:hover {
border-color: var(--border-input-hover);
}
.checkout-input input:focus {
border-color: var(--border-input-focus);
}
.checkout-input input:disabled {
border-color: transparent;
color: var(--text-disable);
background: var(--bg-control-disable);
}
.checkout-input input[aria-invalid="true"],
.woocommerce-invalid .checkout-input input {
border-color: var(--border-input-error);
}
.checkout-delivery,
.checkout-payment-options {
min-width: 0;
margin: 20px 0 0;
padding: 0;
border: 0;
}
.checkout-delivery legend,
.checkout-payment-options legend {
margin-bottom: 16px;
padding: 0;
font: var(--h5);
letter-spacing: var(--ls-tight-s);
}
.delivery-switch {
position: relative;
display: flex;
width: 256px;
max-width: 100%;
height: 56px;
margin-bottom: 8px;
padding: 4px;
border-radius: 10px;
background: var(--bg-secondary);
}
.delivery-switch::before {
position: absolute;
top: 4px;
left: 4px;
width: calc((100% - 8px) / 2);
height: 48px;
border-radius: 8px;
background: var(--bg-main);
box-shadow: 0 2px 8px rgb(0 0 0 / 6%);
content: "";
transition: transform 180ms ease-in-out;
}
.delivery-switch.is-delivery::before {
transform: translateX(100%);
}
.delivery-switch label {
position: relative;
z-index: 1;
flex: 1 1 0;
cursor: pointer;
}
.delivery-switch input {
position: absolute;
opacity: 0;
}
.delivery-switch span {
display: grid;
height: 48px;
place-items: center;
border-radius: 8px;
transition: color 180ms ease-in-out;
font: var(--control-m);
}
.delivery-switch input:checked + span {
background: transparent;
box-shadow: none;
}
.checkout-radio {
display: flex;
min-height: 32px;
align-items: center;
gap: 8px;
font: var(--control-m);
}
.checkout-map {
display: block;
width: 432px;
max-width: 100%;
height: 300px;
margin-top: 16px;
border-radius: 8px;
object-fit: cover;
}
.delivery-address-fields {
margin-top: 16px;
}
.checkout-payment-options {
margin-top: 24px;
}
.checkout-order-products {
display: grid;
gap: 8px;
margin-bottom: 16px;
}
.checkout-order-product {
display: grid;
min-height: 72px;
grid-template-columns: 56px 1fr;
align-items: center;
gap: 16px;
border-bottom: 1px solid var(--border-secondary);
}
.checkout-order-thumb {
width: 56px;
height: 56px;
overflow: hidden;
border-radius: 6px;
background: var(--bg-select-unit-selected);
}
.checkout-order-thumb img {
width: 100%;
height: 100%;
object-fit: cover;
}
.checkout-order-product strong,
.checkout-order-product > div > span {
display: block;
font: var(--control-s);
}
.checkout-order-product > div > span {
color: var(--text-caption);
}
.checkout-order-totals .order-row {
border-bottom: 1px dashed var(--border-secondary);
}
.checkout-order-totals .order-row.total {
border-bottom: 0;
}
.checkout-consent {
display: flex;
margin-top: 16px;
align-items: center;
gap: 8px;
color: var(--text-caption);
font: var(--control-s);
}
.woocommerce form .form-row {
margin: 0 0 14px;
}
.woocommerce form .form-row label {
display: block;
margin-bottom: 6px;
font: var(--control-s);
}
.woocommerce-checkout-review-order-table {
width: 100%;
border-collapse: collapse;
}
.woocommerce-checkout-review-order-table th,
.woocommerce-checkout-review-order-table td {
padding: 9px 0;
border-bottom: 1px solid var(--border-secondary);
text-align: left;
}
.woocommerce-checkout-payment {
margin-top: 18px;
}
.woocommerce-checkout-payment ul {
margin: 0;
padding: 0;
list-style: none;
}
/*
* Notices. WooCommerce's own stylesheets are dequeued (see inc/assets.php),
* so these rules win on their own and no longer need `!important`. The status
* mark is the matching Phosphor vector carried as a mask — never a glyph.
*/
.woocommerce-message,
.woocommerce-info,
.woocommerce-error,
.woocommerce-warning {
--notice-accent: var(--notice-info);
--notice-mark: var(--icon-info-fill);
position: relative;
display: flex;
width: min(100%, 447px);
min-height: 64px;
margin: 16px 0;
padding: 16px 56px 16px 64px;
align-items: center;
border: 0;
border-radius: var(--br-modal);
color: var(--text-main-contrast);
background: var(--notice-accent);
font: var(--control-m);
list-style: none;
transition:
opacity 180ms ease-in-out,
transform 180ms ease-in-out;
}
.woocommerce-message {
--notice-accent: var(--notice-success);
--notice-mark: var(--icon-check-circle-fill);
}
.woocommerce-error {
--notice-accent: var(--notice-error);
--notice-mark: var(--icon-x-circle-fill);
}
.woocommerce-warning {
--notice-accent: var(--notice-warning);
--notice-mark: var(--icon-warning-fill);
}
.woocommerce-message::before,
.woocommerce-info::before,
.woocommerce-error::before,
.woocommerce-warning::before {
position: absolute;
top: 50%;
left: 16px;
width: 32px;
height: 32px;
background: currentColor;
content: "";
transform: translateY(-50%);
-webkit-mask: var(--notice-mark) center / contain no-repeat;
mask: var(--notice-mark) center / contain no-repeat;
}
.woocommerce-error li {
margin: 0;
}
.woocommerce-notice-dismiss {
position: absolute;
top: 50%;
right: 16px;
width: 24px;
height: 24px;
padding: 0;
border: 0;
color: var(--text-main-contrast);
background: transparent;
transform: translateY(-50%);
}
.woocommerce-notice-dismiss::before {
position: absolute;
inset: 0;
background: currentColor;
content: "";
-webkit-mask: var(--icon-x) center / contain no-repeat;
mask: var(--icon-x) center / contain no-repeat;
}
.woocommerce-notice-dismiss:focus-visible {
outline: 2px solid var(--text-main-contrast);
outline-offset: 2px;
}
.woocommerce-notice-closing {
opacity: 0;
transform: translateY(-8px);
}
.wc-block-components-notice-banner > svg {
display: none;
}
.shop-toast-stack {
position: fixed;
z-index: 1000;
top: 104px;
right: 24px;
display: grid;
width: min(calc(100vw - 48px), 447px);
gap: 12px;
pointer-events: none;
}
.home .shop-toast-stack {
top: 136px;
}
.shop-toast {
--toast-fade-duration: 300ms;
position: relative;
display: grid;
width: 100%;
min-height: 64px;
padding: 16px 56px 16px 64px;
grid-template-columns: 1fr;
align-items: center;
border-radius: 16px;
color: var(--text-main-contrast);
background: var(--notice-info);
box-shadow: 0 12px 32px rgb(0 0 0 / 14%);
opacity: 0;
pointer-events: auto;
transition: opacity var(--toast-fade-duration) ease-in-out;
font: var(--control-m);
}
.shop-toast-success {
background: var(--notice-success);
}
.shop-toast-error {
background: var(--notice-error);
}
.shop-toast.is-visible {
opacity: 1;
}
.shop-toast.is-leaving {
opacity: 0;
}
.shop-toast-icon {
--icon-size: 32px;
position: absolute;
top: 50%;
left: 16px;
display: grid;
width: 32px;
height: 32px;
place-items: center;
color: currentColor;
transform: translateY(-50%);
}
.shop-toast-dismiss {
position: absolute;
top: 50%;
right: 16px;
display: grid;
width: 24px;
height: 24px;
padding: 0;
place-items: center;
border: 0;
color: var(--text-main-contrast);
background: transparent;
transform: translateY(-50%);
}
.shop-toast-dismiss .icon {
--icon-size: 20px;
}
.shop-toast-dismiss:focus-visible {
outline: 2px solid var(--text-main-contrast);
outline-offset: 2px;
}
.empty-state {
padding: 60px 0;
text-align: center;
}
.cart-page-empty .cart-empty-message {
margin: 0;
font: var(--control-m);
}
.checkout-input .field-label {
position: absolute;
/* Half of the field, not of the wrapper — the wrapper grows when an error
message appears underneath and would drag the label down with it. */
top: calc(var(--h-input-l) / 2);
left: 21px;
/* The .field component sets width: 100%; here the label only needs to be as
wide as its own text, or it reaches past the field. */
width: auto;
max-width: calc(100% - 42px);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: var(--text-caption);
font-family: var(--font-sans);
font-size: 16px;
line-height: 24px;
pointer-events: none;
transform: translateY(-50%);
transition:
top var(--motion-fast),
font-size var(--motion-fast),
line-height var(--motion-fast),
transform var(--motion-fast);
}
.checkout-input input:focus + .field-label,
.checkout-input input:not(:placeholder-shown) + .field-label {
top: 16px;
font-size: 12px;
line-height: 16px;
transform: none;
}
/* The real placeholder is a single space so :placeholder-shown works; it must
never be visible. */
.checkout-input input::placeholder {
color: transparent;
}
.checkout-input.is-error .field-label {
color: var(--text-negative);
}
/*
* The delivery switch sizes to its labels rather than trusting a fixed width,
* so a longer word cannot crowd the segments.
*/
.delivery-switch span {
padding: 0 20px;
white-space: nowrap;
}
+576
View File
@@ -0,0 +1,576 @@
/*
* Catalog and category archive: filters, toolbar, pagination
*/
/* Catalog / archive */
.archive-shell {
display: grid;
padding: 0 0 72px;
grid-template-columns: 288px minmax(0, 1fr);
align-items: start;
gap: 48px;
}
.filters {
align-self: start;
}
.filter-group {
padding: 15px 0;
}
.filter-group:first-child {
padding-top: 0;
}
.filter-title {
display: inline-flex;
margin-bottom: 10px;
align-items: center;
gap: 8px;
font: var(--h5);
letter-spacing: var(--ls-tight-s);
}
button.filter-title {
width: auto;
padding: 0;
border: 0;
background: transparent;
text-align: left;
}
.filter-caret {
flex: 0 0 auto;
transition: transform 180ms ease-in-out;
}
.filter-collapsed .filter-title {
margin: 0;
}
.filter-collapsed .filter-caret {
transform: rotate(180deg);
}
.filter-content {
overflow: hidden;
opacity: 1;
transition:
height 180ms ease-in-out,
opacity 120ms ease-in-out;
}
.filter-content.is-animating {
will-change: height, opacity;
}
.price-fields {
display: grid;
grid-template-columns: 1fr 14px 1fr;
align-items: center;
gap: 8px;
}
.price-fields > span {
color: var(--text-caption);
text-align: center;
}
.filter-input,
.filter-select,
.field input,
.field textarea,
.field select,
.woocommerce form .form-row input.input-text,
.woocommerce form .form-row textarea,
.woocommerce form .form-row select {
width: 100%;
min-height: 48px;
padding: 10px 12px;
border: 1px solid var(--border-main);
border-radius: 7px;
outline: 0;
background: var(--bg-main);
}
.filter-input {
min-height: 56px;
padding: 14px;
font: var(--control-m);
appearance: textfield;
}
.price-range {
position: relative;
height: 20px;
margin-top: 8px;
--range-min: 0%;
--range-max: 66.3%;
}
.price-range::before {
position: absolute;
top: 50%;
right: 0;
left: 0;
height: 2px;
background: var(--border-secondary);
content: "";
transform: translateY(-50%);
}
.price-range::after {
position: absolute;
top: 50%;
right: calc(100% - var(--range-max));
left: var(--range-min);
height: 2px;
background: var(--text-main);
content: "";
transform: translateY(-50%);
}
.price-range input[type="range"] {
position: absolute;
z-index: 2;
inset: 0;
width: 100%;
height: 20px;
margin: 0;
padding: 0;
border: 0;
outline: 0;
background: transparent;
pointer-events: none;
appearance: none;
}
.price-range input[type="range"]::-webkit-slider-runnable-track {
height: 2px;
background: transparent;
}
.price-range input[type="range"]::-webkit-slider-thumb {
width: 20px;
height: 20px;
margin-top: -9px;
border: 2px solid var(--text-main);
border-radius: 50%;
background: var(--bg-main);
cursor: grab;
pointer-events: auto;
appearance: none;
}
.price-range input[type="range"]::-moz-range-track {
height: 2px;
background: transparent;
}
.price-range input[type="range"]::-moz-range-thumb {
width: 16px;
height: 16px;
border: 2px solid var(--text-main);
border-radius: 50%;
background: var(--bg-main);
cursor: grab;
pointer-events: auto;
}
.price-range input[type="range"]:active::-webkit-slider-thumb {
cursor: grabbing;
}
.price-range input[type="range"]:focus-visible::-webkit-slider-thumb {
outline: 2px solid var(--text-link);
outline-offset: 2px;
}
.filter-option {
display: flex;
min-height: 32px;
align-items: center;
gap: 8px;
font: var(--control-m);
}
.filter-more {
display: inline-block;
margin-top: 5px;
padding: 0;
border: 0;
border-bottom: 1px dashed var(--border-link);
color: var(--text-link);
background: transparent;
transition:
color 100ms ease-in-out,
border-color 100ms ease-in-out;
font: var(--control-m);
}
.filter-more:hover,
.filter-more:focus-visible {
border-bottom-color: var(--text-link);
}
.filter-empty {
margin: 48px 0;
color: var(--text-caption);
text-align: center;
}
.archive-results {
min-width: 0;
}
.archive-toolbar {
display: flex;
min-height: 32px;
margin-bottom: 16px;
align-items: center;
justify-content: space-between;
gap: 20px;
color: var(--text-caption);
font: var(--control-m);
}
.sort-control,
.per-page-control {
display: flex;
align-items: center;
gap: 8px;
}
.archive-toolbar .woocommerce-ordering {
margin: 0;
}
.archive-toolbar select {
min-height: 32px;
padding: 4px 28px 4px 4px;
border: 0;
outline: 0;
color: var(--text-main);
background: transparent var(--icon-caret-down) right 4px center / 14px no-repeat;
font: var(--control-s);
appearance: none;
}
.custom-select {
position: relative;
display: inline-flex;
min-width: 0;
}
.custom-select-native {
position: absolute;
width: 1px;
height: 1px;
min-height: 0;
margin: -1px;
padding: 0;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
border: 0;
}
.custom-select-trigger {
display: inline-flex;
min-height: 24px;
padding: 0 32px 0 0;
align-items: center;
border: 0;
color: var(--text-main);
background: transparent;
text-align: left;
font: var(--control-m);
}
.custom-select-trigger::after {
position: absolute;
top: 50%;
right: 0;
width: 24px;
height: 24px;
background: currentColor;
content: "";
transform: translateY(-50%);
transition: transform 100ms ease-in-out;
-webkit-mask: var(--icon-caret-down) center / contain no-repeat;
mask: var(--icon-caret-down) center / contain no-repeat;
}
.custom-select.is-open .custom-select-trigger::after {
transform: translateY(-50%) rotate(180deg);
}
.custom-select-trigger:focus-visible {
outline: 2px solid var(--text-link);
outline-offset: 2px;
}
.custom-select-menu {
position: absolute;
z-index: 80;
top: calc(100% + 8px);
left: 0;
width: max-content;
min-width: 240px;
max-height: 336px;
overflow: auto;
border-radius: 8px;
background: var(--bg-main);
box-shadow: 0 10px 30px rgb(0 0 0 / 14%);
scrollbar-width: thin;
}
.per-page-control .custom-select-menu {
right: 0;
left: auto;
min-width: 160px;
}
.custom-select-option {
display: flex;
width: 100%;
min-height: 56px;
padding: 16px;
align-items: center;
border: 0;
border-bottom: 1px solid var(--border-main);
color: var(--text-main);
background: var(--bg-main);
text-align: left;
transition: background-color 100ms ease-in-out;
font: var(--control-m);
}
.custom-select-option:last-child {
border-bottom: 0;
}
.custom-select-option:hover,
.custom-select-option:focus-visible,
.custom-select-option.is-selected {
background: var(--bg-secondary);
}
.archive-results .product-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
row-gap: 24px;
}
.archive-results .product-card {
height: 405px;
}
.pagination,
.woocommerce nav.woocommerce-pagination ul {
display: flex;
margin: 24px 0 0;
padding: 0;
gap: 6px;
border: 0;
list-style: none;
}
.pagination .nav-links {
display: flex;
gap: 6px;
}
.pagination .page-numbers,
.woocommerce nav.woocommerce-pagination ul li a,
.woocommerce nav.woocommerce-pagination ul li span {
display: grid;
width: 56px;
height: 56px;
padding: 0;
place-items: center;
border: 1px solid var(--border-control);
border-radius: var(--br-btn-m);
background: var(--bg-main);
font: var(--control-m);
transition:
background-color 100ms ease-in-out,
border-color 100ms ease-in-out;
}
.woocommerce nav.woocommerce-pagination ul li {
border: 0;
}
.pagination .current,
.woocommerce nav.woocommerce-pagination ul li span.current {
color: var(--text-main);
background: var(--bg-secondary);
}
.pagination .icon-arrow-fill {
width: 24px;
height: 24px;
}
.pagination a.page-numbers:hover,
.pagination a.page-numbers:focus-visible,
.woocommerce nav.woocommerce-pagination ul li a:hover,
.woocommerce nav.woocommerce-pagination ul li a:focus-visible {
background: var(--bg-button-light-hover);
}
/* ------------------------------------------------- subcategory cards --- */
/*
* A scrollable row above the filters. Measured off `sub-categorys` in the
* Category block: 216x80 cards on bg-secondary, 16px gap, a 64px media square,
* and a circular next button overlapping the right edge.
*/
.subcategories {
position: relative;
margin-bottom: 24px;
}
.subcategory-list {
display: flex;
align-items: stretch;
margin: 0;
padding: 0;
gap: 16px;
overflow-x: auto;
scroll-behavior: smooth;
scrollbar-width: none;
list-style: none;
}
.subcategory-list::-webkit-scrollbar {
height: 0;
}
.subcategory-card {
display: flex;
width: 216px;
/* Fixed, not min: the design keeps the row even when a name wraps. */
height: 80px;
padding: 8px;
align-items: center;
gap: 12px;
border-radius: var(--br-section-m);
background: var(--bg-secondary);
transition: background-color var(--motion-fast);
}
.subcategory-card:hover {
background: var(--bg-button-light-hover);
}
.subcategory-card:active {
background: var(--bg-button-light-pressed);
}
.subcategory-card-media {
display: block;
width: 64px;
height: 64px;
flex: 0 0 64px;
overflow: hidden;
border-radius: var(--br-control-m);
background: var(--bg-select-unit-selected);
}
.subcategory-card-media img {
width: 100%;
height: 100%;
object-fit: cover;
}
.subcategory-card-copy {
display: flex;
min-width: 0;
flex-direction: column;
gap: 2px;
}
.subcategory-card-title {
display: -webkit-box;
overflow: hidden;
color: var(--text-main);
font: var(--control-m);
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.subcategory-card-count {
color: var(--text-caption);
font: var(--caption);
}
.subcategory-next {
position: absolute;
z-index: 2;
top: 50%;
right: 0;
display: grid;
width: 40px;
height: 40px;
padding: 0;
place-items: center;
border: 0;
border-radius: 50%;
color: var(--text-main);
background: var(--bg-main);
box-shadow: var(--shadow-m);
transform: translateY(-50%);
transition: background-color var(--motion-fast);
}
.subcategory-next:hover {
background: var(--bg-button-light-hover);
}
.subcategory-next[hidden] {
display: none;
}
/* --------------------------------------------------- quick filters --- */
/*
* The `quick-filters-tabs` row: pills that wrap, 36px tall, on the container
* edge rather than filled, and the active one inverts.
*/
.quick-filters {
display: flex;
margin-bottom: 16px;
flex-wrap: wrap;
gap: 8px;
}
.quick-filter {
padding: 6px 16px;
border: 1px solid var(--border-control);
border-radius: 999px;
color: var(--text-main);
background: var(--bg-main);
font: var(--control-m);
transition:
color var(--motion-fast),
border-color var(--motion-fast),
background-color var(--motion-fast);
}
.quick-filter:hover {
border-color: var(--border-control-hover);
background: var(--bg-button-light-hover);
}
.quick-filter.is-active {
border-color: transparent;
color: var(--text-main-contrast);
background: var(--bg-button);
}
.quick-filter:focus-visible {
outline: 2px solid var(--border-input-focus);
outline-offset: 2px;
}
+576
View File
@@ -0,0 +1,576 @@
/*
* Components.
*
* Every control here is built against the `Компоненты` matrices in Figma
* (DESKTOP + MOBILE, light theme) and uses tokens only. States follow the
* design's own vocabulary: default / hover / pressed / focus / error /
* disabled.
*/
/* ---------------------------------------------------------------- icon --- */
.icon {
display: inline-block;
width: var(--icon-size, 24px);
height: var(--icon-size, 24px);
flex: 0 0 auto;
color: inherit;
fill: currentColor;
vertical-align: middle;
}
.icon-20 {
--icon-size: 20px;
}
.icon-16 {
--icon-size: 16px;
}
/* Icons that read as "back" are the forward vector mirrored, never a
second asset. */
.icon-flip {
transform: scaleX(-1);
}
/* -------------------------------------------------------------- button --- */
.button {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: var(--pad-h-btn-m) var(--pad-w-text-m);
border: 1px solid transparent;
border-radius: var(--br-btn-m);
color: var(--text-main-contrast);
background: var(--bg-button);
font: var(--control-m);
text-align: center;
cursor: pointer;
transition:
color var(--motion-fast),
background-color var(--motion-fast),
border-color var(--motion-fast);
}
.button:hover {
background: var(--bg-button-hover);
}
.button:active {
background: var(--bg-button-pressed);
}
.button:disabled,
.button[aria-disabled="true"] {
color: var(--text-disable);
background: var(--bg-control-disable);
cursor: default;
}
/* Large button — the hero / checkout size. */
.button-l {
padding: var(--pad-h-btn-l) var(--pad-w-text-l);
border-radius: var(--br-btn-l);
}
/* An icon sitting next to the label tightens the padding on its side. */
.button:has(> .icon:first-child) {
padding-left: var(--pad-w-icon-m);
}
.button:has(> .icon:last-child) {
padding-right: var(--pad-w-icon-m);
}
.button-l:has(> .icon:first-child) {
padding-left: var(--pad-w-icon-l);
}
.button-l:has(> .icon:last-child) {
padding-right: var(--pad-w-icon-l);
}
/* Light (secondary) button. */
.button-light {
color: var(--text-main);
background: var(--bg-button-light);
}
.button-light:hover {
background: var(--bg-button-light-hover);
}
.button-light:active {
background: var(--bg-button-light-pressed);
}
/* Outline button — light fill with a visible edge. */
.button-outline {
color: var(--text-main);
border-color: var(--border-control);
background: var(--bg-main);
}
.button-outline:hover {
border-color: var(--border-control-hover);
background: var(--bg-button-light-hover);
}
.button-outline:active {
border-color: var(--border-control-pressed);
background: var(--bg-button-light-pressed);
}
/* Square icon-only control (cart, carousel arrows, favourite). */
.icon-button {
display: inline-grid;
width: 56px;
height: 56px;
padding: 0;
place-items: center;
border: 1px solid var(--border-control);
border-radius: var(--br-btn-m);
color: var(--text-main);
background: var(--bg-main);
cursor: pointer;
transition:
border-color var(--motion-fast),
background-color var(--motion-fast);
}
.icon-button:hover {
border-color: var(--border-control-hover);
background: var(--bg-button-light-hover);
}
.icon-button:active {
border-color: var(--border-control-pressed);
background: var(--bg-button-light-pressed);
}
.icon-button:disabled {
border-color: var(--border-control-disable);
color: var(--text-disable);
background: var(--bg-main);
cursor: default;
}
/* ---------------------------------------------------------- text link --- */
.text-link {
display: inline-flex;
align-items: center;
gap: 8px;
color: var(--text-link);
font: var(--control-m);
transition: color var(--motion-fast);
}
.text-link:hover {
color: var(--text-link-hover);
}
/* -------------------------------------------------- checkbox and radio --- */
/*
* Measured off the `radio-btn-icon` and `checkbox-icon` components: 20×20 box,
* 1px edge, 4px radius (`br-checkbox`), an 8px dot and a ~12px tick.
*
* The edge stays `border-checkbox` in every state, including checked — only
* the mark inside turns on. Turning the edge black as well is what made the
* radio read as a bullseye.
*
* Disabled fills with `bg-control-disable`, drops the edge, and dims the mark.
*/
.control-check {
display: inline-flex;
align-items: center;
gap: 12px;
font: var(--control-m);
cursor: pointer;
}
.control-check input[type="checkbox"],
.control-check input[type="radio"],
input[type="checkbox"],
input[type="radio"] {
position: relative;
width: 20px;
height: 20px;
margin: 0;
flex: 0 0 20px;
border: 1px solid var(--border-checkbox);
/* The mark is drawn in currentColor, so pin it here instead of inheriting
whatever colour the surrounding label happens to use. */
color: var(--text-main);
background: var(--bg-main);
cursor: pointer;
appearance: none;
transition:
border-color var(--motion-fast),
background-color var(--motion-fast);
}
input[type="checkbox"] {
border-radius: var(--br-checkbox);
}
input[type="radio"] {
border-radius: 50%;
}
input[type="checkbox"]:hover,
input[type="radio"]:hover {
border-color: var(--border-checkbox-hover);
}
/* The tick is the Phosphor `check-bold` vector, drawn as a mask so the mark
inherits `currentColor` and stays a vector at every zoom level. */
input[type="checkbox"]:checked::after {
position: absolute;
inset: 0;
background: currentColor;
content: "";
-webkit-mask: var(--icon-check) center / 12px 12px no-repeat;
mask: var(--icon-check) center / 12px 12px no-repeat;
}
input[type="radio"]:checked::after {
position: absolute;
top: 50%;
left: 50%;
width: 8px;
height: 8px;
border-radius: 50%;
background: currentColor;
content: "";
transform: translate(-50%, -50%);
}
input[type="checkbox"]:disabled,
input[type="radio"]:disabled {
border-color: transparent;
color: var(--text-disable);
background: var(--bg-control-disable);
cursor: default;
}
input[type="checkbox"]:focus-visible,
input[type="radio"]:focus-visible {
outline: 2px solid var(--border-input-focus);
outline-offset: 2px;
}
.control-check:has(input:disabled) {
color: var(--text-disable);
cursor: default;
}
/* ---------------------------------------------------------- text field --- */
/*
* Figma text field: 72px tall on desktop / 64px on mobile, 16px radius,
* the label sits inside the field above the value.
*/
.field {
display: flex;
flex-direction: column;
gap: 4px;
}
.field-control {
position: relative;
display: flex;
min-height: var(--h-input-l);
padding: 12px 20px;
align-items: center;
flex-direction: column;
justify-content: center;
gap: 2px;
border: 1px solid var(--border-input);
border-radius: var(--br-control-l);
background: var(--bg-main);
transition: border-color var(--motion-fast);
}
.field-control:hover {
border-color: var(--border-input-hover);
}
.field-control:focus-within {
border-color: var(--border-input-focus);
box-shadow: inset 0 0 0 1px var(--border-input-focus);
}
.field-label {
width: 100%;
color: var(--text-caption);
font: var(--caption);
}
.field-control input,
.field-control textarea,
.field-input {
width: 100%;
padding: 0;
border: 0;
outline: 0;
color: var(--text-main);
background: transparent;
font: var(--control-m);
}
.field-control input::placeholder,
.field-control textarea::placeholder {
color: var(--text-caption);
}
.field-control textarea {
min-height: calc(var(--h-text-area-l) - 48px);
resize: vertical;
}
.field-error-text,
.field-error {
color: var(--text-negative);
font: var(--caption);
}
/* The slot only takes space once it carries a message. */
.field-error:empty {
display: none;
}
.field.is-error .field-control {
border-color: var(--border-input-error);
box-shadow: inset 0 0 0 1px var(--border-input-error);
}
.field.is-disabled .field-control,
.field-control:has(input:disabled),
.field-control:has(textarea:disabled) {
border-color: transparent;
background: var(--bg-control-disable);
}
.field.is-disabled .field-label,
.field-control:has(input:disabled) .field-label,
.field-control:has(input:disabled) input {
color: var(--text-disable);
}
/* Compact single-line input used inside filters and the cart. */
.input-compact {
min-height: 48px;
padding: 12px 16px;
border: 1px solid var(--border-input);
border-radius: var(--br-control-m);
outline: 0;
color: var(--text-main);
background: var(--bg-main);
font: var(--control-m);
transition: border-color var(--motion-fast);
}
.input-compact:hover {
border-color: var(--border-input-hover);
}
.input-compact:focus {
border-color: var(--border-input-focus);
}
/* --------------------------------------------------------------- select --- */
.custom-select {
position: relative;
}
.custom-select-trigger {
display: flex;
width: 100%;
align-items: center;
justify-content: space-between;
gap: 8px;
padding: 0;
border: 0;
color: var(--text-main);
background: transparent;
font: var(--control-m);
cursor: pointer;
transition: color var(--motion-fast);
}
.custom-select-trigger .icon {
--icon-size: 20px;
transition: transform var(--motion-fast);
}
.custom-select.is-open .custom-select-trigger .icon {
transform: rotate(180deg);
}
.custom-select-menu {
position: absolute;
z-index: 20;
top: calc(100% + 8px);
right: 0;
min-width: 100%;
padding: 8px 0;
border: 1px solid var(--border-main);
border-radius: var(--br-control-m);
background: var(--bg-select-unit);
box-shadow: var(--shadow-m);
}
.custom-select-option {
display: block;
width: 100%;
padding: 10px 16px;
border: 0;
color: var(--text-main);
background: transparent;
font: var(--control-m);
text-align: left;
white-space: nowrap;
cursor: pointer;
transition: background-color var(--motion-fast);
}
.custom-select-option:hover {
background: var(--bg-select-unit-hover);
}
.custom-select-option[aria-selected="true"] {
background: var(--bg-select-unit-selected);
}
/* ----------------------------------------------------- quantity control --- */
.quantity-control {
display: grid;
min-height: 52px;
grid-template-columns: 40px minmax(0, 1fr) 40px;
align-items: center;
border-radius: var(--br-control-m);
background: var(--bg-secondary);
}
.quantity-control button {
display: grid;
height: 100%;
padding: 0;
place-items: center;
border: 0;
border-radius: inherit;
color: var(--text-main);
background: transparent;
cursor: pointer;
transition: background-color var(--motion-fast);
}
.quantity-control button .icon {
--icon-size: 20px;
}
.quantity-control button:hover {
background: var(--bg-button-light-hover);
}
.quantity-control button:active {
background: var(--bg-button-light-pressed);
}
.quantity-control button:disabled {
color: var(--text-disable);
cursor: default;
}
.quantity-control button:disabled:hover,
.quantity-control button:disabled:active {
background: transparent;
}
.quantity-control button:focus-visible {
z-index: 1;
outline: 2px solid var(--border-input-focus);
outline-offset: -2px;
}
.quantity-control input {
width: 100%;
padding: 0;
border: 0;
outline: 0;
background: transparent;
font: var(--control-m);
text-align: center;
appearance: textfield;
}
.quantity-control input::-webkit-outer-spin-button,
.quantity-control input::-webkit-inner-spin-button {
margin: 0;
appearance: none;
}
/* ------------------------------------------------------------- pill/tag --- */
.badge {
display: inline-block;
padding: 4px 8px;
border-radius: var(--br-checkbox);
color: var(--text-main-contrast);
background: var(--bg-main-contrast);
font: var(--upper-s);
letter-spacing: var(--ls-upper);
text-transform: uppercase;
}
/* ----------------------------------------------------------- focus ring --- */
.button:focus-visible,
.icon-button:focus-visible,
.text-link:focus-visible,
.custom-select-trigger:focus-visible,
.custom-select-option:focus-visible {
outline: 2px solid var(--border-input-focus);
outline-offset: 2px;
}
/* ------------------------------------------------------------ carousel --- */
/*
* Applied by script once a carousel is wired up. Without JS the container
* stays the grid it was authored as, showing every item.
*/
.is-carousel {
overflow: hidden;
}
.carousel-track {
--carousel-gap: 24px;
display: flex;
flex-wrap: nowrap;
gap: var(--carousel-gap);
will-change: transform;
transition: transform var(--motion-slow-duration) var(--motion-slow);
}
.carousel-track > * {
flex: 0 0
calc(
(100% - (var(--carousel-per-view) - 1) * var(--carousel-gap)) /
var(--carousel-per-view)
);
min-width: 0;
}
/* While the track is being re-ordered behind the scenes. */
.carousel-track.is-settling {
transition: none;
}
+372
View File
@@ -0,0 +1,372 @@
/*
* Home page: hero, product cards, category cards, news cards
*/
/* Home hero */
.home .site-header {
height: 120px;
}
.hero {
height: 654px;
min-height: 654px;
padding: 48px 0 0;
background: var(--bg-secondary);
}
.hero-copy {
display: flex;
width: 100%;
max-width: 1008px;
flex-direction: column;
gap: 32px;
}
.hero-main {
display: flex;
flex-direction: column;
gap: 24px;
}
.hero-title-group {
display: flex;
flex-direction: column;
gap: 16px;
}
.hero h1 {
max-width: 1008px;
margin: 0;
font: var(--h1);
letter-spacing: var(--ls-tight);
}
.hero-copy > p,
.hero-title-group > p {
max-width: 656px;
min-height: 84px;
margin: 0;
color: var(--text-main);
font: var(--lead);
}
.hero-features {
display: grid;
width: 100%;
max-width: 656px;
margin: 0;
grid-template-columns: repeat(3, 1fr);
gap: 32px;
}
.hero-feature {
display: flex;
min-width: 0;
flex-direction: column;
gap: 8px;
font: var(--control-m);
}
.feature-mark {
--icon-size: 24px;
display: block;
}
.hero-button {
width: 144px;
height: 72px;
min-height: 72px;
padding: 0 28px;
font: var(--control-m);
}
/* Product cards */
.products-section {
height: 555px;
padding-top: 16px;
overflow: hidden;
}
.products-section .section-head {
margin-bottom: 24px;
}
.product-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 24px;
}
.product-card {
container-type: inline-size;
min-width: 0;
padding: 16px;
border: 0;
border-radius: 16px;
background: var(--bg-main);
box-shadow: inset 0 0 0 1px var(--border-main);
transition: box-shadow 400ms var(--motion-slow);
}
.product-card:hover,
.product-card:focus-within {
box-shadow: inset 0 0 0 1px var(--border-secondary);
}
.product-card-media {
position: relative;
display: block;
height: 220px;
overflow: hidden;
border-radius: 8px;
background: var(--bg-select-unit-selected);
}
.product-card-media img {
width: 100%;
height: 100%;
object-fit: cover;
}
.product-badge {
display: inline-block;
padding: 3px 6px;
color: var(--text-main-contrast);
background: var(--text-main);
font: var(--upper-s);
letter-spacing: var(--ls-upper);
text-transform: uppercase;
}
.product-card-media .product-badge {
position: absolute;
z-index: 2;
top: 10px;
left: 10px;
}
.product-card-body {
padding: 12px 0 0;
}
.stock {
color: var(--text-positive);
font: var(--control-s);
}
.product-card-title {
margin: 5px 0 1px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font: var(--control-m);
}
.price {
display: flex;
min-height: 27px;
align-items: baseline;
gap: 10px;
font: var(--h5);
letter-spacing: var(--ls-tight-s);
}
.price ins {
order: -1;
text-decoration: none;
}
.price del {
color: var(--text-caption);
font: var(--control-s);
}
/*
* The stepper is 132px at the design width and gives that space back as the
* card narrows; min-content on the button track is its natural width, so the
* label is never squeezed. Below the point where both still fit they stack,
* ending up the same width as each other rather than one starving the other.
*/
.card-buy {
display: grid;
margin-top: 12px;
grid-template-columns: minmax(104px, 132px) minmax(min-content, 1fr);
gap: 8px;
}
@container (max-width: 251px) {
.card-buy {
grid-template-columns: minmax(0, 1fr);
}
}
.add-cart {
min-width: 0;
min-height: 52px;
padding: 10px 12px;
white-space: nowrap;
}
.add-cart .icon {
width: 20px;
height: 20px;
}
/* Category cards */
.categories-section {
padding-top: 60px;
}
.category-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 24px;
}
.category-card {
position: relative;
display: grid;
height: 260px;
grid-template-columns: 400px 260px;
overflow: hidden;
border-radius: var(--br-section-m);
background: var(--bg-secondary);
}
.category-card::after {
position: absolute;
z-index: 2;
inset: 0;
border: 1px solid var(--border-secondary);
border-radius: inherit;
content: "";
opacity: 0;
pointer-events: none;
transition: opacity 400ms var(--motion-slow);
}
.category-card-copy {
display: flex;
padding: 24px;
align-items: flex-start;
flex-direction: column;
transition: background-color 400ms var(--motion-slow);
}
.category-card:hover,
.category-card:focus-visible {
outline: 0;
}
.category-card:hover::after,
.category-card:focus-visible::after {
opacity: 1;
}
.category-card:hover .category-card-copy,
.category-card:focus-visible .category-card-copy {
background: var(--bg-main);
}
.category-card h3 {
margin: 0 0 3px;
font: var(--h4);
letter-spacing: var(--ls-tight);
}
.category-card p {
margin: 0;
color: var(--text-caption);
font: var(--control-m);
}
.category-card .text-link {
margin-top: auto;
}
.category-card-media {
background: var(--bg-select-unit-selected);
}
/* News cards */
.news-section {
padding-top: 24px;
padding-bottom: 64px;
}
.news-section .section-head {
margin-bottom: 24px;
}
.news-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 24px;
}
.news-card {
position: relative;
display: flex;
height: 408px;
padding: 24px;
justify-content: flex-end;
flex-direction: column;
overflow: hidden;
border-radius: 10px;
color: var(--text-main-contrast);
background: linear-gradient(to bottom, var(--bg-select-unit-selected) 0 43%, var(--bg-select-unit-selected) 48%, #000 100%);
}
.news-card > * {
position: relative;
z-index: 1;
transition: transform 400ms var(--motion-slow);
}
.news-card:hover > *,
.news-card:focus-visible > * {
transform: translateY(-8px);
}
.news-card h3 {
margin: 0 0 4px;
font: var(--h5);
letter-spacing: var(--ls-tight-s);
}
.news-card p {
max-width: 340px;
margin: 0;
color: var(--text-main-contrast);
font: var(--control-s);
}
.all-news-link {
display: flex;
height: 56px;
margin-top: 24px;
align-items: center;
justify-content: center;
gap: 8px;
border-radius: var(--br-btn-m);
color: var(--text-main);
background: var(--bg-secondary);
font: var(--control-m);
transition: background-color 100ms ease-in-out;
}
.all-news-link:hover,
.all-news-link:focus-visible {
background: var(--bg-button-light-hover);
}
.all-news-link:active {
background: var(--bg-button-light-pressed);
}
/* The two home grids double as carousels; the track replaces the grid flow. */
.product-grid.is-carousel,
.news-grid.is-carousel {
display: block;
}
+240
View File
@@ -0,0 +1,240 @@
/*
* Header, shared page furniture and the footer
*/
/* Header */
.site-header {
position: relative;
z-index: 30;
background: var(--bg-main);
}
.header-inner {
display: flex;
height: 88px;
align-items: center;
gap: 37px;
border-bottom: 1px solid var(--border-main);
}
.brand {
display: grid;
width: 105px;
height: 42px;
flex: 0 0 105px;
align-items: center;
color: var(--text-main);
}
.brand-mark,
.brand img {
width: 105px;
height: auto;
}
.main-nav {
margin-right: auto;
}
.main-nav ul {
display: flex;
margin: 0;
padding: 0;
align-items: center;
gap: 24px;
list-style: none;
}
.main-nav a {
display: block;
padding: 8px 0;
font: var(--control-m);
}
/* Square icon controls all share the .icon-button component. */
.cart-link,
.slider-controls button,
.gallery-arrow,
.gallery-favorite {
display: inline-grid;
width: 56px;
height: 56px;
padding: 0;
place-items: center;
border: 1px solid var(--border-control);
border-radius: var(--br-btn-m);
color: var(--text-main);
background: var(--bg-main);
cursor: pointer;
transition:
border-color var(--motion-fast),
background-color var(--motion-fast),
color var(--motion-fast);
}
.cart-link:hover,
.slider-controls button:hover,
.gallery-arrow:hover,
.gallery-favorite:hover {
border-color: var(--border-control-hover);
background: var(--bg-button-light-hover);
}
.cart-link:active,
.slider-controls button:active,
.gallery-arrow:active,
.gallery-favorite:active {
border-color: var(--border-control-pressed);
background: var(--bg-button-light-pressed);
}
.cart-link:focus-visible,
.slider-controls button:focus-visible,
.gallery-arrow:focus-visible,
.gallery-favorite:focus-visible {
outline: 2px solid var(--border-input-focus);
outline-offset: 2px;
}
.menu-toggle {
display: none;
width: 48px;
height: 48px;
padding: 0;
place-items: center;
border: 1px solid var(--border-control);
border-radius: var(--br-btn-m);
color: var(--text-main);
background: var(--bg-main);
transition:
border-color var(--motion-fast),
background-color var(--motion-fast);
}
.menu-toggle:hover {
border-color: var(--border-control-hover);
background: var(--bg-button-light-hover);
}
/* Shared typography and controls */
.breadcrumbs {
display: flex;
margin: 32px 0 16px;
padding: 0;
flex-wrap: wrap;
gap: 8px;
color: var(--text-caption);
list-style: none;
font: var(--control-s);
}
.breadcrumbs li:not(:last-child)::after {
display: inline-block;
width: 6px;
height: 6px;
margin-left: 8px;
border-radius: 50%;
background: var(--text-disable);
content: "";
vertical-align: 2px;
}
.breadcrumbs li:last-child {
color: var(--text-main);
}
.page-heading,
.section-title {
margin: 0;
font: var(--h2);
letter-spacing: var(--ls-tight);
}
.page-heading {
margin-bottom: 24px;
}
.section {
padding: 64px 0;
}
.section-head {
display: flex;
margin-bottom: 28px;
align-items: center;
justify-content: space-between;
gap: 24px;
}
.slider-controls {
display: flex;
gap: 8px;
}
.slider-controls .icon {
width: 24px;
height: 24px;
}
.slider-controls button:disabled {
cursor: default;
opacity: 0.35;
}
.gallery-arrow .icon {
width: 24px;
height: 24px;
}
/* Footer */
.site-footer {
height: 176px;
padding: 30px 0 22px;
flex: 0 0 auto;
background: var(--bg-secondary);
}
.page-template-page-catalog .site-main {
padding-bottom: 24px;
}
.catalog-grid-section {
padding-top: 16px;
}
.products-section {
padding-bottom: 48px;
}
.categories-section {
padding-top: 16px;
padding-bottom: 48px;
}
.footer-top {
height: 70px;
border-bottom: 1px dashed var(--border-secondary);
}
.footer-bottom {
display: grid;
padding-top: 20px;
grid-template-columns: auto 1fr auto;
align-items: center;
gap: 24px;
font: var(--control-s);
}
.footer-bottom > span:nth-child(2) {
display: flex;
gap: 28px;
}
.footer-bottom a,
.footer-bottom > span:last-child {
color: var(--text-caption);
text-decoration: underline;
text-decoration-color: var(--border-secondary);
text-decoration-style: dashed;
text-underline-offset: 4px;
}
+258
View File
@@ -0,0 +1,258 @@
/*
* Drawn separators, interaction states, the mobile filter sheet and checkout validation
*/
/* ------------------------------------------------- glyph-free separators --- */
/*
* These were literal "•", "–" and "×" characters in the markup. They are
* separators, not content, so they are drawn instead of typed — which also
* keeps them out of the accessibility tree and out of copied text.
*/
.meta-separator {
display: inline-block;
width: 4px;
height: 4px;
margin: 0 10px;
border-radius: 50%;
background: currentColor;
opacity: 0.4;
vertical-align: middle;
}
.price-fields-separator {
width: 8px;
height: 1px;
flex: 0 0 8px;
background: var(--text-caption);
}
.multiply {
display: inline-block;
width: 8px;
height: 8px;
margin: 0 2px;
background: currentColor;
vertical-align: baseline;
-webkit-mask: var(--icon-x) center / contain no-repeat;
mask: var(--icon-x) center / contain no-repeat;
}
/* ------------------------------------------------------------ interaction --- */
/*
* Hover feedback the design specifies through its own state tokens: list rows
* pick up bg-select-unit-hover, muted tabs and links resolve toward
* text-main / text-link-hover.
*/
.filter-option {
padding: 0 8px;
margin-inline: -8px;
border-radius: var(--br-control-m);
transition: background-color var(--motion-fast);
cursor: pointer;
}
.filter-option:hover {
background: var(--bg-select-unit-hover);
}
.tab-list a {
transition: color var(--motion-fast);
}
.tab-list a:hover {
color: var(--text-main);
}
.main-nav a {
transition: color var(--motion-fast);
}
.main-nav a:hover {
color: var(--text-body);
}
.breadcrumbs a {
transition: color var(--motion-fast);
}
.breadcrumbs a:hover {
color: var(--text-main);
}
.product-card-title,
.cart-item-title a {
transition: color var(--motion-fast);
}
.product-card:hover .product-card-title {
color: var(--text-body);
}
.cart-item-remove {
transition:
background-color var(--motion-fast),
color var(--motion-fast);
}
.cart-item-remove:hover {
color: var(--notice-error);
}
/* ------------------------------------------------- mobile filter sheet --- */
/*
* The design keeps filters in a sidebar on desktop but moves them into a
* sheet on mobile, opened by a "Фильтр" button next to the sort control.
* The sheet reuses the same form, so filtering behaves identically.
*/
.filters-open,
.filters-sheet-head,
.filters-sheet-foot {
display: none;
}
@media (max-width: 767px) {
.filters-open {
display: inline-flex;
align-items: center;
gap: 8px;
padding: var(--pad-h-btn-m) var(--pad-w-text-m) var(--pad-h-btn-m) var(--pad-w-icon-m);
border: 0;
border-radius: var(--br-btn-l);
color: var(--text-main);
background: var(--bg-button-light);
font: var(--control-m);
transition: background-color var(--motion-fast);
}
.filters-open:hover {
background: var(--bg-button-light-hover);
}
.filters-open:active {
background: var(--bg-button-light-pressed);
}
.filters {
position: fixed;
z-index: 60;
inset: 0;
display: flex;
flex-direction: column;
/* The desktop rule sets align-self: start. On an absolutely positioned
box that means "size to content" instead of stretching between top and
bottom, which would make the sheet taller than the viewport. */
align-self: stretch;
overflow: hidden;
border-radius: var(--br-modal) var(--br-modal) 0 0;
background: var(--bg-main);
/* Kept in the DOM so the form state survives; moved out of reach until
the sheet is opened. */
visibility: hidden;
opacity: 0;
transform: translateY(2%);
transition:
opacity var(--motion-slow-duration) var(--motion-slow),
transform var(--motion-slow-duration) var(--motion-slow),
visibility 0s linear var(--motion-slow-duration);
}
.filters.is-open {
visibility: visible;
opacity: 1;
transform: none;
transition-delay: 0s;
}
.filters-sheet-head {
display: flex;
padding: 16px var(--container-gutter);
align-items: center;
justify-content: space-between;
gap: 16px;
border-bottom: 1px solid var(--border-main);
}
.filters-sheet-title {
margin: 0;
font: var(--h4);
letter-spacing: var(--ls-tight);
}
.filters-close {
width: 44px;
height: 44px;
}
.filters form {
flex: 1 1 auto;
padding: 0 var(--container-gutter);
overflow-y: auto;
overscroll-behavior: contain;
}
.filters .filter-group {
padding: 16px 0;
border-bottom: 1px solid var(--border-main);
}
.filters-sheet-foot {
display: block;
padding: 16px var(--container-gutter) calc(16px + env(safe-area-inset-bottom));
border-top: 1px solid var(--border-main);
}
.filters-apply {
width: 100%;
}
body.filters-open-lock {
overflow: hidden;
}
}
.filter-input::-webkit-outer-spin-button,
.filter-input::-webkit-inner-spin-button {
margin: 0;
appearance: none;
}
/* --------------------------------------------------- checkout validation --- */
/*
* The design puts validation on the field itself: a red edge plus red caption
* text under it, per field. It does not use a banner listing every problem, so
* the WooCommerce notice group is suppressed once its errors have been mapped
* onto the fields.
*/
.checkout-input {
position: relative;
}
.checkout-input .field-error {
display: block;
margin-top: 4px;
color: var(--text-negative);
font: var(--caption);
}
.checkout-input .field-error:empty {
display: none;
}
.checkout-input.is-error input {
border-color: var(--border-input-error);
box-shadow: inset 0 0 0 1px var(--border-input-error);
}
.checkout-input input:focus {
box-shadow: inset 0 0 0 1px var(--border-input-focus);
}
.woocommerce-NoticeGroup-checkout.is-field-level,
.checkout .woocommerce-error.is-field-level {
display: none;
}
+300
View File
@@ -0,0 +1,300 @@
/*
* Product page: gallery, summary, tabs
*/
/* Product page */
.product-layout {
display: grid;
margin-bottom: 40px;
grid-template-columns: 776px 544px;
align-items: start;
gap: 24px;
}
.product-gallery {
position: relative;
height: 580px;
overflow: hidden;
border: 1px solid var(--border-main);
border-radius: 16px;
background: var(--bg-secondary);
}
.gallery-images {
position: absolute;
z-index: 0;
inset: 0;
}
.gallery-image {
position: absolute;
inset: 0;
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
.gallery-image-placeholder {
background: var(--bg-secondary);
}
.gallery-badges {
position: absolute;
z-index: 2;
top: 16px;
left: 16px;
display: flex;
gap: 4px;
}
.gallery-favorite {
position: absolute;
z-index: 2;
top: 10px;
right: 10px;
width: 48px;
height: 48px;
border-radius: 50%;
}
.gallery-favorite .icon {
--icon-size: 24px;
}
.gallery-favorite.is-active {
background: var(--bg-main);
}
.gallery-favorite.is-active {
color: var(--notice-error);
}
.gallery-arrow {
position: absolute;
z-index: 2;
top: 50%;
width: 48px;
height: 48px;
border-radius: 50%;
transform: translateY(-50%);
}
.gallery-arrow-prev {
left: 8px;
}
.gallery-arrow-next {
right: 8px;
}
.gallery-dots {
position: absolute;
bottom: 10px;
left: 50%;
display: flex;
gap: 4px;
transform: translateX(-50%);
}
.gallery-dots i {
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--text-caption);
}
.gallery-dots i.active {
background: var(--text-main);
}
.product-summary {
min-height: 652px;
padding: 32px;
border-radius: 16px;
background: var(--bg-main);
box-shadow: 0 16px 38px rgb(0 0 0 / 8%);
}
.product-summary h1 {
margin: 6px 0 3px;
font: var(--h4);
letter-spacing: var(--ls-tight);
}
.product-meta-line {
color: var(--text-caption);
font: var(--control-s);
}
.product-summary .woocommerce-product-details__short-description {
margin-bottom: 14px;
color: var(--text-caption);
font: var(--control-m);
}
.product-summary .woocommerce-product-details__short-description p {
margin: 0;
}
.attribute-table {
width: 100%;
margin: 10px 0 18px;
border-collapse: collapse;
}
.attribute-table td {
padding: 8px 0;
border-top: 1px solid var(--border-main);
font: var(--control-m);
}
.attribute-table tr:last-child td {
border-bottom: 1px solid var(--border-main);
}
.attribute-table td:first-child {
width: 42%;
color: var(--text-caption);
}
.product-option {
position: relative;
display: block;
margin: 14px 0 20px;
}
.product-option > span {
position: absolute;
z-index: 1;
top: 10px;
left: 20px;
color: var(--text-caption);
font: var(--caption);
}
.product-option select {
width: 100%;
height: 60px;
padding: 23px 50px 7px 20px;
border: 1px solid var(--border-main);
border-radius: 10px;
outline: 0;
background: var(--bg-main) var(--icon-caret-down) right 20px center / 16px no-repeat;
appearance: none;
}
.product-option .custom-select {
display: flex;
width: 100%;
}
.product-option .custom-select-trigger {
width: 100%;
height: 60px;
padding: 23px 50px 7px 20px;
border: 1px solid var(--border-main);
border-radius: 10px;
background: var(--bg-main);
}
.product-option .custom-select-trigger::after {
right: 20px;
}
.product-option .custom-select-menu {
width: 100%;
}
.product-summary > .price {
margin: 0 0 12px;
font: var(--h3);
letter-spacing: var(--ls-tight);
}
.product-summary form.cart {
display: grid;
margin: 0;
grid-template-columns: 144px minmax(0, 1fr);
gap: 12px;
}
.product-summary form.cart .quantity-control,
.product-summary form.cart .single_add_to_cart_button {
min-height: 56px;
}
.product-summary .single_add_to_cart_button {
width: 100%;
}
.product-summary .single_add_to_cart_button .icon {
--icon-size: 20px;
}
.buy-one-click {
display: flex;
width: 100%;
min-height: 56px;
margin-top: 8px;
}
.product-tabs {
margin: 0 0 64px;
}
.single-product .product-tabs {
margin-bottom: 46px;
}
.single-product .section {
padding: 16px 0 90px;
}
.tab-list {
display: flex;
margin: 0 0 28px;
padding: 0;
gap: 30px;
border-bottom: 1px solid var(--border-main);
list-style: none;
}
.tab-list a {
display: block;
padding: 14px 0 12px;
color: var(--text-caption);
text-transform: uppercase;
font: var(--upper-m);
letter-spacing: var(--ls-upper);
text-transform: uppercase;
}
.tab-list .active a {
color: var(--text-main);
border-bottom: 1px solid var(--text-main);
}
.prose {
max-width: 800px;
font: var(--body-m);
}
.prose h2,
.prose h3 {
margin: 28px 0 8px;
}
.prose h2 {
font: var(--h4);
letter-spacing: var(--ls-tight);
}
.prose h3 {
font: var(--h5);
letter-spacing: var(--ls-tight-s);
}
.prose p {
margin: 0 0 14px;
}
+548
View File
@@ -0,0 +1,548 @@
/*
* Breakpoints. Must stay after every layer it overrides
*/
/* Responsive */
@media (max-width: 1439px) {
.container {
width: min(calc(100% - 48px), 1200px);
}
.product-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.category-card {
grid-template-columns: minmax(0, 1fr) 40%;
}
.archive-shell {
grid-template-columns: 250px minmax(0, 1fr);
gap: 32px;
}
.archive-results .product-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.product-layout {
grid-template-columns: minmax(0, 1.43fr) minmax(440px, 1fr);
}
}
@media (max-width: 1023px) {
.home .site-header {
height: 120px;
}
.hero-copy,
.hero h1 {
width: 100%;
max-width: 100%;
}
.hero h1 {
white-space: normal;
}
.header-inner {
gap: 16px;
}
.menu-toggle {
display: grid;
margin-left: auto;
}
.main-nav {
position: fixed;
z-index: 50;
inset: 88px 0 0;
display: none;
margin: 0;
padding: 30px 24px;
background: var(--bg-main);
}
.menu-open .main-nav {
display: block;
}
.main-nav ul {
align-items: stretch;
flex-direction: column;
gap: 0;
}
.main-nav a {
padding: 15px 0;
border-bottom: 1px solid var(--border-main);
font: var(--lead);
}
.product-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.category-grid,
.news-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.archive-shell,
.product-layout,
.cart-layout,
.checkout-layout {
grid-template-columns: 1fr;
}
.cart-order-card {
width: 100%;
}
.filters {
padding: 20px;
border-radius: 12px;
background: var(--bg-secondary);
}
.archive-results .product-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.product-gallery {
height: min(70vw, 580px);
}
.product-summary {
min-height: 0;
}
.footer-bottom {
grid-template-columns: 1fr auto;
}
.footer-bottom > span:nth-child(2) {
order: 3;
grid-column: 1 / -1;
}
}
@media (max-width: 639px) {
.home .site-header {
height: 72px;
}
.container {
width: calc(100% - 32px);
}
.header-inner {
height: 72px;
}
.main-nav {
inset: 72px 0 0;
}
.cart-link {
width: 48px;
height: 48px;
}
.shop-toast-stack,
.home .shop-toast-stack {
top: 88px;
right: 16px;
width: calc(100vw - 32px);
}
.section {
padding: 48px 0;
}
.hero {
height: auto;
min-height: 0;
padding: 44px 0 48px;
}
.hero-title-group > p,
.hero-features {
width: 100%;
max-width: 100%;
}
.hero-features {
grid-template-columns: 1fr;
gap: 14px;
}
.products-section {
height: auto;
overflow: visible;
}
.product-grid,
.category-grid,
.news-grid,
.archive-results .product-grid {
grid-template-columns: 1fr;
}
.category-card {
height: 230px;
grid-template-columns: minmax(0, 1fr) 38%;
}
.news-card {
height: 360px;
}
.pagination .nav-links,
.woocommerce nav.woocommerce-pagination ul {
flex-wrap: wrap;
}
.pagination .page-numbers,
.woocommerce nav.woocommerce-pagination ul li a,
.woocommerce nav.woocommerce-pagination ul li span {
width: 40px;
height: 40px;
}
.slider-controls {
display: none;
}
/* The design keeps the filter button and the sort control on one row; the
sort label stacks above its value so the pair fits at 360px. */
.archive-toolbar {
align-items: center;
flex-direction: row;
flex-wrap: nowrap;
gap: 12px;
}
.archive-toolbar .sort-control {
display: flex;
min-width: 0;
margin-left: auto;
align-items: flex-end;
flex-direction: column;
gap: 0;
text-align: right;
}
.archive-toolbar .sort-control > span {
font: var(--caption);
}
/* The mobile layout does not expose the per-page control. */
.archive-toolbar .per-page-control {
display: none;
}
.product-gallery {
height: 400px;
}
.product-summary {
padding: 22px;
}
.product-summary form.cart {
grid-template-columns: 120px minmax(0, 1fr);
}
.tab-list {
overflow-x: auto;
}
.tab-list a {
white-space: nowrap;
}
.article-media,
.article-media-wide {
height: 62vw;
}
.article-lead {
margin-bottom: 32px;
}
.cart-table thead {
display: none;
}
.cart-table tr,
.cart-table td {
display: block;
}
.cart-table tr {
padding: 16px 0;
border-bottom: 1px solid var(--border-main);
}
.cart-table td {
padding: 7px 0;
border: 0;
}
.cart-page {
width: 100%;
height: 622px;
padding: 8px 16px 32px;
}
.checkout-fields {
width: 100%;
}
.checkout-page {
width: 100%;
min-height: 1278px;
padding: 8px 16px 32px;
}
.checkout-page .page-heading {
margin-bottom: 14px;
}
.checkout-layout {
gap: 32px;
}
.checkout-input,
.checkout-map {
width: 100%;
}
.checkout-input,
.checkout-input input {
height: 64px;
}
.checkout-delivery,
.checkout-payment-options {
margin-top: 24px;
}
.checkout-delivery legend,
.checkout-payment-options legend {
margin-bottom: 8px;
}
.delivery-switch {
height: 48px;
margin-bottom: 16px;
}
.delivery-switch span {
height: 40px;
}
.checkout-radio {
min-height: 24px;
}
.checkout-map {
height: auto;
margin-top: 16px;
aspect-ratio: 1.44;
}
.checkout-payment-options {
margin-top: 24px;
}
.checkout-order-card {
width: 100%;
min-height: 408px;
height: 408px;
padding: 16px;
}
.site-footer {
height: auto;
min-height: 210px;
}
.footer-bottom {
grid-template-columns: 1fr;
}
.footer-bottom > span:nth-child(2) {
grid-column: auto;
flex-direction: column;
gap: 10px;
}
}
@media (max-width: 767px) {
/* The mobile frame shows the same row, edge to edge and without the
desktop next button — a touch drag does that job. */
.subcategories {
margin-inline: calc(var(--container-gutter) * -1);
padding-inline: var(--container-gutter);
}
.subcategory-next {
display: none;
}
.subcategory-card {
width: 200px;
}
.quick-filters {
flex-wrap: nowrap;
margin-inline: calc(var(--container-gutter) * -1);
padding-inline: var(--container-gutter);
overflow-x: auto;
scrollbar-width: none;
}
.quick-filters::-webkit-scrollbar {
height: 0;
}
.quick-filter {
flex: 0 0 auto;
}
}
/*
* The cart row needs about 550px before its columns start colliding, and the
* summary beside it is a fixed 432px. Below the width where both fit, they
* stack — otherwise the summary ends up sitting on top of the items.
*/
@media (max-width: 1199px) {
.cart-layout,
.checkout-layout {
grid-template-columns: minmax(0, 1fr);
}
.cart-order-card {
width: 100%;
}
/* Once the summary drops below the fields the checkout is one column, so
centre it rather than leaving both blocks pinned to the left edge. */
.checkout-layout .checkout-fields,
.checkout-layout .checkout-order-card {
width: 432px;
max-width: 100%;
margin-inline: auto;
}
}
/*
* The cart row needs about 550px before its columns collide. Below that it
* takes the stacked shape from the mobile frame — thumbnail top left, copy
* beside it, price and controls on the bottom row.
*/
@media (max-width: 767px) {
.cart-page .page-heading {
margin-bottom: 8px;
}
.cart-layout {
display: flex;
flex-direction: column;
gap: 16px;
}
.cart-items {
width: 100%;
gap: 8px;
}
.cart-item {
position: relative;
display: block;
width: 100%;
min-height: 150px;
height: 150px;
padding: 12px;
}
.cart-thumb {
position: absolute;
top: 12px;
left: 12px;
width: 88px;
height: 70px;
}
.cart-thumb .product-badge {
display: none;
}
.cart-item-copy {
position: absolute;
top: 16px;
right: 12px;
left: 112px;
}
.cart-item-price {
position: absolute;
bottom: 16px;
left: 12px;
text-align: left;
}
.cart-item-quantity {
position: absolute;
right: 64px;
bottom: 16px;
width: 104px;
height: 44px;
}
.cart-item-remove {
position: absolute;
right: 12px;
bottom: 16px;
width: 44px;
height: 44px;
}
.cart-order-card {
width: 100%;
min-height: 212px;
height: 212px;
padding: 16px;
}
.cart-order-card .order-row {
min-height: 28px;
padding: 2px 0;
}
.cart-order-card .order-row.total {
min-height: 36px;
margin: 0;
padding-top: 4px;
}
.cart-order-card .button {
height: 56px;
margin-top: 12px;
}
}
@media (max-width: 767px) {
.checkout-input input {
padding: 25px 20px 15px;
}
.checkout-input input:focus + .field-label,
.checkout-input input:not(:placeholder-shown) + .field-label {
top: 10px;
}
}
+188
View File
@@ -0,0 +1,188 @@
/*
* Design tokens.
*
* A 1:1 transcription of the Figma variable collections (`colors`, `borders`,
* `size`) and text styles. Nothing below this file may invent a colour, a
* radius or a type size — everything resolves to a token defined here.
*/
:root {
/* text */
--text-main: #000;
--text-body: rgb(0 0 0 / 80%);
--text-caption: rgb(0 0 0 / 40%);
--text-disable: rgb(0 0 0 / 24%);
--text-main-contrast: #fff;
--text-body-contrast: rgb(255 255 255 / 88%);
--text-caption-contrast: rgb(255 255 255 / 48%);
--text-disable-contrast: rgb(255 255 255 / 24%);
--text-link: #3b67db;
--text-link-hover: #294ca7;
--text-negative: #d7202b;
--text-positive: #82b443;
--text-white: #fff;
--text-black: #000;
/* bg */
--bg-main: #fff;
--bg-secondary: #f4f4f4;
--bg-main-contrast: #000;
--bg-secondary-contrast: #212121;
--bg-button: #010101;
--bg-button-hover: #373737;
--bg-button-pressed: #000;
--bg-button-light: #f3f3f3;
--bg-button-light-hover: #e2e2e2;
--bg-button-light-pressed: #f0f0f0;
--bg-control-disable: rgb(0 0 0 / 6%);
--bg-select-unit: #fff;
--bg-select-unit-hover: #f4f4f4;
--bg-select-unit-selected: #ededed;
--bg-modal-shadow: rgb(0 0 0 / 64%);
/* border */
--border-main: rgb(0 0 0 / 8%);
--border-secondary: rgb(0 0 0 / 12%);
--border-link: rgb(48 93 209 / 24%);
--border-link-hover: rgb(41 76 167 / 32%);
--border-link-main: rgb(0 0 0 / 16%);
--border-link-main-hover: rgb(0 0 0 / 24%);
--border-checkbox: rgb(0 0 0 / 24%);
--border-checkbox-hover: rgb(0 0 0 / 32%);
--border-input: rgb(0 0 0 / 12%);
--border-input-hover: rgb(0 0 0 / 16%);
--border-input-focus: #393939;
--border-input-error: #d7202b;
--border-control: rgb(0 0 0 / 12%);
--border-control-hover: rgb(0 0 0 / 20%);
--border-control-pressed: rgb(0 0 0 / 12%);
--border-control-disable: rgb(0 0 0 / 8%);
/* notice */
--notice-info: #4299ff;
--notice-success: #8cca3e;
--notice-warning: #f1ab43;
--notice-error: #f5473c;
/* radii — desktop values, overridden for mobile below */
--br-control-l: 16px;
--br-control-m: 8px;
--br-btn-l: 12px;
--br-btn-m: 8px;
--br-section-l: 24px;
--br-section-m: 16px;
--br-modal: 16px;
--br-checkbox: 4px;
/* sizes */
--margin-main-top: 16px;
--margin-main-bottom: 48px;
--margin-header-bottom: 32px;
--h-input-l: 72px;
--h-text-area-l: 136px;
--pad-h-btn-l: 24px;
--pad-h-btn-m: 16px;
--pad-w-text-l: 28px;
--pad-w-text-m: 20px;
--pad-w-icon-l: 24px;
--pad-w-icon-m: 16px;
/* type scale — desktop */
--font-sans: "Inter", system-ui, -apple-system, "Segoe UI", arial, sans-serif;
--h1: 700 68px/72px var(--font-sans);
--h2: 700 48px/56px var(--font-sans);
--h3: 700 38px/42px var(--font-sans);
--h4: 700 28px/32px var(--font-sans);
--h5: 700 20px/24px var(--font-sans);
--lead: 400 20px/28px var(--font-sans);
--body-m: 400 16px/24px var(--font-sans);
--control-m: 400 16px/24px var(--font-sans);
--control-s: 400 14px/20px var(--font-sans);
--caption: 400 12px/16px var(--font-sans);
--upper-l: 600 16px/24px var(--font-sans);
--upper-m: 600 14px/24px var(--font-sans);
--upper-s: 600 12px/16px var(--font-sans);
--accent-m: 700 16px/24px var(--font-sans);
--ls-tight: -0.03em;
--ls-tight-s: -0.02em;
--ls-upper: 0.02em;
/* layout */
--container: 1344px;
--container-gutter: 24px;
/* motion — Figma "Slow" spring: mass 1, stiffness 80, damping 20, 400ms */
--motion-fast: 100ms ease-in-out;
--motion-slow-duration: 400ms;
--motion-slow: linear(
0 0%,
0.0257 6.25%,
0.0879 12.5%,
0.1696 18.75%,
0.2601 25%,
0.3523 31.25%,
0.4419 37.5%,
0.5265 43.75%,
0.6047 50%,
0.6759 56.25%,
0.7401 62.5%,
0.7976 68.75%,
0.8488 75%,
0.894 81.25%,
0.934 87.5%,
0.9691 93.75%,
1 100%
);
/* effects */
--shadow-s: 0 2px 8px rgb(0 0 0 / 6%);
--shadow-m: 0 8px 32px rgb(0 0 0 / 10%);
/*
* The checkbox tick. A native `input` cannot hold a child element, so the
* Phosphor `check-bold` vector is carried as a mask — still the real SVG
* path, tinted with `currentColor`, and it covers checkboxes WooCommerce
* prints for itself.
*/
--icon-check: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"/></svg>');
--icon-x: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"/></svg>');
--icon-caret-down: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"/></svg>');
--icon-caret-up: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><path d="M213.66,165.66a8,8,0,0,1-11.32,0L128,91.31,53.66,165.66a8,8,0,0,1-11.32-11.32l80-80a8,8,0,0,1,11.32,0l80,80A8,8,0,0,1,213.66,165.66Z"/></svg>');
--icon-check-circle-fill: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm45.66,85.66-56,56a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L112,148.69l50.34-50.35a8,8,0,0,1,11.32,11.32Z"/></svg>');
--icon-info-fill: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm-4,48a12,12,0,1,1-12,12A12,12,0,0,1,124,72Zm12,112a16,16,0,0,1-16-16V128a8,8,0,0,1,0-16,16,16,0,0,1,16,16v40a8,8,0,0,1,0,16Z"/></svg>');
--icon-warning-fill: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><path d="M236.8,188.09,149.35,36.22h0a24.76,24.76,0,0,0-42.7,0L19.2,188.09a23.51,23.51,0,0,0,0,23.72A24.35,24.35,0,0,0,40.55,224h174.9a24.35,24.35,0,0,0,21.33-12.19A23.51,23.51,0,0,0,236.8,188.09ZM120,104a8,8,0,0,1,16,0v40a8,8,0,0,1-16,0Zm8,88a12,12,0,1,1,12-12A12,12,0,0,1,128,192Z"/></svg>');
--icon-x-circle-fill: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm37.66,130.34a8,8,0,0,1-11.32,11.32L128,139.31l-26.34,26.35a8,8,0,0,1-11.32-11.32L116.69,128,90.34,101.66a8,8,0,0,1,11.32-11.32L128,116.69l26.34-26.35a8,8,0,0,1,11.32,11.32L139.31,128Z"/></svg>');
}
@media (max-width: 767px) {
:root {
--br-control-l: 12px;
--br-btn-l: 8px;
--br-section-l: 16px;
--br-section-m: 12px;
--margin-main-top: 8px;
--margin-main-bottom: 32px;
--margin-header-bottom: 16px;
--h-input-l: 64px;
--h-text-area-l: 128px;
--pad-h-btn-l: 16px;
--pad-h-btn-m: 10px;
--pad-w-text-l: 24px;
--pad-w-text-m: 16px;
--pad-w-icon-l: 16px;
--pad-w-icon-m: 10px;
--h1: 700 32px/36px var(--font-sans);
--h2: 700 26px/30px var(--font-sans);
--h3: 700 22px/26px var(--font-sans);
--h4: 700 20px/22px var(--font-sans);
--h5: 700 16px/20px var(--font-sans);
--lead: 400 16px/24px var(--font-sans);
--upper-l: 600 14px/18px var(--font-sans);
--upper-m: 600 12px/16px var(--font-sans);
--upper-s: 600 10px/14px var(--font-sans);
--container-gutter: 16px;
}
}