/* ============================================================================
   DEXPACE — DESIGN TOKENS
   ----------------------------------------------------------------------------
   Source of truth: Figma `DEXPACE` — ycUPkTIhfWmRUfFe7Eg2Ty, page `UI kit`.
   Colour ramps, type styles, gap/radius tokens and the button spec were read
   out of that file, not invented here. Site-only additions are marked EXTENDS.

   Three layers, one source of truth per layer:
       RAW  ->  PRIMITIVE (--base-*, --size-*, --font-*)  ->  SEMANTIC (--color-*)
                mode-invariant                                flips with the theme

   Two hard rules:
     1. A semantic token is ALWAYS an alias to a primitive, never a new value.
        Need a shade that is not on a ramp? Add the ramp step first, or derive
        it with color-mix() FROM a token. No loose hex anywhere below layer 1.
     2. Components bind to SEMANTIC tokens only. A primitive inside a component
        is the same mistake as a hardcoded hex.

   Project rules inherited from the DEX developer review:
     - border-radius never exceeds 12px anywhere in the product;
     - primary CTA default is the brand fill, not white;
     - header horizontal padding is 40px.

   Contrast: every pair below was measured, not eyeballed. Ratios are in the
   comments. AA body text needs 4.5:1, large text and UI bounds need 3:1.
   ============================================================================ */

/* ============================================================================
   LAYER 1 - PRIMITIVES.  Mode-invariant: identical in light and dark.
   ============================================================================ */

