/*
Theme Name:   Madformat
Theme URI:    https://madformat.com
Description:  Storefront for a decor catalogue — aluminium wall panels, art prints and soft-touch tables. Child of Storefront, so the parent stays updatable and every custom change reads as a diff against it.
Author:       kunkk
Version:      0.2.0
Template:     storefront
Requires PHP: 8.1
Text Domain:  madformat
Domain Path:  /languages
*/

/* ---------------------------------------------------------------------------
   Tokens — drawn from the materials: gallery-white paper, linen, the oak of
   the table legs, soft-touch graphite. The chrome is quiet and monochrome so
   the patterns are the colour. Oak is the one warm accent and is decoration
   only (underlines, rules, icons): at 2.8:1 on white it never carries text.
   Signal red is for errors and sale, nothing else.
   ------------------------------------------------------------------------ */

:root {
  --paper: #e9e6e0;          /* linen: surfaces, cards, image frames */
  --paper-bright: #f7f6f3;   /* gallery white: the page */
  --aluminium: #b9bcbe;
  --graphite: #2b2e31;
  --ink: #141518;
  --oak: #b78b5e;
  --signal: #b8323f;         /* 5.5:1 on the page, 4.7 on linen */
  --carmine: var(--signal);  /* legacy name; errors only */

  --rule: rgba(20, 21, 24, 0.12);
  --rule-soft: rgba(20, 21, 24, 0.06);

  --measure: 66ch;
  --gutter: clamp(1rem, 4vw, 2.5rem);

  --step--1: clamp(0.82rem, 0.79rem + 0.15vw, 0.9rem);
  --step-0: clamp(1rem, 0.96rem + 0.2vw, 1.12rem);
  --step-1: clamp(1.26rem, 1.18rem + 0.4vw, 1.5rem);
  --step-2: clamp(1.6rem, 1.44rem + 0.8vw, 2.2rem);
  --step-3: clamp(2.1rem, 1.78rem + 1.6vw, 3.4rem);
  --step-4: clamp(2.7rem, 1.6rem + 5vw, 5.6rem);

  /* Type roles. The steps above are a size ladder; these say what a size is
     *for*, so a heading and a price stop borrowing each other's rung. Each
     clamp runs from the 390px phone to the 1440px desktop.

     The page used to lean on two sizes — step-0 and step--1 — under one very
     large heading, which is why the hierarchy read as a poster over small
     print with nothing in between. The middle is what these add. */
  --type-display: clamp(2.125rem, 1.614rem + 2.1vw, 3.5rem);   /* 34 → 56, homepage opener only */
  --type-h1: clamp(1.75rem, 1.471rem + 1.14vw, 2.5rem);        /* 28 → 40 */
  --type-h2: clamp(1.375rem, 1.259rem + 0.48vw, 1.6875rem);    /* 22 → 27 */
  --type-lede: clamp(1.0625rem, 1.016rem + 0.19vw, 1.1875rem); /* 17 → 19 */
  --type-body: clamp(1.03rem, 1.02rem + 0.05vw, 1.0625rem);    /* 16.5 → 17 */
  --type-card: 0.9375rem;                                      /* 15, flat: a name is a name */
  --type-price: clamp(1rem, 0.977rem + 0.1vw, 1.0625rem);      /* 16 → 17 */
  --type-control: 0.9375rem;                                   /* 15, buttons and chips */
  --type-meta: clamp(0.8125rem, 0.8rem + 0.05vw, 0.84375rem);  /* 13 → 13.5 */
  --type-caption: clamp(0.75rem, 0.738rem + 0.05vw, 0.78125rem); /* 12 → 12.5 */

  /* The brand's own lettering. Archivo has no Cyrillic, which is exactly why
     it no longer sets the page — but the wordmark is Latin and stays as drawn. */
  --font-wordmark: 'Archivo', system-ui, sans-serif;

  /* Shape and depth. Rounded like a soft-touch edge, never glossy. */
  --page: 1380px;
  --radius-card: 0.5rem;     /* media */
  --radius-inner: 0.25rem;   /* controls inside cards */
  --radius-control: 4px;     /* buttons, fields */
  --radius-pill: 999px;      /* chips only */
  --lift: 0 1px 2px rgba(18, 20, 22, 0.06), 0 12px 32px -12px rgba(18, 20, 22, 0.22);
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);

  /* Colour roles. Every text and control colour below comes from here, and
     each pair is checked against WCAG 2.2 AA on paper-bright, paper and
     white (text 4.5:1, control edges and graphics 3:1). Do not use raw
     rgba() greys for text: an alpha grey passes on one surface and fails on
     the next. */
  --text: var(--ink);
  --text-muted: #54575b;          /* 6.7 : 1 on the page, 5.8 on linen */
  --border-control: #7a7d82;      /* 3.8 : 1 on the page, 3.3 on linen */
  --on-dark: #f7f6f3;             /* 12.6 : 1 on graphite */
  --on-dark-muted: #b4b2ad;       /* 6.5 : 1 on graphite */
  --accent-on-dark: var(--on-dark-muted);
  --focus: var(--ink);
  --focus-on-dark: var(--on-dark);

  /* The bridge to the plugins (madformat-print, madformat-3d): their CSS is
     structure only and reads these, so they wear the theme without the
     theme reaching into them. A "line" there is also a control's edge, so
     it takes the 3:1 control colour; hairlines use "rule". */
  --mf-ink: var(--ink);
  --mf-paper: var(--paper);
  --mf-surface: var(--paper-bright);
  --mf-rule: var(--rule);
  --mf-line: var(--border-control);
  --mf-text-muted: var(--text-muted);
  --mf-accent: var(--focus);
  --mf-radius-card: var(--radius-card);
  --mf-radius-control: var(--radius-control);
}

