/* ============================================================
   sykloo : design tokens
   ------------------------------------------------------------
   Calm underneath the noise. Data is the protagonist.
   80% neutrals · 15% data · 5% signal.
   ============================================================ */

/* ---------- Fonts ---------- */

/* Inter : variable font, every weight 100-900, latin + latin-ext + cyrillic
   + greek + vietnamese (full unicode coverage from upstream rsms/inter).
   The lander renders 400/500/600; the variable file carries the full axis. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("./fonts/InterVariable.woff2") format("woff2-variations"),
       url("./fonts/InterVariable.woff2") format("woff2");
  font-variation-settings: "opsz" 14;
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("./fonts/PlexMono-400.woff2") format("woff2");
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("./fonts/PlexMono-500.woff2") format("woff2");
}

:root {
  /* ----------------------------------------------------------
     COLOR : core neutrals (80% of any surface)
     ---------------------------------------------------------- */
  --carbon:        #0B0E13;   /* app canvas, dark */
  --slate:         #1A1F28;   /* cards, panels */
  --slate-2:       #232934;   /* hover / raised card */
  --slate-line:    #2A3140;   /* hairline borders on dark */
  --graphite:      #8A8D94;   /* secondary text */
  --graphite-2:    #5C616B;   /* tertiary text / disabled */
  --chalk:         #F5F4EF;   /* light mode canvas */
  --chalk-2:       #ECEAE2;   /* hover / raised card on light */
  --chalk-line:    #DEDBD1;   /* hairline borders on light */

  /* ----------------------------------------------------------
     COLOR : signal · "Maillot Gold" (the one ownable accent)
     ------------------------------------------------------------
     A TWO-SHADE accent resolved per theme: the BRIGHT shade rides
     on the dark product canvas; the DEEP shade rides on light
     (deck / press / print) surfaces. Components just consume
     --signal / --signal-ink / --signal-700 : the active theme
     swaps in the right shade automatically. No rule to remember,
     no exception: both shades clear WCAG AA as text AND as a
     button fill in their own context (gold on carbon ≈ 11.6:1;
     deep gold on chalk ≈ 7.0:1; chalk on deep-gold fill ≈ 7.7:1).
     Still <5% surface area · one CTA per view · one accent number.
     Heritage: the maillot jaune : yellow is the leader in cycling.
     ---------------------------------------------------------- */
  --gold-bright:     #FFC233;   /* accent on DARK surfaces */
  --gold-bright-700: #EBA90F;   /* hover / pressed on dark */
  --gold-deep:       #8A6500;   /* accent on LIGHT surfaces · "Antique Gold" */
  --gold-deep-700:   #6E4D00;   /* hover / pressed on light */

  /* Theme-resolved aliases : these are the DARK defaults (this
     :root IS the dark theme); [data-theme="light"] overrides them. */
  --signal:        var(--gold-bright);
  --signal-700:    var(--gold-bright-700);          /* hover / pressed */
  --signal-100:    rgba(255, 194, 51, 0.16);        /* gold wash · badge / tint bg */
  --signal-ink:    var(--carbon);                   /* text/icons ON a signal fill */

  /* ----------------------------------------------------------
     COLOR : data palette (charts, dashboards, series)
     Never used for UI chrome.
     ---------------------------------------------------------- */
  --data-cobalt:   #4C8DFF;   /* Series 1 */
  --data-aqua:     #2DD4BF;   /* Series 2 */
  --data-violet:   #B36AE2;   /* Series 3 */
  --data-ember:    #FF8A4C;   /* Series 4 */
  --data-bronze:   #E8B83C;   /* Series 5 */

  /* ----------------------------------------------------------
     COLOR : semantic / system feedback
     ---------------------------------------------------------- */
  --success:       #22C55E;
  --warning:       #F59E0B;
  --danger:        #EF4444;
  --info:          #38BDF8;

  /* ----------------------------------------------------------
     CYCLING SEMANTIC : concept → color
     Each cycling concept gets a fixed mapping that never
     changes across product, marketing or print. Use these
     instead of reaching for --data-* directly. --data-* is the
     raw palette for charts; these are the semantic layer
     consumed by components.
     ---------------------------------------------------------- */

  /* Training & HR zones : 5-band, cool → hot.
     Maps directly to Coggan power zones and matched HR zones. */
  --zone-1: var(--graphite);     /* Z1 · Recovery */
  --zone-2: var(--data-cobalt);  /* Z2 · Endurance */
  --zone-3: var(--data-aqua);    /* Z3 · Tempo */
  --zone-4: var(--data-bronze);  /* Z4 · Threshold */
  --zone-5: var(--data-ember);   /* Z5 · VO₂ · anaerobic */

  /* Rider load / form state */
  --state-in-form:      var(--success);   /* on-plan, no flags */
  --state-building:     var(--info);      /* ramping load */
  --state-load-risk:    var(--warning);   /* watch */
  --state-overtraining: var(--danger);    /* back off */
  --state-recovering:   var(--graphite);  /* rest day(s) */
  --state-leader:       var(--signal);    /* race leader · ONE rider · the Signal exception */

  /* Rider categories : fixed by speciality */
  --role-gc:         var(--data-cobalt); /* general classification */
  --role-classics:   var(--data-violet); /* one-day, punchy attackers */
  --role-sprint:     var(--data-ember);  /* sprinters / lead-out */
  --role-tt:         var(--data-bronze); /* time-triallists */
  --role-climber:    var(--data-aqua);   /* pure climbers */
  --role-domestique: var(--graphite);    /* support riders */

  /* Stage / race state */
  --stage-done:     var(--success);
  --stage-today:    var(--warning);
  --stage-tomorrow: var(--info);
  --stage-rest:     var(--graphite-2);
  --stage-upcoming: var(--fg-4);

  /* Mechanical priority : service-course flag queue */
  --mech-critical: var(--danger);    /* race-day blocker */
  --mech-open:     var(--warning);   /* outstanding, not blocking */
  --mech-routine:  var(--info);      /* scheduled maintenance */
  --mech-cleared:  var(--success);   /* signed off */

  /* ----------------------------------------------------------
     SEMANTIC TOKENS : dark mode (product default)
     ---------------------------------------------------------- */
  --bg:            var(--carbon);
  --bg-raised:     var(--slate);
  --bg-raised-2:   var(--slate-2);
  --border:        var(--slate-line);
  --border-strong: #3A4253;
  --fg:            #F5F4EF;
  --fg-1:          #F5F4EF;   /* primary text */
  --fg-2:          #C7CAD1;   /* body */
  --fg-3:          var(--graphite);
  /* Tertiary / incidental text. Bumped off raw graphite-2 (#5C616B ≈ 3.05:1
     on Carbon : below AA) to ~4.5:1 so it's safe for the supporting
     sentences in empty/error states. This is the contrast FLOOR: never
     put essential copy below --fg-4. */
  --fg-4:          #777B83;
  --fg-on-signal:  var(--signal-ink);

  /* The accent rivet on the brand wordmark : Maillot Gold, theme-resolved
     (bright #FFC233 on dark, antique #8A6500 on light) via --signal. */
  --brand-accent:  var(--signal);

  /* Icon inversion. SVG icons load as <img>; their default fill is black,
     so dark mode inverts them to white via this filter. Light mode is
     a no-op since the source SVG is already black. Use --icon-* on any
     <img> rule that displays an icon. */
  --icon-filter:        invert(0.85);
  --icon-filter-strong: invert(1);
  --icon-filter-muted:  invert(0.7);
  --icon-filter-dim:    invert(0.4);
  /* Icon that sits ON a signal fill. Dark fill is bright gold → black
     glyph (none); light fill is deep gold → white glyph (invert). Mirrors
     --signal-ink for text. */
  --icon-on-signal:     none;

  /* Topbar scrim : semi-transparent canvas color for the sticky header. */
  --scrim: rgba(11, 14, 19, 0.86);
}

