/* GENERATED — do not edit. Source: frontend/src/styles/tokens.css
   Regenerate with landing/sync-tokens.sh */
/* ============================================================
   CLASPEX — DESIGN TOKENS
   v0.3 · 8 August 2026

   Derived from Brand Book Amendment v0.3 (colour + surface).
   STATUS: the palette is [Proposed] — not yet signed off by the
   business owner. Expect layer 2 to change. That is the point
   of layer 2.

   HOW TO USE
   - Components reference LAYER 2 only (--color-*, --space-*, etc).
   - Never reference layer 1 (--indigo-700, --blue-500) in a
     component. Never write a raw hex in a component. If you find
     yourself needing a colour that has no semantic token, the
     token is missing — add it here, don't inline it.
   - Load once, globally. In angular.json -> styles, or an
     @import at the top of styles.css. Not per-component.
   - These are CSS custom properties, not SCSS variables, so they
     stay live at runtime. That is what makes theming, dark mode
     and the .on-dark scope below possible.
   ============================================================ */


/* ============================================================
   LAYER 1 — PRIMITIVES
   What the colour IS. Never referenced by components.
   ============================================================ */

:root {

  /* --- Indigo: ink and dark surfaces -------------------- */
  --indigo-900: #101A2E;
  --indigo-800: #141F36;
  --indigo-700: #1C2B4A;   /* brand primary */
  --indigo-500: #2E4370;
  --indigo-300: #7386A8;

  /* --- Signal blue: interactive ------------------------- */
  --blue-700:   #1E42C4;
  --blue-600:   #2549D9;
  --blue-500:   #2E5BFF;
  --blue-200:   #C7D6FF;
  --blue-100:   #E4EBFF;
  --blue-text:  #2444B8;

  /* --- Cool neutrals ------------------------------------ */
  --white:        #FFFFFF;
  --neutral-25:   #FAFBFC;
  --neutral-50:   #F7F8FA;
  --neutral-100:  #EFF1F4;
  --neutral-200:  #DDE1E6;
  --neutral-300:  #C4CAD2;
  --neutral-400:  #B6BCC6;
  --neutral-500:  #8A93A0;
  --neutral-600:  #5F6B7A;

  /* --- Status ------------------------------------------- */
  --green-600:  #0E8A5F;
  --green-text: #0E6B45;
  --green-bg:   #D8F0E4;

  --amber-600:  #B07A18;
  --amber-text: #8A5E12;
  --amber-bg:   #FDECCB;

  --red-600:    #B3261E;
  --red-text:   #932018;
  --red-bg:     #FBE4E2;

  /* --- Brand-only --------------------------------------- */
  /* selvedge is LOGO AND PRINT ONLY. It is deliberately not
     mapped to any semantic token below. If it appears in a UI
     screen, that is a bug. */
  --selvedge:   #B4232A;
  --chalk:      #8FA9BC;   /* secondary text on dark bands only */

}


/* ============================================================
   LAYER 2 — SEMANTIC
   What the colour MEANS. This is the only layer components touch.
   ============================================================ */

