/*
 * Component primitives — Hitsi-Äijät redesign
 * Class-based, page-independent building blocks (DOCX 4.1 "Primitives" and
 * layout helpers). Loads after base.css. Every selector below is a single
 * class (or a documented modifier), so nothing here needs !important and
 * everything stays easy to override from future page-level components.
 * Mobile-first: base rules target small screens, min-width media queries
 * layer on larger-screen behaviour.
 */

/* ---------- Layout primitives ---------- */

.container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-padding-mobile);
}

@media (min-width: 768px) {
  .container {
    padding-inline: var(--container-padding-desktop);
  }
}

.reading {
  max-width: var(--container-reading-max);
  margin-inline: auto;
}

/* For free-form textarea Customizer values (address/hours) — keeps the
   owner's line breaks after esc_html() without needing nl2br(). */
.text-multiline {
  white-space: pre-line;
}

.section {
  padding-block: var(--space-8);
}

@media (min-width: 1024px) {
  .section {
    padding-block: var(--space-9);
  }
}

.section--dark {
  background-color: var(--color-bg-dark);
  color: var(--color-text-on-dark);
}

.stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.stack--sm { gap: var(--space-2); }
.stack--lg { gap: var(--space-6); }

.cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

/* Phase B4: moved here from front-page.css (originally front-page-only) —
   the Yhteystiedot hero (page-yhteystiedot.php) now reuses the exact same
   short accent mark, so this is a page-independent primitive, not a
   front-page-specific one. front-page.css's own mobile centering rule
   (`.hero__accent-bar { margin-inline: auto }`, inside a max-width:767.98px
   query) still applies only where that file loads (is_front_page()), so
   this move changes nothing about the front page's own behavior. */
.hero__accent-bar {
  width: 64px;
  height: 4px;
  margin: 0;
  background-color: var(--color-brand-blue-600);
  border-radius: var(--radius-control);
}

.grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(1, minmax(0, 1fr));
}

@media (min-width: 600px) {
  .grid--2-up { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
  .grid--3-up { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (min-width: 1280px) {
  .grid--4-up { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ---------- Button ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--control-height-medium);
  min-width: var(--touch-target-min);
  padding-inline: 1.25rem; /* 20px */
  border: var(--border-width-default) solid transparent;
  border-radius: var(--radius-control);
  font-family: var(--font-body);
  font-size: var(--text-button-size);
  font-weight: var(--text-button-weight);
  line-height: var(--text-button-line-height);
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--motion-fast) var(--motion-easing),
    color var(--motion-fast) var(--motion-easing),
    border-color var(--motion-fast) var(--motion-easing);
}

.btn--large {
  min-height: var(--control-height-large);
  padding-inline: 1.75rem; /* 28px */
}

.btn--brand {
  background-color: var(--color-brand-blue-600);
  color: var(--color-text-on-dark);
  border-radius: var(--radius-control);
}

.btn--brand:hover {
  background-color: #022c7a;
}

.btn--secondary-dark {
  background-color: var(--color-bg-dark);
  color: var(--color-text-on-dark);
}

.btn--secondary-dark:hover {
  background-color: #2A2A2A;
}

.btn--outline {
  background-color: transparent;
  border-color: var(--color-industrial-900);
  color: var(--color-text-default);
}

.btn--outline:hover {
  background-color: var(--color-bg-page);
}

/* .btn--outline's dark text/border (industrial-900) is invisible against
   a dark section background — overridden here for any outline button
   placed on .section--dark (e.g. Hero's no-image state, service-cta).
   Two-class selector outranks the base rule above without !important.
   Contrast: white border/text on industrial-900 is ~18:1, comfortably
   over both the 4.5:1 text and 3:1 non-text WCAG thresholds. Focus ring
   stays visible (white) via the existing .section--dark :focus-visible
   rule. */
.section--dark .btn--outline {
  border-color: var(--color-surface-000);
  color: var(--color-text-on-dark);
}

.section--dark .btn--outline:hover {
  background-color: rgba(255, 255, 255, 0.12);
}

.btn--text {
  min-height: 0;
  min-width: 0;
  padding-inline: 0;
  background: none;
  color: var(--color-text-default);
}

.btn--text:hover,
.btn--text:focus-visible {
  text-decoration: underline;
}

.btn--icon {
  min-height: var(--touch-target-min);
  min-width: var(--touch-target-min);
  padding: 0;
  background-color: transparent;
  border-color: transparent;
  color: var(--color-text-default);
}

/* Usage requirement, not a visual rule: .btn--icon has no visible label,
   so the markup must always include aria-label (DOCX 2.5). */

.btn[disabled],
.btn[aria-disabled='true'] {
  cursor: not-allowed;
  opacity: 0.6;
}

/* DOCX 2.5: loading keeps the button's footprint and blocks re-submission;
   pair this class with aria-busy="true" in markup. */
.btn--loading {
  color: transparent;
  pointer-events: none;
  position: relative;
}

/* ---------- Field ---------- */

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.field__label {
  font-size: var(--text-small-size);
  font-weight: 600;
}

.field__control {
  min-height: var(--control-height-medium);
  padding: 0.75rem; /* 12px, within the 12–14px brief range */
  /* --color-border-control, not --color-border-default: the decorative
     #DADADA border fails 3:1 non-text contrast for an interactive field
     boundary (see tokens.css). Focus/error states below still override
     this independently. */
  border: var(--border-width-default) solid var(--color-border-control);
  border-radius: var(--radius-control);
  background-color: var(--color-bg-surface);
  font-size: 1rem; /* 16px on mobile prevents iOS input zoom, per DOCX 5.2 */
}

.field__control:focus-visible {
  border-color: var(--color-border-active);
  border-width: var(--border-width-active);
}

textarea.field__control {
  min-height: 8rem; /* 128px */
  resize: vertical;
}

.field__help {
  font-size: var(--text-small-size);
  color: var(--color-text-muted);
}

.field--error .field__control {
  border-color: var(--color-danger);
}

.field__error {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-small-size);
  color: var(--color-danger);
}

/* ---------- Badge ---------- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding-inline: var(--space-2);
  padding-block: 0.125rem;
  border-radius: var(--radius-control);
  font-size: var(--text-small-size);
  font-weight: 600;
  line-height: var(--text-small-line-height);
}

/* Two distinct classes, not one shared "accent" badge: a UI counter
   (cart item count, active-filter count) and a sale/discount indicator
   are different entities that happen to render the same brand-blue right
   now — kept as separate selectors so they can diverge again later
   (e.g. a future promo color) without becoming coupled to each other. */
.badge--brand {
  background-color: var(--color-brand-blue-600);
  color: var(--color-text-on-dark);
}

.badge--sale {
  background-color: var(--color-brand-blue-600);
  color: var(--color-text-on-dark);
}

.badge--success {
  background-color: var(--color-success);
  color: var(--color-text-on-dark);
}

.badge--danger {
  background-color: var(--color-danger);
  color: var(--color-text-on-dark);
}

.badge--muted {
  background-color: var(--color-bg-page);
  border: var(--border-width-default) solid var(--color-border-default);
  color: var(--color-text-muted);
}

/* ---------- Card ---------- */

.card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  background-color: var(--color-bg-surface);
  border: var(--border-width-default) solid var(--color-border-default);
  border-radius: var(--radius-card);
  transition: box-shadow var(--motion-base) var(--motion-easing);
}

