/*
 * Elan Deco base layer — typography, controls, interaction.
 * Depends on brand-tokens.css. Loaded on every page.
 */

/* --- Self-hosted fonts. No Google Fonts CDN (RGPD + latency). ---
 *
 *   Instrument Serif  display   Google, OFL          14.7 KB
 *   Satoshi           body/UI   Fontshare, ITF FFL   41.6 KB
 *   Geist Mono        technical Google, OFL          22.6 KB
 *
 * Satoshi is the only Fontshare sans carrying tabular figures (tnum), which
 * price lists and dimension tables need. Its licence forbids modification, so
 * it ships whole rather than subset — see assets/fonts/SATOSHI-LICENSE.txt.
 *
 * No latin-ext: every French character (é è ê à ç ù œ Œ « » € and the narrow
 * no-break space U+202F) lives in the latin range. Only Ÿ (U+0178) falls
 * outside, and it appears in proper nouns we do not carry.
 *
 * Each face is paired with a metric-matched Arial fallback so swapping the
 * real font in shifts nothing — this is what keeps CLS at zero. Values are
 * computed from the font tables by scripts/build-fonts.sh, not guessed.
 */

@font-face {
  font-family: 'Instrument Serif';
  font-style: normal;
  font-weight: 400;
  font-display: optional;
  src: url('../fonts/instrument-serif-400.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Instrument Serif Fallback';
  src: local('Times New Roman'), local('Georgia');
  size-adjust: 98.4%;
  ascent-override: 100.7%;
  descent-override: 31.5%;
  line-gap-override: 0%;
}

@font-face {
  font-family: 'Satoshi';
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url('../fonts/satoshi-variable.woff2') format('woff2-variations');
}

@font-face {
  font-family: 'Satoshi Fallback';
  src: local('Arial'), local('Helvetica Neue');
  size-adjust: 96.4%;
  ascent-override: 104.7%;
  descent-override: 24.9%;
  line-gap-override: 10.4%;
}

@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 100 900;
  font-display: optional;
  src: url('../fonts/geist-mono-variable.woff2') format('woff2-variations');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Geist Mono Fallback';
  src: local('Menlo'), local('Consolas');
  size-adjust: 102.2%;
  ascent-override: 98.3%;
  descent-override: 28.9%;
  line-gap-override: 0%;
}

/* --- Reset ---
 *
 * border-box everywhere. Without it any element combining width:100% with
 * padding overflows its container — the card buttons were 50px wider than the
 * cards holding them.
 */

*,
*::before,
*::after { box-sizing: border-box; }

body { margin: 0; }

img,
picture,
svg,
video {
  display: block;
  max-width: 100%;
}

button,
input,
select,
textarea { font: inherit; color: inherit; }

ul[class],
ol[class] { list-style: none; }

/* --- Global --- */