/* ============================================================
   LIGHT MODE : opt-in via [data-theme="light"]
   ------------------------------------------------------------
   Light mode is for surfaces OUTSIDE the product:
     · investor decks projected in sunny rooms
     · press article screenshots, social cards
     · printed collateral, business cards
     · iOS share-sheet thumbnails
   The product itself defaults to dark : staff work it from
   hotel rooms and team buses during multi-day races. Do not
   ship a light-mode product surface without explicit reason.
   ============================================================ */
[data-theme="light"] {
  /* Canvas + raised surfaces. Cards on light carry a 1-step shadow
     (--elev-1) and a hair-lighter surface : that's the elevation step
     instead of a color jump like on dark. */
  --bg:            var(--chalk);
  --bg-raised:     #FCFBF7;       /* one tick lighter than chalk */
  --bg-raised-2:   #FFFFFF;       /* hover · pure white is allowed at small areas */
  --border:        var(--chalk-line);
  --border-strong: #C9C5BA;

  /* Ink. Carbon body, graphite-2 for secondary, graphite for tertiary. */
  --fg:            var(--carbon);
  --fg-1:          var(--carbon);
  --fg-2:          #2A2F38;        /* near-carbon body */
  --fg-3:          var(--graphite-2);
  /* ~4.5:1 on Chalk : see dark-mode note above. */
  --fg-4:          #6B6F77;
  --fg-on-signal:  var(--chalk);   /* deep-gold fill takes chalk ink on light */

  /* Signal · Maillot Gold : DEEP shade on light surfaces. Full bright
     gold has too little contrast on chalk; the antique shade stays clearly
     gold and clears full AA (4.8:1) as text, ring, and fill. */
  --signal:        var(--gold-deep);
  --signal-700:    var(--gold-deep-700);   /* hover / pressed */
  --signal-100:    rgba(138, 101, 0, 0.15); /* gold wash · badge / tint bg */
  --signal-ink:    var(--chalk);           /* text/icons ON a deep-gold fill */
  --brand-accent:  var(--signal);

  /* Icons: source SVGs are already black. No inversion needed.
     Muted/dim states use opacity so the silhouette stays carbon. */
  --icon-filter:        none;
  --icon-filter-strong: none;
  --icon-filter-muted:  opacity(0.6);
  --icon-filter-dim:    opacity(0.42);
  --icon-on-signal:     invert(1);   /* white glyph on the deep-gold fill */

  /* Topbar scrim → chalk-tinted instead of carbon-tinted. */
  --scrim: rgba(245, 244, 239, 0.86);
}