.card:hover {
  box-shadow: var(--shadow-card-hover);
}

/* ---------- Icon button (alias kept explicit per DOCX registry naming) --- */

/* Phase B3.1: padding:0 is required, not defensive. Astra's own dynamic
   CSS (Customizer global button style) applies `padding: 15px 30px`
   (desktop) down to `12px 24px` (mobile) to every bare <button> element —
   .icon-button never reset it, and with box-sizing:border-box a padding
   wider than an element's own min-width/min-height forces the box to grow
   to fit the padding instead of the reverse (confirmed live on staging:
   without this reset, the header search toggle measured 80x50px and the
   mobile nav-toggle 63.8x44px, both against an intended 44x44).
   Confirmed via a full audit of every real .icon-button usage in this
   theme (grep across every .php file, not assumed) that all eight are
   icon-only — an inline SVG (search/account/cart/nav-toggle/scroll-top/
   mega-menu toggle/catalog tree toggle) or a single "×" glyph (catalog
   filters close), never a text/word label — so this reset is safe to
   apply to the whole shared class rather than one selector at a time.
   .icon-button is also never applied to Astra's own markup or to any of
   this theme's *text* buttons (.btn/.btn--brand use a separate class
   entirely — see below), so this stays scoped to icon-only controls, not
   a global `button { padding: 0 }` override. */
.icon-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--touch-target-min);
  min-width: var(--touch-target-min);
  padding: 0;
  background: none;
  border: none;
  color: var(--color-text-default);
  cursor: pointer;
}

/* ---------- Breadcrumb ---------- */

.breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1);
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: var(--text-small-size);
  color: var(--color-text-muted);
}

.breadcrumb__item {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.breadcrumb__item:not(:last-child)::after {
  content: '/';
  color: var(--color-border-default);
}

.breadcrumb__item[aria-current='page'] {
  color: var(--color-text-default);
}

/* ---------- Pagination ---------- */

.pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  list-style: none;
  margin: 0;
  padding: 0;
}

.pagination__link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--touch-target-min);
  min-width: var(--touch-target-min);
  border: var(--border-width-default) solid var(--color-border-default);
  border-radius: var(--radius-control);
  color: var(--color-text-default);
  text-decoration: none;
}

.pagination__link[aria-current='page'] {
  border-color: var(--color-industrial-900);
  font-weight: 600;
}

/* ---------- Notice ---------- */

.notice {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-4);
  border: var(--border-width-default) solid var(--color-border-default);
  border-radius: var(--radius-control);
  background-color: var(--color-bg-surface);
}

/* Non-color cue requirement (DOCX 2.9): pair each variant with an icon in
   markup, not color alone, since danger/success can't be the only signal. */
.notice--info { border-color: var(--color-info); }
.notice--success { border-color: var(--color-success); }
.notice--warning { border-color: var(--color-brand-blue-600); }
.notice--error { border-color: var(--color-danger); }