/* ---------------------------------------------------------------------------
   Type. Golos Text, 400 to 600, sentence case throughout — a restrained voice
   a business buyer respects, with no shouting capitals. It replaces Archivo,
   which reads the same way but has no Cyrillic, so two thirds of the shop's
   languages were being set by the visitor's operating system.
   ------------------------------------------------------------------------ */

body,
button,
input,
select,
textarea,
.site-title,
.widget h1,
.widget h2 {
  font-family: 'Golos Text', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: var(--type-body);
  line-height: 1.6;
  color: var(--ink);
  background-color: var(--paper-bright);
  font-synthesis: none;
}

h1,
h2,
h3,
.site-title,
.woocommerce-loop-product__title,
.product_title {
  font-family: 'Golos Text', system-ui, sans-serif;
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -0.018em;
  color: var(--ink);
  /* Russian and Latvian words are long; a heading that breaks into a single
     orphan reads as a mistake before it reads as a size. */
  text-wrap: balance;
}

h1,
.product_title {
  font-size: var(--type-h1);
  line-height: 1.1;
  letter-spacing: -0.022em;
}
h2 {
  font-size: var(--type-h2);
  line-height: 1.18;
}

/* The wordmark keeps Archivo; nothing else does. */
.mf-logo__name,
.site-title a {
  font-family: var(--font-wordmark);
}

/* Prices and the counts beside a facet are read by comparing them down a
   column, so their digits share one width. */
.price,
.mf-facet__count,
.mf-filters__count,
.mf-mega__count,
.woocommerce-result-count {
  font-variant-numeric: tabular-nums;
}

p,
li {
  max-width: var(--measure);
}

a {
  color: var(--ink);
  text-underline-offset: 0.22em;
  text-decoration-thickness: 1px;
}

a:hover {
  color: var(--ink);
  text-decoration-color: var(--oak);
}

a:focus-visible,
button:focus-visible,
select:focus-visible,
input:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

/* Storefront outlines anything focused, mouse clicks included, in its own
   purple (#7f54b3, not in this palette). A clicked chip kept a rounded purple
   ring that our user read as "nonsense when selecting". The focus ring is for
   keyboard users, so it shows on :focus-visible only; the selected state is
   the ink ring the chips draw themselves. */
a:focus:not(:focus-visible),
button:focus:not(:focus-visible),
.button:focus:not(:focus-visible),
input:focus:not(:focus-visible),
select:focus:not(:focus-visible),
textarea:focus:not(:focus-visible),
summary:focus:not(:focus-visible),
[tabindex]:focus:not(:focus-visible) {
  outline: none;
}

/* ---------------------------------------------------------------------------
   Chrome — quiet, so the work carries the page.
   ------------------------------------------------------------------------ */

.site-header {
  background-color: var(--paper);
  border-bottom: 1px solid var(--rule);
  padding-top: 1.4em;
  padding-bottom: 1.4em;
}

.site-title a {
  font-weight: 700;
  letter-spacing: -0.02em;
  text-decoration: none;
}