:root {
  /* --- Colour ramps, straight from Figma Variables ------------------------ */

  /* Brand. Figma `Brand/*`; Brand/500 is the alias `Color/Accent/100` #7cb500. */
  --base-brand-50:  #f2f8e6;
  --base-brand-100: #d6e8b0;
  --base-brand-200: #c3dd8a;
  --base-brand-300: #a7cd54;
  --base-brand-400: #96c433;
  --base-brand-500: #7cb500;   /* the brand colour */
  --base-brand-600: #71a500;
  --base-brand-700: #588100;
  --base-brand-750: #527900;   /* EXTENDS: clearer light-theme text, 4.66:1 on #f4f4f2 */
  --base-brand-800: #446400;
  --base-brand-900: #344c00;

  /* Neutral. Figma `Base/*`. Note the extra 550 step - it is Figma's own. */
  --base-neutral-50:  #fcfcfc;
  --base-neutral-100: #e9e9e9;
  --base-neutral-200: #bbbbbb;
  --base-neutral-300: #9b9b9b;
  --base-neutral-400: #6d6d6d;
  --base-neutral-500: #515151;
  --base-neutral-550: #393939;
  --base-neutral-600: #252525;
  --base-neutral-700: #222222;
  --base-neutral-800: #1a1a1a;
  --base-neutral-900: #141414;

  /* Signals. Figma `Red/*`, `Orange/*`, `Blue/*`.
     There is no success ramp in Figma on purpose - green already means go,
     so success aliases the brand ramp in the semantic layer below. */
  --base-signal-error-50:  #fce6e6;
  --base-signal-error-300: #ea5454;
  --base-signal-error-500: #df0000;
  --base-signal-error-600: #cb0000;
  --base-signal-error-700: #9e0000;
  --base-signal-error-800: #7b0000;

  --base-signal-warning-50:  #faf1e6;
  --base-signal-warning-300: #dfa154;
  --base-signal-warning-400: #d98e33;
  --base-signal-warning-500: #cf7200;
  --base-signal-warning-700: #935100;
  --base-signal-warning-800: #723f00;

  --base-signal-info-50:  #e6f2f8;
  --base-signal-info-300: #54a7cd;
  --base-signal-info-500: #007cb5;   /* #7cb500 with the channels swapped */
  --base-signal-info-600: #0071a5;
  --base-signal-info-700: #005881;
  --base-signal-info-800: #004464;

  /* --- One size scale. Spacing, radius, border width and sizing all alias
         into it, so re-tuning the grid is a single-file change.
         Every step is RIGID on purpose: a control height or an inner padding
         that breathes makes a button look different on a tablet than on a
         laptop. The only things allowed to breathe are section rhythm and the
         page margin, and they are separate tokens below. ------------------ */
  --size-0:   0;
  --size-1:   0.0625rem;   /* 1px  - hairline */
  --size-2:   0.125rem;    /* 2px  */
  --size-4:   0.25rem;
  --size-6:   0.375rem;
  --size-8:   0.5rem;      /* Figma Gap/8  */
  --size-10:  0.625rem;
  --size-12:  0.75rem;     /* Figma Gap/12 */
  --size-14:  0.875rem;
  --size-16:  1rem;
  --size-20:  1.25rem;     /* Figma Gap/20 */
  --size-24:  1.5rem;
  --size-28:  1.75rem;
  --size-32:  2rem;
  --size-36:  2.25rem;     /* Figma button S */
  --size-40:  2.5rem;      /* Figma button M; header horizontal padding */
  --size-44:  2.75rem;     /* minimum tap target */
  --size-48:  3rem;
  --size-56:  3.5rem;      /* Figma button L */
  --size-64:  4rem;
  --size-80:  5rem;
  --size-96:  6rem;
  --size-128: 8rem;
  --size-160: 10rem;
  --size-192: 12rem;

  /* --- Section rhythm. The one family that is fluid, declared inside the
         token so no section ever restates its padding in a media query.
         Unit is vi, not vw: unaffected by a scrollbar.
         Ratios follow resend.com, where dense grid sections (899-967px tall)
         alternate with airy ones (1296-1367px). ---------------------------- */
  --space-section-sm: clamp(2.5rem, 1.8785rem + 2.6519vi, 4rem);    /* 40 -> 64  */
  --space-section-md: clamp(3.5rem, 2.4641rem + 4.4199vi, 6rem);    /* 56 -> 96  */
  --space-section-lg: clamp(4.5rem, 3.0497rem + 6.1878vi, 8rem);    /* 72 -> 128 */
  --space-section-xl: clamp(5.5rem, 3.6354rem + 7.9558vi, 10rem);   /* 88 -> 160 */

  /* --- Radius. Aliases into the size scale. The 12px ceiling is a project
         rule, so there is deliberately no 2xl/3xl step. ------------------- */
  --radius-none:    var(--size-0);
  --radius-sm:      var(--size-2);
  --radius-default: var(--size-4);
  --radius-md:      var(--size-6);
  --radius-lg:      var(--size-8);
  --radius-xl:      var(--size-12);   /* Figma `Corner radius/12` - the ceiling */
  --radius-full:    999px;            /* circles only: dots, avatars, bullets */

  /* --- Border width ------------------------------------------------------- */
  --border-width-hairline: 0.5px;     /* 21st.dev grid language, decorative only */
  --border-width-thin:     var(--size-1);
  --border-width-medium:   var(--size-2);
  --border-width-thick:    var(--size-4);

  /* --- Type primitives ---------------------------------------------------- */

  /* Families. Three roles, one more than the usual two, and it is justified:
     Quantico is the brand's own display face (it draws the DEXPACE wordmark),
     Manrope is Figma `Plain/Font`, and the mono carries the engineering voice
     that this audience reads as precision. */
  --font-family-display: 'Quantico', 'Manrope', system-ui, sans-serif;
  --font-family-text:    'Manrope', system-ui, -apple-system, sans-serif;
  --font-family-code:    'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  /* Sizes. Nine steps. The 24 -> 48 gap is deliberate, the same move resend.com
     makes at 24 -> 56: no mid-sized headings exist, so hierarchy never blurs.
     EXTENDS Figma: 12/14/16/18/20/48 are its MH ladder and `subtitle L`;
     24, 56 and 96 are added for the site, as steps of the same progression. */
  --font-size-xs:  0.75rem;    /* 12 - Figma MH6 */
  --font-size-sm:  0.875rem;   /* 14 - Figma MH5 */
  --font-size-base:1rem;       /* 16 - Figma MH4 */
  --font-size-md:  1.125rem;   /* 18 - Figma `Plain/subtitle L` */
  --font-size-lg:  1.25rem;    /* 20 - Figma MH2 / QH2 */
  --font-size-xl:  1.5rem;     /* 24 - EXTENDS */
  --font-size-2xl: clamp(1.75rem, 1.232rem + 2.2099vi, 3rem);    /* 28 -> 48, Figma MH1 / QH1 */
  --font-size-3xl: clamp(2rem, 1.3785rem + 2.6519vi, 3.5rem);    /* 32 -> 56, EXTENDS */
  --font-size-4xl: clamp(2.5rem, 1.0497rem + 6.1878vi, 6rem);    /* 40 -> 96, EXTENDS */

  /* Line heights. Two registers with nothing in between, per the taste library:
     headings 0.92-1.2, prose 1.6. Labels keep Figma's 1.2. */
  --line-height-display: 0.92;
  --line-height-heading: 1.0;
  --line-height-tight:   1.2;    /* Figma's ladder value, labels and MH styles */
  --line-height-snug:    1.35;
  --line-height-prose:   1.6;

  /* Weights. Manrope ships 400..700 variable. Quantico ships 400 and 700 ONLY -
     never ask it for 500 or 600, the browser will synthesise and it looks wrong. */
  --font-weight-regular:  400;
  --font-weight-medium:   500;
  --font-weight-semibold: 600;   /* Figma `Plain/Weight-semibold`, the workhorse */
  --font-weight-bold:     700;

  /* Letter spacing. Tracking tightens as the size grows, and stays slightly
     negative even at body size - measured on resend.com (-5% at 56px) and
     powder.framer.website (-1% at 16px, -2% at 14px, -11% at 144px).
     Body tracking at exactly 0 is what makes a page read as untouched. */
  --letter-spacing-display: -0.06em;   /* 96px */
  --letter-spacing-tight:   -0.05em;   /* 56px - resend measures -2.8px at 56 */
  --letter-spacing-snug:    -0.03em;   /* 48px */
  --letter-spacing-normal:  -0.01em;   /* body */
  --letter-spacing-label:   0.011em;   /* Figma `subtitle L` tracking, +0.2px at 18px */
  --letter-spacing-wide:    0.05em;    /* mono labels in caps */

  /* --- Motion. Deliberately scarce: this site is read by partners, banks and
         regulators, so nothing moves except a single quiet entrance.
         Curves are chosen by PROPERTY, not by component - opacity cannot
         physically overshoot, geometry can. ------------------------------- */
  --duration-fast: 150ms;   /* hover, focus, theme switch */
  --duration-base: 500ms;   /* the one entrance */
  --ease-motion:   cubic-bezier(0.16, 1, 0.3, 1);   /* translate, scale */
  --ease-opacity:  cubic-bezier(0.4, 0, 0.2, 1);    /* opacity, colour */

  /* --- Z ladder, step 100. No bare 9999 anywhere. ------------------------- */
  --z-base:      0;
  --z-sticky:    200;
  --z-overlay:   300;
  --z-modal:     400;
  --z-toast:     500;
  --z-skip-link: 900;   /* must sit above everything - accessibility */

  /* --- Icons. Outline only; filled action icons read as AI slop. ---------- */
  --icon-size-sm: var(--size-16);
  --icon-size-md: var(--size-20);   /* the size the Figma button uses */
  --icon-size-lg: var(--size-24);
  --icon-size-xl: var(--size-32);
  --icon-stroke:  1.5;

  /* --- Grid. Locked with Tiko: the working grid is 1280 inside a 1440 frame. */
  --grid-max:     80rem;   /* 1280px */
  --grid-columns: 12;
  --grid-gutter:  var(--size-16);
  --grid-margin:  clamp(1.25rem, 0.732rem + 2.2099vi, 2.5rem);   /* 20 -> 40 */
  /* One formula for the page gutter: content is centred at 1280 and keeps its
     margin below that width, so no component needs its own breakpoint. */
  --page-gutter:  max(var(--grid-margin), calc((100vw - var(--grid-max)) / 2 + var(--grid-margin)));

  /* --- Focus ring. One composite token for the whole system, so focus is
         never left dissolved inside hover styles. ------------------------- */
  --focus-ring-width:  var(--size-2);
  --focus-ring-offset: var(--size-2);
}

