/*
 * emo2026, shared design tokens.
 *
 * Vocabulary contract for every subsystem CSS file in this theme.
 * Subsystem files (header.css, footer.css, …) consume these tokens and
 * keep only their own subsystem-specific values local at the top of the
 * file as --header-*, --footer-*, etc.
 *
 * Plain CSS, no preprocessor, no nesting, no @scope. Targets stable
 * Firefox/Chromium/Safari custom-property support only.
 *
 * Naming rule: --{category}-{name}. Lowercase, hyphenated, no underscores,
 * no camelCase, no nested hierarchies.
 */

:root {
	/* ============================================================
	 * Palette, semantic
	 *
	 * BRAND: the EMO Color System, Brand Guidelines v1.0 (September 2026,
	 * received 2026-10-02, kept at design/palette/EMO-Color-System.svg,
	 * DESIGN-SPEC.md section 11). Its seven values are the final colour
	 * scheme adopted 2026-08-24, grown out of styleguide variant V2
	 * "Grün & Petrol" (2026-07 sheets, shipped 2026-08-11). Each colour
	 * is a --brand-* token below; group and use as the sheet states them,
	 * then what the colour carries on this site:
	 *
	 *   #002b3d  EMO DEEP      PRIMARY    headlines, dark surfaces / hover ink, on-accent ink, dark surfaces
	 *   #007660  EMO CORE      PRIMARY    links, icons, UI / links, accents, interactive text
	 *   #72bf02  EMO SIGNAL    PRIMARY    accents, highlights / on-dark accents, artefact floaters
	 *   #cce4df  EMO AIR       SECONDARY  light surfaces, panels / wash surfaces, soft fills
	 *   #d6e5a5  EMO HARMONY   SECONDARY  surfaces, illustration, charts / CTA fills, wash surfaces
	 *   #faf7f4  EMO PURE      NEUTRAL    backgrounds, text on dark / elevated surfaces
	 *   #101a2e  EMO GRAPHITE  NEUTRAL    body text, dark mode / primary text ink, headlines too
	 *
	 * Two renames, values and roles unchanged both times: on 2026-09-17
	 * the EMO names replaced the first sheet's set (emo Green, emo Blue,
	 * Peter Pan Green, Thursday Blue, Summers Green, Nika White, Davy
	 * Black), and on 2026-10-02 the v1.0 sheet renamed EMO BALANCE to
	 * EMO HARMONY. Older comments elsewhere may still carry an old name;
	 * the hex is the thing to trust.
	 *
	 * The final sheet specifies its own black (#101a2e) and that is now the
	 * text ink. The GREY ramp below stays Apple's: text-secondary/-muted
	 * carry a WCAG audit worth keeping, and neutral fills must not follow
	 * the brand.
	 *
	 * Contrast, measured on adoption (see DESIGN-SPEC.md section 11 for the
	 * full table): ink #101a2e on #ffffff is 17.37:1, on paper 16.27:1, on
	 * the tints ~13:1; #007660 on #ffffff is 5.58:1 (AA body); the CTA pair
	 * #002b3d on #d6e5a5 is 11.05:1 (it was 6.49:1 while the fill was the
	 * lime #72bf02). CAUTION: #007660 on either tint is only ~4.2:1, large
	 * text or icons there, never body text.
	 * ============================================================ */

	/* The seven brand colours under their official names, the single
	 * source of these values; every semantic and raw token below
	 * consumes them. */
	--brand-emo-graphite: #101a2e;
	--brand-emo-deep:     #002b3d;
	--brand-emo-core:     #007660;
	--brand-emo-signal:   #72bf02;
	--brand-emo-harmony:  #d6e5a5;
	--brand-emo-air:      #cce4df;
	--brand-emo-pure:     #faf7f4;

	/* Pure white, deliberately, NOT EMO PURE (owner 2026-08-31): the
	 * page ground has to match the white the catalogue photography is
	 * shot on, so product images meet the page without a seam. EMO PURE
	 * is the brand's white and carries the elevated surfaces below. See
	 * DESIGN-SPEC.md section 11 for the whole rule. */
	--color-bg-base:                 #ffffff;
	/* Warm paper, not Apple's cool #f5f5f7. The grey ramp below keeps
	   #f5f5f7 as --grey-50 for genuinely neutral fills. */
	--color-bg-elevated:             var(--brand-emo-pure);
	--color-bg-translucent:          rgba(255, 255, 255, 0.72);  /* sticky nav over content */
	--color-bg-translucent-strong:   rgba(255, 255, 255, 0.92);  /* dropdown panel */

	/* Final-scheme ink (#101a2e), not Apple's #1d1d1f: 17.37:1 on #ffffff,
	 * 16.27:1 on --color-bg-elevated. Adopted 2026-08-24 with the final sheet. */
	--color-text-primary:            var(--brand-emo-graphite);
	/* A11Y-1 WCAG AA audit (bumped from #6e6e73 → #5c5c61): now 5.79:1 on #ffffff,
	 * 5.34:1 on #f5f5f7, both pass AA cleanly. */
	--color-text-secondary:          #5c5c61;
	/* A11Y-1 WCAG AA audit (bumped from #86868b → #737378): now 4.51:1 on #ffffff
	 * (passes AA for body text); 4.16:1 on #f5f5f7, still slightly under 4.5:1 but
	 * a large improvement, and kept visually distinct from --color-text-secondary. */
	--color-text-muted:              #737378;
	/* Pure white, deliberately, NOT EMO PURE (owner 2026-08-31): this
	 * is legibility ink on dark grounds, never a surface, and EMO PURE
	 * costs 5 to 7 percent of every ratio. Where that margin
	 * bites it decides the case: a 0.72 eyebrow on the lightest dark
	 * tile stop is 5.03:1 in white and 4.79:1 in EMO PURE, i.e.
	 * under AA. The two muted tiers below mirror --color-text-secondary
	 * and --color-text-muted on light grounds. */
	--color-text-inverse:            #ffffff;
	--color-text-inverse-secondary:  rgba(255, 255, 255, 0.86);
	--color-text-inverse-muted:      rgba(255, 255, 255, 0.72);

	/* Two hairline tokens because the chrome currently uses both:
	 * - translucent for sticky nav (sits over blurred backdrop)
	 * - opaque grey for the footer (sits on solid #f5f5f7) */
	--color-border-hairline:             #d2d2d7;
	--color-border-hairline-translucent: rgba(0, 0, 0, 0.08);

	--color-link:                    var(--brand-emo-core);
	--color-link-hover:              var(--brand-emo-deep);
	--color-accent:                  var(--brand-emo-core);

	/* Hover and press washes on transparent icon buttons. Neutral black
	 * alpha by design: these darken whatever they sit on and must not
	 * follow the brand. The press step is the spec's sub-100ms pointer
	 * feedback (section 1). */
	--color-overlay-hover:           rgba(0, 0, 0, 0.04);
	--color-overlay-press:           rgba(0, 0, 0, 0.08);

	/* Call-to-action fill, every primary action pill/submit consumes
	 * these three: EMO HARMONY fill, deep petrol ink.
	 *
	 * The fill was the lime EMO SIGNAL until 2026-09-01; the softer
	 * tint reads better against the warm paper and, because it is lighter,
	 * carries the dark ink at 11.05:1 where the lime managed 6.49:1.
	 *
	 * The ink is emphatically NOT white: on a tint this light white falls
	 * to 1.35:1, which is invisible. The dark ink is the whole pairing.
	 * Hover is the same hue a step down in lightness (9.71:1), never a
	 * different colour, so the button reads as one control. */
	--color-cta:                     var(--brand-emo-harmony);
	--color-cta-ink:                 var(--brand-emo-deep);
	--color-cta-hover:               #c5da81;

	/* ============================================================
	 * Status colours, shared
	 *
	 * One danger red and one success green for the whole theme; the
	 * -ink/-soft pairs are for text on tinted notice/chip surfaces.
	 * Before 2026-08-31 four red families (#d70015, #b91c1c, #b3261e,
	 * #7f1d1d) and three greens had grown in parallel across forms,
	 * notices and chips; every consumer now points here. Neutral by
	 * design, these do not follow the brand palette.
	 * ============================================================ */
	--color-danger:       #d70015;  /* borders, icons, error text on white */
	--color-danger-ink:   #a71422;  /* text on the soft tint */
	--color-danger-soft:  #fde6e8;  /* notice/chip background */
	--color-success:      #007a3d;  /* stock dots, in-stock text */
	--color-success-ink:  #1d6f3a;  /* text on the soft tint */
	--color-success-soft: #e6f6ec;  /* notice/chip background */

	/* ============================================================
	 * Brand palette, raw
	 *
	 * The final-scheme colours by name, for surfaces that need a
	 * specific brand colour rather than a semantic role (artefact floaters,
	 * on-dark accents, the logo mask). Semantic tokens above should be
	 * preferred wherever one fits.
	 * ============================================================ */
	--color-brand-deep:              var(--brand-emo-deep);
	--color-brand-muted:             var(--brand-emo-core);
	--color-brand-accent:            var(--brand-emo-signal);
	--color-brand-paper:             var(--brand-emo-pure);
	--color-brand-ink:               var(--brand-emo-graphite);
	/* The two official tint surfaces. Body text on these is ink or deep
	 * petrol only; #007660 here is ~4.2:1, large text/icons only. */
	--color-brand-tint-mint:         var(--brand-emo-air);
	--color-brand-tint-lime:         var(--brand-emo-harmony);

	/* ============================================================
	 * Shop filter bar (spec "Filter Bar Redesign", 2026-10-01)
	 *
	 * The spec names its tokens by role and drew them in near-brand
	 * hexes (#1b6b58, #124c3f, #0f2a3a, #16262e). Each role lands on the
	 * brand colour it approximates, so the bar cannot drift from the
	 * palette: the dark green is EMO CORE (white on it 5.58:1), text on
	 * the mint and the "open" navy are EMO DEEP (on EMO AIR about 10:1),
	 * body ink is the theme ink. Neutrals reuse the audited greys.
	 * ============================================================ */
	--cf-tint:            var(--brand-emo-air);
	--cf-brand:           var(--brand-emo-core);
	--cf-brand-dark:      var(--brand-emo-deep);
	--cf-navy:            var(--brand-emo-deep);
	--cf-ink:             var(--color-text-primary);
	--cf-muted:           var(--color-text-secondary);
	--cf-control-border:  color-mix(in srgb, var(--brand-emo-deep) 14%, transparent);
	--cf-divider:         var(--grey-100);
	--cf-checkbox-off:    var(--color-text-muted);
	--cf-row-wash:        #f6f8f7;
	--cf-scrim:           color-mix(in srgb, var(--brand-emo-deep) 45%, transparent);
	--cf-shadow-pop:      0 16px 40px color-mix(in srgb, var(--brand-emo-deep) 16%, transparent), 0 2px 6px color-mix(in srgb, var(--brand-emo-deep) 8%, transparent);
	--cf-shadow-strip:    0 8px 24px color-mix(in srgb, var(--brand-emo-deep) 14%, transparent);
	--cf-radius-bar:      12px;
	--cf-radius-panel:    10px;
	--cf-radius-control:  8px;
	--cf-radius-chip:     6px;
	--cf-radius-box:      4px;

	/* ============================================================
	 * Brand gradient ramp
	 *
	 * Every accented gradient fill in the theme resolves to one of these,
	 * so a palette change is a change HERE and nowhere else. The a..f ramp
	 * is the generic rotation used by card/tile grids (wizard tiles,
	 * comparison media, product-line variants); feature/wash are the
	 * one-off treatments.
	 *
	 * Neutral charcoal and grey fills deliberately do NOT come from here,
	 * they are neutral by design and must not follow the brand.
	 * ============================================================ */
	--emo-grad-a: linear-gradient(135deg, #0e3f4a 0%, #4c8f7a 100%);
	--emo-grad-b: linear-gradient(135deg, #082f3a 0%, #3f8a6b 100%);
	--emo-grad-c: linear-gradient(135deg, #1a5560 0%, #5fa184 100%);
	--emo-grad-d: linear-gradient(135deg, #0b3844 0%, #2f7d68 100%);
	--emo-grad-e: linear-gradient(135deg, #14606a 0%, #6fae8e 100%);
	--emo-grad-f: linear-gradient(135deg, #06303c 0%, #4a9a5f 100%);
	--emo-grad-feature:    linear-gradient(160deg, #002b3d 0%, #00695c 55%, #58a63a 100%);
	/* Washes land on the OFFICIAL tint surfaces (EMO AIR #cce4df, EMO
	 * BALANCE #d6e5a5) instead of the improvised greens they used before
	 * the final sheet arrived; the light stops are those tints mixed
	 * toward white. */
	--emo-grad-wash:       linear-gradient(135deg, #eef7f4 0%, #ddeee9 50%, #cce4df 100%);
	/* Opens on EMO PURE, not pure white: its sibling above opens on a
	 * tint mixed toward white, and this ramp's only consumer is a
	 * full-bleed tile, so a cold-white first stop painted a large
	 * off-palette field above a warm lime ramp. */
	--emo-grad-wash-soft:  linear-gradient(160deg, #faf7f4 0%, #ebf2d2 60%, #d6e5a5 100%);

	/* ============================================================
	 * Greyscale, 9 stops for ad-hoc reach
	 * Anchored to the named greys above (600 ≈ text-secondary, 500 ≈
	 * text-muted, 900 ≈ text-primary). --grey-50 was the elevated
	 * surface until the brand palette turned that warm; it stays cool
	 * here as the neutral ramp's lightest stop.
	 * ============================================================ */
	--grey-25:   #fbfbfd;  /* hero off-white above 50, shared gradient stop */
	--grey-50:   #f5f5f7;
	--grey-100:  #e8e8ed;
	--grey-200:  #d2d2d7;
	--grey-300:  #c7c7cc;
	--grey-400:  #aeaeb2;
	--grey-500:  #86868b;
	--grey-600:  #6e6e73;
	--grey-700:  #515154;
	--grey-800:  #2c2c2e;
	--grey-900:  #1d1d1f;

	/* ============================================================
	 * Typography
	 *
	 * Brand face (owner decision 2026-09-01): Inter, self-hosted. It
	 * replaces Helvetica World, which was chosen on 2026-08-27 but
	 * whose licensed webfont files never arrived, so the site had been
	 * rendering the fallback the whole time. The @font-face
	 * declarations live in fonts.css (inc/fonts.php) and load a
	 * variable woff2 from assets/fonts/, never from Google's servers.
	 *
	 * Display and body share one family on purpose: Inter is drawn for
	 * both, and the theme separates the two roles by size, weight and
	 * tracking rather than by typeface. The two tokens stay distinct so
	 * a display face can be introduced later without touching call
	 * sites.
	 * ============================================================ */
	--font-sans:    "Inter", "Helvetica Neue", Helvetica, Arial, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	--font-display: "Inter", "Helvetica Neue", Helvetica, Arial, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

	/* Type scale in rem (DESIGN-SPEC.md section 6): identical render at the
	 * default 16px root, but the whole scale now follows the user's browser
	 * text-size setting instead of ignoring it. Token names keep their px
	 * meaning at the default root so call sites stay readable. */
	--font-size-12: 0.75rem;
	--font-size-14: 0.875rem;
	--font-size-16: 1rem;
	--font-size-18: 1.125rem;
	--font-size-21: 1.3125rem;
	--font-size-28: 1.75rem;
	--font-size-40: 2.5rem;
	--font-size-56: 3.5rem;
	--font-size-80: 5rem;
	--font-size-96: 6rem;

	--line-height-tight: 1.2;
	--line-height-base:  1.5;
	--line-height-loose: 1.75;
	/* Display leading: 56px+ headlines want a tighter set than 1.2. */
	--line-height-display: 1.08;

	--letter-spacing-tight: -0.02em;
	--letter-spacing-base:  -0.01em;
	--letter-spacing-wide:   0.02em;

	/* ============================================================
	 * Spacing, 4px base, doubling-ish progression. In rem so layouts
	 * scale WITH user text size (DESIGN-SPEC.md section 6); values are
	 * the same px at the default 16px root.
	 * ============================================================ */
	--space-1:   0.25rem;
	--space-2:   0.5rem;
	--space-3:   0.75rem;
	--space-4:   1rem;
	--space-5:   1.375rem;   /* Apple's sticky-nav side padding (22px) */
	--space-6:   1.75rem;
	--space-7:   2.5rem;
	--space-8:   3rem;
	--space-9:   4rem;
	--space-10:  5rem;
	--space-11:  6rem;
	--space-12:  8rem;

	/* ============================================================
	 * Radius
	 *
	 * The standard corner radius is 10 percent of an element's shorter
	 * side (owner 2026-08-31). CSS cannot express that: a percentage
	 * border-radius resolves per AXIS, so border-radius: 10% is a tenth
	 * of the width horizontally and a tenth of the height vertically,
	 * which draws elliptical corners on anything that is not square,
	 * and no unit reads an element's own min(width, height). So the
	 * rule is banded here instead: each step is a tenth of the typical
	 * shorter side of the elements that use it, and an element with a
	 * pinned dimension may carry its exact tenth inline.
	 *
	 * The scale is UNCAPPED (owner 2026-08-31, second pass: "it is 10
	 * percent always"), so the top bands are large by design. A radius
	 * that big clips whatever sits in the corner, which is a real
	 * constraint rather than a reason to shrink it: anything pinned
	 * near a corner needs an inset above r * (1 - 1/sqrt2), about 0.3r,
	 * or the arc cuts it. The gallery thumbnail strip, the compare
	 * table and the prose code block carry that clearance explicitly;
	 * when a new surface lands in the top two bands, check its padding
	 * against 0.3r before shipping it.
	 * ============================================================ */
	--radius-chip:     3px;   /* ~25px  chips, marks, small badges   */
	--radius-control:  5px;   /* ~50px  inputs, buttons, list rows   */
	--radius-block:   10px;   /* ~100px thumbs, strips, small media  */
	--radius-panel:   20px;   /* ~200px tiles, card media, panels    */
	--radius-card:    38px;   /* ~380px product cards, summaries     */
	--radius-surface: 62px;   /* ~620px hero media, forms, canvases  */

	/* The rule reaches buttons and chips too (owner 2026-08-31, third
	 * pass: a control is a rounded rectangle, so ten percent of its
	 * shorter side is what it gets, and it should look boxy). What is
	 * left here is the TRACK: a bar only a few px tall, where the round
	 * end is the bar's own shape and a tenth of 3px would be nothing.
	 * Three consumers: the toggle track, the load progress bar, the
	 * carousel scrollbar thumb. Genuinely round objects (avatars, dots,
	 * step markers, icon buttons) are 50 percent, written inline so the
	 * intent is visible where it is used. */
	--radius-pill: 9999px;

	/* Focus rings around INLINE text have no measurable shorter side
	 * (the outline fragments across line breaks), so they keep a fixed
	 * small constant. About twenty rules share it. */
	--radius-focus: 4px;

	/* Legacy names, kept so no rule breaks mid-migration. sm and md
	 * already sat near their band; lg was the flat 12px that served
	 * everything from an 80px thumbnail to a 682px card, which is the
	 * value the rule replaces. */
	--radius-sm:   var(--radius-focus);
	--radius-md:   var(--radius-control);
	--radius-lg:   var(--radius-block);

	/* ============================================================
	 * Motion, Apple-ish easings
	 * ============================================================ */
	/* Press feedback must land under 100ms (DESIGN-SPEC.md section 1);
	 * :active states use this, hover keeps the slower ease on release. */
	--motion-duration-press: 80ms;
	--motion-duration-fast: 150ms;
	--motion-duration-base: 250ms;
	--motion-duration-slow: 400ms;

	/* Standard curve: gentle ease-in/out, the workhorse for hover/focus.
	 * Matches Apple's "standard" cubic, also Material's MD2 standard. */
	--motion-ease-standard:    cubic-bezier(0.4, 0, 0.2, 1);
	/* Emphasized: longer ease-out tail for entry transitions (panels, sheets). */
	--motion-ease-emphasized:  cubic-bezier(0.2, 0, 0, 1);
	/* Mirror of the standard curve, for the RETURN leg of reversible
	 * transitions (DESIGN-SPEC.md section 4: inverse bezier on the way back). */
	--motion-ease-standard-out: cubic-bezier(0.8, 0, 0.6, 1);

	/* ============================================================
	 * Layout
	 * ============================================================ */
	/* Container width. Was a flat 1200px (Apple's marketing cap), which on a
	 * 2560px monitor filled under half the screen and read as a narrow strip
	 * on a professional site (owner 2026-08-25: "not limited to 50 percent,
	 * maybe 65 to 70 percent"). Now: never below the old 1200px, so small
	 * desktops are untouched; 70vw once the viewport is wide enough for that
	 * to be more; the ceiling only stops runaway growth on very wide panels.
	 * 1920 -> 1344, 2560 -> 1792, 3840 -> 2560 (67% of the screen).
	 * The ceiling was 1800px at first, which put a 4K screen back at 47%,
	 * i.e. the exact "half the screen" problem this token exists to fix.
	 * Long lines are NOT a reason to cap here: running text carries its own
	 * measures (content.css --content-column-*, 720 to 820px) which
	 * deliberately do not follow this token. */
	--layout-content-max-width: clamp(1200px, 70vw, 2560px);
	/* Side gutter for every full-width surface. It was a flat 22px, and
	 * because --layout-content-max-width has a 1200px FLOOR, every
	 * viewport below about 1244px got exactly that 22px and nothing
	 * more: the cap is wider than the window, margin auto has no free
	 * space to distribute, and the padding is the whole gutter. That is
	 * the band where text reads as glued to the edge, and it covers
	 * every wide-but-short window on a large monitor.
	 *
	 * Now it grows from 22px at 1100px to 56px at 1600px, then stops
	 * because above that the container's own centering is the larger
	 * term anyway. It stays flat below 1100px on purpose: the nav bar
	 * needs about 978px BETWEEN the gutters for the logo, eight items
	 * and the utility cluster (see --nav-mobile-breakpoint), and
	 * widening the gutter there would reopen the sideways-scroll bug
	 * that comment describes. Every surface resolves to
	 * max(gutter, (100vw - container) / 2), so raising this keeps the
	 * whole theme on one alignment line. */
	--layout-gutter: clamp(22px, calc(22px + (100vw - 1100px) * 0.068), 56px);
}