body {
  font-family: var(--eld-font-body);
  font-size: var(--eld-text-body);
  line-height: var(--eld-leading-normal);
  color: var(--eld-ink-2);
  background-color: var(--eld-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, h5, h6,
.entry-title {
  font-family: var(--eld-font-display);
  font-weight: 400;
  color: var(--eld-ink);
  letter-spacing: var(--eld-tracking-tight);
  line-height: var(--eld-leading-tight);
}

h1, .entry-title { font-size: var(--eld-text-h1); }
h2 { font-size: var(--eld-text-h2); }
h3 { font-size: var(--eld-text-h3); }

/*
 * Instrument Serif ships one weight (400). Below h3 the display face has no
 * headroom left, so smaller headings switch to the body face and take their
 * hierarchy from weight instead.
 */
h4, h5, h6 {
  font-family: var(--eld-font-body);
  font-weight: 600;
  letter-spacing: -0.01em;
}

.eld-eyebrow {
  font-family: var(--eld-font-body);
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--eld-tracking-eyebrow);
  color: var(--eld-ink-2);
}

/* --- Figures ---
 *
 * Tabular figures where numbers stack and must align — tables, cart lines,
 * price lists, quantity fields. A column of 19,90 € above 119,90 € with
 * proportional digits puts the commas out of line, and that alone reads as
 * a careless site.
 *
 * NOT applied globally: a single large price on a product card sits better
 * with proportional figures, which are drawn to look right in isolation.
 */
table td,
table th,
.eld-tnum,
.eld-order-table,
.woocommerce-Price-amount,
.eld-action--cart,
.quantity input,
.eld-specs td { font-variant-numeric: tabular-nums; }

.eld-price--single .eld-price__amount,
.eld-price--hero { font-variant-numeric: proportional-nums; }

/* Reference codes: mono, and never wrapped mid-code. */
.eld-ref,
code.eld-ref {
  font-family: var(--eld-font-mono);
  font-size: 0.875em;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
  white-space: nowrap;
  color: var(--eld-ink-2);
}

/* --- Interaction: every interactive element moves toward accent in 200ms --- */

a,
button,

.button,
input,
select,
textarea {
  transition:
    color var(--eld-transition),
    background-color var(--eld-transition),
    border-color var(--eld-transition),
    transform var(--eld-transition);
}

a { color: var(--eld-accent); text-decoration: none; }
a:hover { color: var(--eld-accent-h); }

/* --- Buttons: gold fill, dark ink, 4px radius, 44px tall --- */

.eld-btn,
.wp-element-button,
.wp-block-button__link,
button.button,
input[type='submit'],
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button,
.woocommerce #respond input#submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: var(--eld-control-h);
  padding: 0 1.5rem;
  border: 0;
  border-radius: var(--eld-radius);
  background-color: var(--eld-accent);
  color: var(--eld-on-accent);
  font-family: var(--eld-font-body);
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: var(--eld-tracking-wide);
  line-height: 1;
  cursor: pointer;
  text-decoration: none;
}

.eld-btn:hover,
.wp-element-button:hover,
.wp-block-button__link:hover,
button.button:hover,
input[type='submit']:hover,
.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce input.button:hover,
.woocommerce #respond input#submit:hover {
  background-color: var(--eld-accent-h);
  color: var(--eld-on-accent);
  transform: scale(1.02);
}

.eld-btn:active,
.woocommerce a.button:active,
.woocommerce button.button:active { transform: scale(0.99); }

.eld-btn--outline,
.woocommerce a.button.alt--outline {
  background-color: transparent;
  border: 1px solid var(--eld-border-2);
  color: var(--eld-ink);
}

.eld-btn--outline:hover {
  background-color: var(--eld-bg-2);
  border-color: var(--eld-accent);
  color: var(--eld-accent);
}

/*
 * Half opacity says "broken", which is the wrong message on a product page:
 * the add-to-cart control is disabled only because a reference has not been
 * picked yet, and it is telling the visitor what to do next. Keep it legible
 * and clearly not-yet-active — flat, no lift on hover — rather than faded.
 */
.eld-btn[disabled],
.woocommerce button.button:disabled {
  background-color: var(--eld-bg-3);
  border-color: var(--eld-border-2);
  color: var(--eld-ink-2);
  cursor: not-allowed;
  transform: none;
}

.eld-btn[disabled]:hover,
.woocommerce button.button:disabled:hover {
  background-color: var(--eld-bg-3);
  border-color: var(--eld-border-2);
  color: var(--eld-ink-2);
}

/* --- Form controls --- */

input[type='text'],
input[type='email'],
input[type='tel'],
input[type='password'],
input[type='search'],
input[type='number'],
select,
textarea,
.woocommerce form .form-row input.input-text,
.woocommerce form .form-row select {
  min-height: var(--eld-control-h);
  padding: 0 1rem;
  border: 1px solid var(--eld-border-2);
  border-radius: var(--eld-radius);
  background-color: var(--eld-bg);
  color: var(--eld-ink);
  font-family: var(--eld-font-body);
  font-size: 1rem;
}

textarea { padding: 0.75rem 1rem; min-height: 8rem; }

input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--eld-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--eld-accent) 25%, transparent);
}

::placeholder { color: var(--eld-ink-3); opacity: 1; }

/* --- Geometry: this brand has exactly two radii. --- */