:root {

  /* --- Text --------------------------------------------- */
  --color-text-primary:    var(--indigo-700);
  --color-text-secondary:  var(--neutral-600);
  --color-text-muted:      var(--neutral-500);   /* 3.11:1 — hints
                                                    and placeholders
                                                    ONLY, never body */
  --color-text-disabled:   var(--neutral-400);
  --color-text-inverse:    var(--white);

  /* --- Surfaces ----------------------------------------- */
  --color-surface-page:    var(--neutral-50);    /* page background */
  --color-surface-raised:  var(--neutral-25);    /* hover rows */
  --color-surface-card:    var(--white);         /* cards, tables */
  --color-surface-sunken:  var(--neutral-100);   /* table headers */
  --color-surface-dark:    var(--indigo-800);    /* inverted bands */
  --color-surface-darkest: var(--indigo-900);    /* footer */

  /* --- Borders ------------------------------------------ */
  --color-border:          var(--neutral-200);
  --color-border-strong:   var(--neutral-300);
  --color-border-dark:     var(--indigo-500);    /* on dark surfaces */

  /* --- Interactive -------------------------------------- */
  /* One accent per view. At most one filled action button on
     screen at a time. */
  --color-action:          var(--blue-500);
  --color-action-hover:    var(--blue-600);
  --color-action-pressed:  var(--blue-700);
  --color-action-subtle:   var(--blue-100);      /* selected rows */
  --color-action-border:   var(--blue-200);
  --color-on-action:       var(--white);
  --color-on-subtle:       var(--blue-text);
  --color-focus-ring:      var(--blue-500);

  /* --- Product states ----------------------------------- */
  /* Green means VERIFIED / HELD / PAID — not "good". */
  --color-verified:        var(--green-600);
  --color-verified-bg:     var(--green-bg);
  --color-on-verified:     var(--green-text);

  --color-pending:         var(--amber-600);
  --color-pending-bg:      var(--amber-bg);
  --color-on-pending:      var(--amber-text);

  --color-danger:          var(--red-600);
  --color-danger-bg:       var(--red-bg);
  --color-on-danger:       var(--red-text);

  --color-info:            var(--blue-500);
  --color-info-bg:         var(--blue-100);
  --color-on-info:         var(--blue-text);


  /* --- Typography --------------------------------------- */
  --font-sans: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont,
               'Segoe UI', Roboto, sans-serif;
  /* Mono is not decorative. Every number, price, request code,
     size quantity, SAM value and eyebrow label uses it. */
  --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular,
               Menlo, monospace;

  --weight-regular: 400;
  --weight-medium:  500;
  --weight-bold:    600;

  --text-display-l:  40px;
  --text-display-s:  24px;
  --text-title:      17px;
  --text-body:       16px;
  --text-label:      13px;
  --text-eyebrow:    11px;

  --leading-display-l: 1.05;
  --leading-display-s: 1.15;
  --leading-title:     1.35;
  --leading-body:      1.6;
  --leading-label:     1.4;
  --leading-eyebrow:   1.2;

  --tracking-eyebrow:  0.16em;
  --tracking-tight:    -0.01em;
  /* The logo's own tracking, -15/1000. Not interchangeable with
     --tracking-tight: this one is a brand constant and must not
     drift if the type scale is retuned. */
  --tracking-wordmark: -0.015em;


  /* --- Spacing (4px base scale) ------------------------- */
  --space-1:  4px;
  --space-2:  8px;
  --space-3:  12px;
  --space-4:  16px;
  --space-5:  24px;
  --space-6:  32px;
  --space-7:  48px;
  --space-8:  72px;


  /* --- Shape -------------------------------------------- */
  /* [Open] 2px (v0.2) vs 4px (v0.3 proposal). Change here only. */
  --radius:       4px;
  --radius-sm:    2px;
  --radius-pill:  999px;
  --radius-none:  0;

  --border-width: 1px;


  /* --- Elevation ---------------------------------------- */
  /* No shadows, no gradients. Carried forward from v0.2 and
     unaffected by the tech-register override. Depth is
     expressed with surface steps and hairlines. */
  --shadow-none: none;
  --focus-shadow: 0 0 0 3px var(--blue-100);


  /* --- Layout ------------------------------------------- */
  --page-max:        1200px;   /* brand + admin content column */
  --page-gutter:     120px;
  --worker-column:   680px;    /* narrow column, eases mobile port */
  --sidebar-width:   240px;    /* brand + admin left nav (UI-SPEC) */
  --control-height:  40px;

  /* Logo icon height. Every other lockup measurement is derived
     from it, per logo/README.md: the icon-to-wordmark gap is a
     third of it, the wordmark is two thirds of it, and clearspace
     on all four sides is half of it. Change this one value and the
     lockup rescales without losing its proportions.

     28px is a floor, not a preference. The rendered lockup measures
     3.68x the icon height, so 28px yields 103px — clear of the 96px
     minimum in logo/README.md. 24px yields 88px and breaks the rule.
     (Do not size this from the lockup SVG's 292x72 canvas: that
     canvas assumes a 196-unit wordmark advance and the real advance
     in Plex Medium at -15/1000 is ~170, so it over-reads by 27
     units. See the note in landing.css.) */
  --lockup-icon:     28px;


  /* --- Motion ------------------------------------------- */
  /* Motion is held to the same discipline as shadow: it has to
     be doing a job. The rules, in the same spirit as "no
     shadows, no gradients":

     - Motion either confirms an action or shows where something
       came from. Nothing moves to be noticed.
     - Only transform and opacity are animated. Never height,
       width, top or left — they force layout on every frame.
       Colour is the one exception; it is cheap and it is how a
       hover state reads.
     - Nothing exceeds --duration-slow. A landing page is not a
       showreel and an admin table is used all day.
     - Status never animates. A pill that fades from amber to
       green misreports when the change happened. It swaps.
     - Numbers never count up. Mono with tabular-nums exists so
       figures are read, not watched.
     - Every rule here is overridden by the reduced-motion block
       at the foot of this file. That block is not optional. */

  --duration-instant: 80ms;    /* press feedback */
  --duration-fast:    120ms;   /* hover, focus, colour swaps */
  --duration-base:    200ms;   /* small surfaces entering */
  --duration-slow:    320ms;   /* section reveal, longer travel */

  --ease-out:    cubic-bezier(0.2, 0, 0, 1);      /* arriving */
  --ease-in:     cubic-bezier(0.4, 0, 1, 1);      /* leaving */
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);    /* moving in place */

  /* Travel distance for anything entering. Small on purpose —
     the eye should register direction, not distance. */
  --motion-rise:    8px;
  --motion-press:   1px;    /* button nudge on :active */
  --motion-stagger: 45ms;   /* delay step between siblings entering */

}