.site-footer {
  background-color: var(--graphite);
  color: var(--paper);
}

.site-footer a {
  color: var(--paper);
}

.storefront-breadcrumb {
  background-color: transparent;
  padding: 0.7em 0 0;
  font-size: var(--type-meta);
}

/* ---------------------------------------------------------------------------
   Catalogue. The image is the product, so the grid keeps each work's own
   proportion instead of cropping everything to a common square. Panels are
   near-square, posters are portrait, tables are landscape — that variation is
   information about what the thing is, not noise to be flattened.
   ------------------------------------------------------------------------ */

ul.products {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(15rem, 100%), 1fr));
  gap: clamp(1.1rem, 2.6vw, 2.2rem);
  margin: 0;
  padding: 0;
  list-style: none;
}

ul.products::before,
ul.products::after {
  content: none;
}

ul.products li.product {
  width: auto;
  margin: 0;
  padding: 0;
  float: none;
  clear: none;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  text-align: left;
}

ul.products li.product a img {
  display: block;
  width: 100%;
  height: auto;
  margin: 0;
  background-color: var(--paper-bright);
  border: 1px solid var(--rule-soft);
}

ul.products li.product .woocommerce-loop-product__title {
  font-size: var(--step-0);
  font-weight: 500;
  letter-spacing: 0;
  line-height: 1.3;
  margin: 0;
  padding: 0;
  max-width: none;
}

ul.products li.product .price {
  color: var(--ink);
  font-size: var(--step--1);
  font-variant-numeric: tabular-nums;
  margin: 0;
}

ul.products li.product .price del {
  opacity: 0.5;
}

ul.products li.product .button {
  margin-top: 0.3rem;
  align-self: start;
}

/* ---------------------------------------------------------------------------
   Buttons — flat, matte, the soft-touch finish the tables are sold on.
   ------------------------------------------------------------------------ */

button,
.button,
input[type='submit'],
.woocommerce #respond input#submit,
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button {
  background-color: var(--ink);
  color: var(--paper-bright);
  border: 0;
  border-radius: var(--radius-control);
  padding: 0.95em 1.9em;
  font-size: var(--step--1);
  font-weight: 700;
  text-shadow: none;
  transition: background-color 0.16s ease, transform 0.16s var(--ease);
}

button:hover,
.button:hover,
.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce input.button:hover,
.woocommerce button.button.alt:hover {
  background-color: var(--graphite);
  color: var(--paper-bright);
}

.woocommerce button.button.alt,
.woocommerce a.button.alt {
  background-color: var(--ink);
  color: var(--paper-bright);
}

/* ---------------------------------------------------------------------------
   Product page
   ------------------------------------------------------------------------ */

.single-product div.product .summary .price,
.single-product div.product .summary .price .amount {
  color: var(--ink);
  font-size: var(--step-1);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.single-product div.product .woocommerce-product-gallery img {
  background-color: var(--paper-bright);
  border: 1px solid var(--rule-soft);
}

.single-product .woocommerce-tabs ul.tabs {
  border-bottom: 1px solid var(--rule);
}

.woocommerce-message,
.woocommerce-info {
  border-top-color: var(--ink);
  background-color: var(--paper-bright);
}

.woocommerce-message::before,
.woocommerce-info::before {
  color: var(--ink);
}

/* ---------------------------------------------------------------------------
   Pickers — print formats and table heights, as size chips.

   Both keep their drawing: a size dropdown cannot answer "how big is that on
   my wall", nor "how tall next to my sofa". But the drawing now sits inside a
   chip of one fixed footprint, so a row of ten formats reads as a grid with
   labels and prices on shared lines, not as rectangles of every size with
   text wherever it lands.

   Selection is a 2px ink ring, the same on every picker on the page. Carmine
   is kept for errors and warnings, so a chosen size never reads as a wrong one.
   ------------------------------------------------------------------------ */

.format-scale,
.height-scale {
  margin: 1.6rem 0;
  padding-top: 1.4rem;
  border-top: 1px solid var(--rule);
}

.format-scale__caption,
.height-scale__caption {
  margin: 0 0 1rem;
  font-size: var(--step--1);
  color: var(--text-muted);
  max-width: var(--measure);
}

.format-scale__list,
.height-scale__list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(6.25rem, 1fr));
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.format-scale__item,
.height-scale__item {
  margin: 0;
  max-width: none;
}