.woocommerce .button,
.woocommerce input,
.woocommerce select,
.woocommerce textarea,
.woocommerce .card,

.entry-card { border-radius: var(--eld-radius); }

.eld-badge,
.eld-icon-badge { border-radius: var(--eld-radius-full); }

/*
 * No shadows anywhere — depth comes from surface colour layering
 * (--eld-bg -> --eld-bg-2 -> --eld-bg-3), a deliberate Phase 1 decision.
 * Focus rings are the sole exception and are re-asserted below.
 */
.woocommerce *,
.eld-container *,
.entry-content * { box-shadow: none; }

:focus-visible {
  outline: 2px solid var(--eld-accent);
  outline-offset: 2px;
}

input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--eld-accent) 25%, transparent);
}

/* --- Icon badge (USP strip, feature bullets) --- */

.eld-icon-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3.5rem;
  height: 3.5rem;
  border: 1px solid var(--eld-border);
  background-color: var(--eld-bg-3);
  color: var(--eld-accent);
}

/* --- Motion preference --- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .eld-btn:hover,
  .woocommerce a.button:hover { transform: none; }
}

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* --- Reveal on scroll --- */

/*
 * Gated three ways, because hiding content is only ever acceptable if it is
 * certain to come back: the class only applies when JavaScript has swapped
 * .eld-no-js for .eld-js, the observer that restores it is in motion.js, and
 * a reader who has asked for less movement never gets the rule at all.
 *
 * Movement is small on purpose. Eighteen pixels reads as the page settling;
 * a longer travel reads as a slideshow, and on a catalogue the reader is
 * scanning, not being presented to.
 */
@media (prefers-reduced-motion: no-preference) {
  .eld-js [data-eld-reveal] {
    opacity: 0;
    transform: translateY(18px);
    transition:
      opacity 600ms var(--eld-ease-out),
      transform 600ms var(--eld-ease-out);
  }

  .eld-js [data-eld-reveal].is-in {
    opacity: 1;
    transform: none;
  }

  /*
   * Children of a revealed group come in one after another. The step is
   * capped so a row of six does not leave the last card waiting: past the
   * sixth, everything shares the final delay.
   */
  .eld-js [data-eld-reveal-group] > * {
    opacity: 0;
    transform: translateY(14px);
    transition:
      opacity 500ms var(--eld-ease-out),
      transform 500ms var(--eld-ease-out);
  }

  .eld-js [data-eld-reveal-group].is-in > * { opacity: 1; transform: none; }

  .eld-js [data-eld-reveal-group].is-in > *:nth-child(1) { transition-delay: 0ms; }
  .eld-js [data-eld-reveal-group].is-in > *:nth-child(2) { transition-delay: 60ms; }
  .eld-js [data-eld-reveal-group].is-in > *:nth-child(3) { transition-delay: 120ms; }
  .eld-js [data-eld-reveal-group].is-in > *:nth-child(4) { transition-delay: 180ms; }
  .eld-js [data-eld-reveal-group].is-in > *:nth-child(5) { transition-delay: 220ms; }
  .eld-js [data-eld-reveal-group].is-in > *:nth-child(n + 6) { transition-delay: 260ms; }

  /* Lazy images resolve rather than snap. Keyed on a class the script adds,
     not on the attribute: only images motion.js has actually taken charge of
     are ever hidden, so anything injected later stays visible. */
  .eld-fade { opacity: 0; transition: opacity 400ms ease; }
  .eld-fade.is-loaded { opacity: 1; }
}

/* Without JavaScript, or with reduced motion, none of the above ever applies
   and every element keeps its natural state. */
.eld-no-js [data-eld-reveal],
.eld-no-js [data-eld-reveal-group] > * { opacity: 1; transform: none; }

/*
 * Printing never scrolls, so the observer never fires and a printed order
 * page would come out with everything below the first screen blank. Anything
 * that captures a page whole rather than scrolling it — print, PDF export,
 * a screenshot tool — lands here.
 */
@media print {
  [data-eld-reveal],
  [data-eld-reveal-group] > *,
  .eld-fade {
    opacity: 1 !important;
    transform: none !important;
  }
}