/* ============================================================
   DARK BAND SCOPE
   For inverted sections — the maker-recruitment band, the
   footer, and any dark panel. Re-scopes the semantic layer
   rather than adding a parallel set of tokens.

   Usage:  <section class="on-dark"> ... </section>
   Everything inside keeps using --color-text-primary and
   resolves correctly. This is what layer 2 buys you.
   ============================================================ */

.on-dark {
  --color-text-primary:   var(--white);
  --color-text-secondary: var(--chalk);
  --color-text-muted:     var(--indigo-300);

  --color-surface-page:   var(--indigo-800);
  --color-surface-card:   var(--indigo-700);
  --color-surface-raised: var(--indigo-700);
  --color-surface-sunken: var(--indigo-900);

  --color-border:         var(--indigo-500);
  --color-border-strong:  var(--indigo-300);

  background: var(--color-surface-page);
  color: var(--color-text-primary);
}


/* ============================================================
   BASE
   Minimal. Everything else belongs in components.
   ============================================================ */

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

html {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  margin: 0;
  background: var(--color-surface-page);
  color: var(--color-text-primary);
  font-family: var(--font-sans);
  font-size: var(--text-body);
  font-weight: var(--weight-regular);
  line-height: var(--leading-body);
}

/* Numerals never reflow in tables. Applies to every price,
   quantity and code in the product. */
.mono,
[data-mono] {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
  box-shadow: var(--focus-shadow);
}

/* Not a nicety. Vestibular disorders are real and this costs us
   nothing — every animation in the product is confirmation or
   orientation, so removing it loses no information.

   Durations are zeroed rather than set to `none` so that
   transitionend/animationend listeners still fire and no state
   machine stalls waiting for a callback that never arrives.
   Delay is zeroed too, or a staggered reveal would still take
   half a second to finish appearing. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }
}
