/* ==========================================================================
   LuxScout — DESIGN TOKENS (single source of truth)
   ==========================================================================
   ONE LuxScout. Every surface — the editorial discovery site (styles.css) and
   the member/search application (app/dashboard.css) — reads its colour,
   typography, spacing, radius, border, shadow and control geometry from THIS
   file. Nothing else may define a palette.

   Before this file existed the product ran two unrelated visual systems: a
   luminous editorial light theme on Home/Brands/Categories/Product, and a
   separate near-black "app" theme on Search, Search by Image, Dashboard,
   Account and the auth flows — different background, type scale, buttons,
   cards, chips, modals and icons. Moving between them felt like leaving the
   product. The dark theme is gone; the editorial language is the product.

   RULES
     1. Never hard-code a colour in a component. Use a token.
     2. Never introduce a page-scoped palette or a route-specific override.
     3. Dark is reserved for deliberate editorial statement SECTIONS
        (--obsidian) and scrims — never for a page chrome or an app shell.
     4. New surface? Compose it from these tokens; if a token is missing,
        add it here so every surface inherits it.
   ========================================================================== */

:root {
  /* ---- SURFACES --------------------------------------------------------- */
  --porcelain: #FBFAF7;   /* primary page — luminous warm white */
  --ivory: #F4F1E9;       /* alternating tint / quiet fills */
  --paper: #FFFFFF;       /* elevated cards */
  --obsidian: #14110B;    /* dark statement sections (editorial only) */
  --obsidian-2: #1E1A12;  /* dark elevated surface */

  /* ---- INK -------------------------------------------------------------- */
  /* Four text weights, all of which must be READABLE.
     --ink-3 and --ink-4 were #8E8678 and #A79E8E: 3.2:1 and 2.4:1 on ivory,
     well under WCAG AA, and used at 12.5px for delivery estimates, counts,
     breadcrumbs, strike-through prices and the footer's legal line. They looked
     refined in a mockup and were genuinely hard to read on a phone.

     Hierarchy below --ink-2 is now carried by SIZE AND WEIGHT rather than by
     fading toward the background, which is why the last two steps are close
     together. scripts/check-contrast.mjs measures every one of these against
     every surface and fails the build below 4.5:1. */
  --ink: #1A1611;         /* primary text                       — 16.0:1 */
  --ink-2: #574F44;       /* secondary                          —  7.1:1 */
  --ink-3: #6E675C;       /* tertiary / captions                —  5.0:1 */
  --ink-4: #726B60;       /* faint — timestamps, meta, was-price —  4.7:1 */
  --on-dark: #F2EEE4;     /* text on obsidian */
  --on-dark-2: #B6AE9D;   /* secondary on obsidian */

  /* ---- METAL ------------------------------------------------------------ */
  /* #8C7339 was 4.35:1 on porcelain and 4.02:1 on ivory — it read as AA and
     was not. Every link on the site uses it. */
  --gold: #7E6832;        /* accent TEXT on light               —  4.8:1 */
  --gold-ink: #7E6832;    /* same value under an app-safe alias */
  --gold-deep: #6F5B2C;   /* hover/pressed accent text */
  --champagne: #C6AC74;   /* decorative gold — rules, hairlines, fills */
  --champagne-soft: #E0CFA6;
  --gold-dark: #D6BE86;   /* gold on obsidian */
  --gold-wash: rgba(140, 115, 57, 0.07);
  --gold-wash-2: rgba(140, 115, 57, 0.12);
  --on-gold: #221805;     /* text on a champagne fill */

  /* ---- LINES ------------------------------------------------------------ */
  --line: #E8E2D5;
  --line-strong: #D8D0BF;
  --line-dark: rgba(214, 190, 134, 0.18);

  /* ---- SEMANTIC --------------------------------------------------------- */
  --success: #2F6B4F;  --success-wash: rgba(47, 107, 79, 0.09);
  --warning: #8A6420;  --warning-wash: rgba(138, 100, 32, 0.10);
  --danger:  #A23B3B;  --danger-wash:  rgba(162, 59, 59, 0.08);
  --info:    #3C5A73;  --info-wash:    rgba(60, 90, 115, 0.08);
  --disabled-bg: #F0EDE5; --disabled-ink: #A79E8E;
  --overlay: rgba(26, 22, 17, 0.42);   /* scrim behind modals/drawers */

  /* Authentication accent — the controlled red used ONLY for the
     sign-in-to-unlock callout (icon, border, primary button). Never a wash. */
  --accent-red: #A23B3B;
  --accent-red-dark: #7E2E2E;
  --accent-red-wash: rgba(162, 59, 59, 0.07);

  /* ---- ELEVATION -------------------------------------------------------- */
  --shadow-sm: 0 1px 2px rgba(26, 22, 17, 0.04);
  --shadow: 0 2px 8px rgba(26, 22, 17, 0.05), 0 24px 60px -28px rgba(26, 22, 17, 0.18);
  --shadow-card: 0 1px 2px rgba(26, 22, 17, 0.04), 0 12px 32px -22px rgba(26, 22, 17, 0.16);
  --shadow-pop: 0 18px 48px -20px rgba(26, 22, 17, 0.26);

  /* ---- TYPEFACES -------------------------------------------------------- */
  --serif: 'Cormorant Garamond', 'Playfair Display', Georgia, serif;
  --sans: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, monospace;

  /* ---- TYPE SCALE ------------------------------------------------------- */
  --t-display: clamp(44px, 7.5vw, 104px);
  --t-h1: clamp(34px, 5.2vw, 64px);
  --t-h2: clamp(30px, 4.4vw, 52px);
  --t-h3: clamp(21px, 2.2vw, 27px);
  --t-h4: 19px;
  --t-lede: clamp(18px, 1.7vw, 22px);
  --t-body: 17px;
  --t-body-app: 15px;      /* denser reading size inside member tools */
  --t-small: 13.5px;
  --t-meta: 12.5px;
  --t-eyebrow: 11.5px;     /* also the LEGIBILITY FLOOR — see below */
  --t-label: 12px;
  /* --t-button was 13.5px and nothing read it: .lx-btn set its label from
     --t-label, so every button on the site was 12px and the button token was
     decoration. The token now carries the size buttons actually use, and
     .lx-btn reads it, so control labels can be tuned in one place. */
  --t-button: 12px;

  /* ---- OBJECT TITLES ----------------------------------------------------
     Between --t-h3 (a section heading) and --t-body sat nine ad-hoc serif
     sizes — 17, 19, 20, 21, 21, 21, 22, 22 and 26px — for headings of the
     same rank: a card name, a bag line, a modal head, a fieldset legend, a
     summary title. Measured on the live site, .lx-rail-name (20px) and
     .lx-launch-item h3 (21px) sit side by side on the homepage at different
     sizes for no reason a reader could name. Four steps, and every object
     heading picks one. */
  --t-title-lg: 22px;      /* modal heads, footer wordmark */
  --t-title: 21px;         /* legends, payment + summary heads, rail names */
  /* Defined FROM --t-h4, not repeated as 19px: a fourth-level heading and a
     product card's name sit on the same rung, and two tokens quietly holding
     the same literal is how a scale starts drifting apart again. */
  --t-title-sm: var(--t-h4);  /* product card name, PDP price */
  --t-title-xs: 17px;      /* bag line title */
  --lh-tight: 1.14;
  --lh-body: 1.7;
  --lh-app: 1.55;
  /* 0.34em was wide enough that a five-letter overline read as five separate
     letters. Couture tracking sits nearer 0.2em: still unmistakably an
     overline, still legible as a word. */
  /* NOTHING that carries words may be set below --t-eyebrow (11.5px).
     .lx-card-badge was 10px and .lx-card-brand 10.5px — and the brand is the
     first word a shopper reads on a product card. Contrast is guarded by
     scripts/check-contrast.mjs; size is guarded by scripts/check-type-scale.mjs.
     Numerals inside a fixed circle (.lx-bag-count) are geometry, not prose,
     and are exempt. */
  --track-eyebrow: 0.2em;    /* overline / eyebrow letter-spacing */
  --track-label: 0.12em;
  --track-button: 0.1em;     /* uppercase control labels */

  /* ---- SPACING (4px base) ----------------------------------------------- */
  --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px; --s-5: 20px;
  --s-6: 24px; --s-7: 32px; --s-8: 40px; --s-9: 56px; --s-10: 80px;
  --gutter: clamp(20px, 5vw, 72px);      /* page side padding */
  /* Section rhythm. Measured on the live homepage before this change: every
     section resolved to 109px of padding top AND bottom, so any two
     neighbours were separated by 218px of nothing, and the page stood
     11,243px tall at laptop width. Premium reads as deliberate space, not as
     a section that ran out of content.

     The scale is now 40px on a phone, ~76px on a laptop and 84px at the top
     end — the "major section" band of the spacing system, rather than half a
     viewport. Small and normal spacing are the --s-* steps below. */
  --section-y: clamp(40px, 5.6vw, 84px);
  /* A product grid reads as merchandise when the pieces have air between them
     and as a spreadsheet when they do not. */
  --card-gap: clamp(14px, 2.2vw, 34px);  /* product grid gap */
  --maxw: 1400px;                        /* editorial max width */
  --maxw-app: 1180px;                    /* member tools max width */
  --maxw-prose: 720px;

  /* ---- RADIUS -----------------------------------------------------------
     Rounding is the loudest signal a storefront sends about what it is. Pills
     and 12px cards read as software; a house reads as paper, plate and edge.
     Everything is square or nearly so, and --r-pill survives only for things
     that are genuinely circular (the bag count, a status dot).
     Before: 4 / 8 / 12 / 18px. */
  --r-xs: 0px; --r-sm: 0px; --r: 1px; --r-lg: 2px; --r-pill: 999px;

  /* ---- CONTROL GEOMETRY -------------------------------------------------
     A 48px control with a tracked uppercase label carries more authority than
     a 44px pill, and still clears the 44px touch floor. */
  --ctl-h: 48px;        /* buttons, inputs, selects */
  --ctl-h-sm: 36px;     /* chips, compact controls */
  --ctl-px: 28px;
  --ctl-px-sm: 16px;
  --icon: 18px;         /* standard icon box */
  --icon-sm: 15px;
  --icon-lg: 22px;
  --stroke: 1.7;        /* one icon stroke weight sitewide */
  --tap: 44px;          /* minimum touch target */

  /* ---- MOTION ----------------------------------------------------------- */
  --ease: cubic-bezier(0.22, 0.61, 0.18, 1);
  --dur: .25s;
  --dur-fast: .16s;

  /* ---- BREAKPOINTS (documented; CSS can't use vars in media queries) -----
     mobile  <= 640px · tablet <= 980px · desktop > 980px · wide > 1280px  */
  --bp-mobile: 640px; --bp-tablet: 980px; --bp-wide: 1280px;
}

@media (prefers-reduced-motion: reduce) {
  :root { --dur: 0s; --dur-fast: 0s; }
}