/* ============================================================
   GLOBAL TYPE / SPACING / RADII / MOTION
   These never flip per theme : they're geometric, not chromatic.
   ============================================================ */
:root {

  /* ----------------------------------------------------------
     TYPE : families
     ---------------------------------------------------------- */
  --font-sans: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* ----------------------------------------------------------
     TYPE : scale (px values from brand guide)
     ---------------------------------------------------------- */
  --fs-display: 44px;
  --fs-h1:      28px;
  --fs-h2:      18px;
  --fs-body:    14px;
  --fs-caption: 11px;
  --fs-mono:    13px;

  --lh-display: 1.04;
  --lh-h1:      1.15;
  --lh-h2:      1.3;
  --lh-body:    1.5;
  --lh-caption: 1.35;
  --lh-mono:    1.4;

  --tracking-display: -0.025em;
  --tracking-h1:      -0.02em;
  --tracking-tight:   -0.01em;
  --tracking-caption: 0.08em;

  /* ----------------------------------------------------------
     SPACING : 4px base
     ---------------------------------------------------------- */
  --s-1:  4px;
  --s-2:  8px;
  --s-3:  12px;
  --s-4:  16px;
  --s-5:  20px;
  --s-6:  24px;
  --s-8:  32px;
  --s-10: 40px;
  --s-12: 48px;
  --s-16: 64px;
  --s-20: 80px;

  /* ----------------------------------------------------------
     RADII : restrained. Cards & inputs share the same radius.
     ---------------------------------------------------------- */
  --r-1: 2px;     /* hairline tags, chips */
  --r-2: 4px;     /* inputs, buttons */
  --r-3: 6px;     /* cards */
  --r-4: 10px;    /* modals, large surfaces */
  --r-pill: 999px;

  /* ----------------------------------------------------------
     ELEVATION : flat by default. One elevation step.
     Dark surfaces NEVER carry drop shadows; light ones may.
     ---------------------------------------------------------- */
  --elev-0: none;
  --elev-1: 0 1px 0 rgba(11,14,19,0.04), 0 1px 2px rgba(11,14,19,0.06);
  --elev-2: 0 4px 12px rgba(11,14,19,0.08), 0 1px 2px rgba(11,14,19,0.06);
  --elev-pop: 0 12px 32px -8px rgba(11,14,19,0.32);

  /* ----------------------------------------------------------
     MOTION : restrained, near-instant.
     ---------------------------------------------------------- */
  --ease-out: cubic-bezier(0.2, 0.7, 0.2, 1);
  --ease-in:  cubic-bezier(0.4, 0, 1, 1);
  --dur-1: 90ms;
  --dur-2: 140ms;
  --dur-3: 220ms;
}