/* ============================================================================
   LAYER 2 - SEMANTICS.  Declared twice; light is the fallback for a document
   with no data-theme attribute. Every variant page carries both themes; only
   the DEFAULT differs, and each page sets that on <html data-theme>.

   The rule that runs through this whole layer: THE ACCENT CHANGES RAMP STEP
   BETWEEN THEMES. Brand/500 is 7.02:1 on the dark ground but only 2.42:1 on
   the light one - using one green for both would fail AA on light. The fill
   colour does not flip (a brand must stay recognisable), the TEXT colour does.
   ============================================================================ */

:root,
[data-theme='light'] {
  color-scheme: light;

  /* Backgrounds */
  --color-bg-page:            var(--base-neutral-50);    /* #fcfcfc */
  --color-bg-surface:         #ffffff;
  --color-bg-surface-raised:  var(--base-neutral-100);
  --color-bg-subtle:          color-mix(in srgb, var(--base-neutral-900) 4%, var(--color-bg-page));

  /* Accent fills. Brand/500 in BOTH themes - the brand does not invert. */
  --color-bg-accent:          var(--base-brand-500);
  --color-bg-accent-hover:    var(--base-brand-400);
  --color-bg-accent-pressed:  var(--base-brand-600);
  --color-bg-accent-disabled: color-mix(in srgb, var(--base-brand-500) 32%, var(--color-bg-page));
  --color-bg-accent-subtle:   color-mix(in srgb, var(--base-brand-500) 10%, var(--color-bg-page));

  /* Content */
  --color-content-primary:       var(--base-neutral-900);  /* 17.96:1 */
  --color-content-subtle:        var(--base-neutral-500);  /*  7.74:1 */
  --color-content-muted:         var(--base-neutral-400);  /*  5.04:1 */
  --color-content-disabled:      var(--base-neutral-300);  /*  2.71:1 - non-text only */
  --color-content-accent:        var(--base-brand-750);    /*  5.13:1 on white; clearer than Brand/800 */
  --color-content-accent-strong: var(--base-brand-900);    /*  9.39:1 */
  --color-content-on-accent:     var(--base-neutral-800);  /*  7.02:1 on the brand fill */
  --color-content-inverse:       var(--base-neutral-50);

  /* Borders. `bearing` is the one that carries meaning - a diagram connector,
     a table rule - and must clear 3:1. `subtle` is decoration and may be faint. */
  --color-border-subtle:  var(--base-neutral-100);
  --color-border-strong:  var(--base-neutral-200);
  --color-border-bearing: var(--base-neutral-500);   /* 7.74:1 */
  --color-border-accent:  var(--base-brand-500);

  /* Signals */
  --color-content-danger:   var(--base-signal-error-600);    /* 5.78:1 */
  --color-content-warning:  var(--base-signal-warning-700);  /* 5.99:1 */
  --color-content-info:     var(--base-signal-info-600);     /* 5.24:1 */
  --color-content-success:  var(--base-brand-750);           /* 5.13:1 - green already means go */
  --color-bg-danger-subtle:  var(--base-signal-error-50);
  --color-bg-warning-subtle: var(--base-signal-warning-50);
  --color-bg-info-subtle:    var(--base-signal-info-50);
  --color-bg-success-subtle: var(--base-brand-50);

  /* Focus + overlay */
  --color-focus-ring: var(--base-brand-750);
  --color-overlay:    color-mix(in srgb, var(--base-neutral-900) 45%, transparent);

  /* The logo mark keeps the brand green in both themes; only the wordmark
     follows the text colour. */
  --logo-mark: var(--base-brand-500);
}