/* The chip. */
button.format-scale__button,
button.height-scale__button {
  position: relative;
  display: grid;
  grid-template-rows: var(--stage, 4.25rem) auto auto;
  align-content: end;
  justify-items: center;
  align-items: end;
  gap: 0.35rem;
  width: 100%;
  height: 100%;
  padding: 0.7rem 0.4rem 0.6rem;
  border: 1.5px solid var(--border-control);
  border-radius: var(--radius-inner);
  background: #fff;
  color: var(--text);
  font-size: var(--step--1);
  font-weight: 600;
  font-stretch: 100%;
  letter-spacing: 0;
  line-height: 1.2;
  text-transform: none;
  cursor: pointer;
  transition: border-color 0.14s ease, box-shadow 0.14s ease;
}

button.format-scale__button:hover,
button.height-scale__button:hover {
  border-color: var(--ink);
  background: #fff;
  color: var(--text);
}

button.format-scale__button[aria-pressed='true'],
button.height-scale__button[aria-pressed='true'] {
  border-color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink);
  background: #fff;
  color: var(--text);
}

/* The drawing, to scale, standing on the chip's baseline. */
.format-scale__swatch {
  display: block;
  align-self: end;
  max-width: 100%;
  box-sizing: border-box;
  background-color: var(--paper);
  border: 1.5px solid var(--border-control);
  transition: border-color 0.14s ease;
}

button.format-scale__button[aria-pressed='true'] .format-scale__swatch {
  border-color: var(--ink);
}

.format-scale__label,
.height-scale__label {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

/* Two lines reserved, so a label that wraps ("841x1189 (A0)") does not push
   its price off the row's shared line. */
.format-scale__label {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  min-height: 2.4em;
  min-width: 0;
  max-width: 100%;
  overflow-wrap: anywhere;
}

button.format-scale__button {
  min-width: 0;
}

/* Media have separate size runs: a poster comes in A sizes, a canvas in
   millimetre formats. Once a medium is chosen the other run is not "sold
   out", it does not exist, so its chips leave instead of greying out. */
.format-scale__item:has(.is-unavailable) {
  display: none;
}

@media (max-width: 600px) {
  .format-scale__list {
    grid-template-columns: repeat(auto-fill, minmax(5rem, 1fr));
    gap: 0.4rem;
  }

  button.format-scale__button {
    --stage: 3.9rem;
    padding: 0.55rem 0.25rem 0.5rem;
    font-size: 0.8125rem;
  }
}

.format-scale__price {
  min-height: 1.2em;
  font-weight: 500;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

button.format-scale__button[aria-pressed='true'] .format-scale__price {
  color: var(--text);
}

/* Heights: a table silhouette in each chip, all drawn at one scale on one
   baseline, so the dashed seat line runs through every chip at the same
   height and reads as one line across the row. */
.height-scale__list {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  --stage: 7.75rem;
}

.height-scale__figure {
  position: relative;
  display: block;
  width: min(4.6rem, 80%);
  height: var(--h);
}

.height-scale__top,
.height-scale__leg {
  position: absolute;
  transition: background-color 0.14s ease;
}

.height-scale__top {
  top: 0;
  left: 0;
  right: 0;
  height: 5px;
  border-radius: 1px;
  background-color: var(--graphite);
}

.height-scale__leg {
  top: 5px;
  bottom: 0;
  width: 4px;
  background-color: var(--border-control);
}

.height-scale__leg--left {
  left: 0.5rem;
}

.height-scale__leg--right {
  right: 0.5rem;
}

button.height-scale__button[aria-pressed='true'] .height-scale__leg {
  background-color: var(--graphite);
}

/* The seat line, per chip, at the shared scale. */
button.height-scale__button::after {
  content: '';
  position: absolute;
  left: 0.5rem;
  right: 0.5rem;
  top: calc(0.7rem + var(--stage) - var(--seat, 0px));
  display: block; /* Storefront hides button::after */
  border-top: 1.5px dashed var(--text-muted);
  pointer-events: none;
}

/* Homepage: the same drawing as a plain illustration, not chips. */
.height-scale--static .height-scale__list {
  display: flex;
  align-items: flex-end;
  position: relative;
}

.height-scale--static .height-scale__list::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(1.9rem + var(--seat, 0px));
  border-top: 1.5px dashed var(--text-muted);
  pointer-events: none;
}

.height-scale--static .height-scale__button {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