/* ============================================================
   SEMANTIC TYPOGRAPHY
   ============================================================ */

.display, .text-display {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: var(--fs-display);
  line-height: var(--lh-display);
  letter-spacing: var(--tracking-display);
}

h1, .h1 {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: var(--fs-h1);
  line-height: var(--lh-h1);
  letter-spacing: var(--tracking-h1);
}

h2, .h2 {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: var(--fs-h2);
  line-height: var(--lh-h2);
  letter-spacing: var(--tracking-tight);
}

p, .body {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}

.label {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: var(--fs-body);
  line-height: 1.2;
}

.caption {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: var(--fs-caption);
  line-height: var(--lh-caption);
  letter-spacing: var(--tracking-caption);
  text-transform: uppercase;
  color: var(--fg-3);
}

.mono,
code,
.numeric {
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: var(--fs-mono);
  line-height: var(--lh-mono);
  font-variant-numeric: tabular-nums;
}

/* tabular numerals are mandatory anywhere a measured value appears */
.tnum { font-variant-numeric: tabular-nums; }

/* The big number : a single one per screen, Signal gold */
.hero-metric {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 56px;
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--signal);
  font-variant-numeric: tabular-nums;
}

/* ============================================================
   Z-INDEX : single source of truth for stacking.
   Reach for a token; never write a bare z-index in app code.
   Gaps of 100 leave room for local offsets inside a layer.
   ============================================================ */
:root {
  --z-base:      0;     /* in-flow content */
  --z-raised:    10;    /* sticky table headers, pinned columns */
  --z-sidebar:   100;   /* fixed left nav */
  --z-topbar:    200;   /* fixed header (sits above sidebar shadow) */
  --z-dropdown:  300;   /* menus, selects, comboboxes, popovers */
  --z-scrim:     400;   /* modal / drawer backdrop */
  --z-modal:     410;   /* dialog + drawer surface (just above its scrim) */
  --z-toast:     500;   /* toast stack : above everything dismissable */
  --z-tooltip:   600;   /* hover tooltips : never occluded */
}

/* ============================================================
   FOCUS : keyboard-visible ring. Signal gold, offset so it
   reads on Carbon and Chalk alike. :focus-visible only, so a
   mouse click never paints a ring but Tab always does.
   Apply .focus-ring or rely on the global rule below.
   ============================================================ */
:where(a, button, input, select, textarea, [tabindex], [role="button"],
        [role="tab"], [role="menuitem"], [role="option"], [role="row"]):focus-visible,
.focus-ring:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 2px;
  border-radius: var(--r-2);
}
[data-theme="light"] :where(a, button, input, select, textarea, [tabindex],
        [role="button"], [role="tab"], [role="menuitem"], [role="option"],
        [role="row"]):focus-visible,
[data-theme="light"] .focus-ring:focus-visible {
  /* Full Signal under-reads on Chalk; Signal-700 holds the AA edge. */
  outline-color: var(--signal-700);
}

/* ============================================================
   REDUCED MOTION : the system is already fast & small; honor
   the OS switch by collapsing transitions/animations to near-zero.
   ============================================================ */
@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;
  }
}

/* ============================================================
   SCROLLBARS : instrument-grade, theme-aware. Thin, no arrows,
   thumb is a border-strong bar that brightens on hover. Keeps
   the dark canvas from showing chunky OS scrollbars.
   ============================================================ */
* {
  scrollbar-width: thin;                              /* Firefox */
  scrollbar-color: var(--border-strong) transparent;  /* thumb / track */
}
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border: 2px solid var(--bg);          /* inset so the thumb looks slim */
  border-radius: var(--r-pill);
}
*::-webkit-scrollbar-thumb:hover { background: var(--fg-4); }
*::-webkit-scrollbar-corner { background: transparent; }