[data-theme='dark'] {
  color-scheme: dark;

  --color-bg-page:            var(--base-neutral-800);   /* #1a1a1a - the product's ground */
  --color-bg-surface:         var(--base-neutral-700);
  --color-bg-surface-raised:  var(--base-neutral-600);
  --color-bg-subtle:          color-mix(in srgb, var(--base-neutral-50) 4%, var(--color-bg-page));

  --color-bg-accent:          var(--base-brand-500);
  --color-bg-accent-hover:    var(--base-brand-400);
  --color-bg-accent-pressed:  var(--base-brand-600);
  --color-bg-accent-disabled: color-mix(in srgb, var(--base-brand-500) 28%, var(--color-bg-page));
  --color-bg-accent-subtle:   color-mix(in srgb, var(--base-brand-500) 14%, var(--color-bg-page));

  --color-content-primary:       var(--base-neutral-50);   /* 16.96:1 */
  --color-content-subtle:        var(--base-neutral-200);  /*  9.07:1 */
  --color-content-muted:         var(--base-neutral-300);  /*  6.26:1 */
  --color-content-disabled:      var(--base-neutral-400);  /*  3.36:1 - non-text only */
  --color-content-accent:        var(--base-brand-500);    /*  7.02:1  <- the brand itself */
  --color-content-accent-strong: var(--base-brand-400);    /*  8.49:1 */
  --color-content-on-accent:     var(--base-neutral-800);  /*  7.02:1 - same as light */
  --color-content-inverse:       var(--base-neutral-900);

  /* Watch this one. On #1a1a1a NO neutral step between 500 and 700 reaches 3:1
     (they measure 2.19 / 1.51 / 1.14), so a meaningful line has to jump all the
     way to Base/300. Base/600 stays available for decoration only. */
  --color-border-subtle:  var(--base-neutral-600);
  --color-border-strong:  var(--base-neutral-550);
  --color-border-bearing: var(--base-neutral-300);   /* 6.26:1 */
  --color-border-accent:  var(--base-brand-500);

  --color-content-danger:   var(--base-signal-error-300);    /* 4.89:1 */
  --color-content-warning:  var(--base-signal-warning-400);  /* 6.52:1 */
  --color-content-info:     var(--base-signal-info-300);     /* 6.45:1 */
  --color-content-success:  var(--base-brand-500);           /* 7.02:1 */
  --color-bg-danger-subtle:  color-mix(in srgb, var(--base-signal-error-500) 18%, var(--color-bg-page));
  --color-bg-warning-subtle: color-mix(in srgb, var(--base-signal-warning-500) 18%, var(--color-bg-page));
  --color-bg-info-subtle:    color-mix(in srgb, var(--base-signal-info-500) 18%, var(--color-bg-page));
  --color-bg-success-subtle: color-mix(in srgb, var(--base-brand-500) 16%, var(--color-bg-page));

  --color-focus-ring: var(--base-brand-400);
  --color-overlay:    color-mix(in srgb, #000000 60%, transparent);

  --logo-mark: var(--base-brand-500);
}

/* ============================================================================
   COMPONENT SEMANTICS - the button, mirroring the Figma component set
   Size L 56 / M 40 / S 36  x  Type Primary / Outline / Natural / Text
   x  State Default / Hovered / Focused / Pressed / Disabled.
   Values read from node 962:3963.
   ============================================================================ */

:root {
  --size-control-lg: var(--size-56);   /* 56 - Figma L */
  --size-control-md: var(--size-40);   /* 40 - Figma M */
  --size-control-sm: var(--size-36);   /* 36 - Figma S */

  --space-padding-button-inline: var(--size-20);   /* Figma Gap/20 */
  --space-padding-button-block:  var(--size-12);   /* Figma Gap/12 */
  --space-gap-button:            var(--size-8);    /* Figma Gap/8  */

  --font-size-button:          var(--font-size-md);        /* 18 */
  --line-height-button:        1.333;                      /* 24 / 18 */
  --font-weight-button:        var(--font-weight-semibold);
  --letter-spacing-button:     var(--letter-spacing-label);
}

/* Radii are the main knob the three site variants turn, so they are declared as
   role tokens here and overridden per variant, exactly once, in the page file:
       variant 1 "Ledger"  - card 0,  button 4   (sharp, institutional)
       variant 2 "Network" - card 12, button 12  (matches the DEX product)
       variant 3 "Grid"    - card 0,  button 0   (swiss)
   Nothing else about a variant's colour or type lives in this file. */
:root {
  --radius-button: var(--radius-xl);
  --radius-chip:   var(--radius-lg);
  --radius-card:   var(--radius-xl);
  --radius-frame:  var(--radius-xl);
}
