/* ============================================================================
   TOKENS.CSS — Single source of truth for Spark's design system
   ----------------------------------------------------------------------------
   Imported by:
     - Every public/web HTML file (index, profile, login, jobs, etc.)
     - /css/_app.css (which overrides for the native mobile context)

   ARCHITECTURE — Option 2: same brand DNA, different expression by context.
     - DEFAULTS in :root below = the WEB / EDITORIAL surface
         Softer background (#121212), softer text (#e0e0e0).
         Magazine-like, reads at desk distance.
     - The mobile app overrides these inside _app.css via body.is-native
         Sharper background (#0a0a0a), pure white text.
         Tool-like, reads at arm's length.

   Both surfaces share: Helvetica for identity, mono for metadata, the
   Verified Green accent, the film-grain texture, and the spacing scale.

   If you change a value here, both surfaces update together. If you need
   to change ONLY the mobile surface, do it in _app.css under the
   `body.is-native` scope, never here.

   See spark_brand_guidelines.md for the full design system documentation.
   ============================================================================ */

:root {

    /* === SURFACES (web defaults) =========================================
       Near-black canvas. The web is intentionally slightly softer than the
       mobile app to support the editorial/magazine reading mode — text on
       this surface should feel like a publication, not a tool. */

    --bg:              #121212;   /* Page background */
    --surface:         #181818;   /* Panels, sidebars, cards */
    --surface-2:       #1a1a1a;   /* Hover states, dropdowns, chat received */
    --border:          #333333;   /* Default dividers and outlines */
    --border-bright:   #3a3a3a;   /* Focus and emphasis states */


    /* === TEXT (web defaults) =============================================
       Off-white on near-black. Slightly softer than pure white — sits
       comfortably during long reading sessions on a desktop monitor. */

    --text:            #e0e0e0;   /* Primary text, headlines, names */
    --text-muted:      #757575;   /* Metadata, secondary text */
    --text-dim:        #555555;   /* Inactive states, placeholders, ghost text */


    /* === ACCENT ==========================================================
       Pure white for primary CTAs, focus states, the wordmark.
       Monochrome by design — the only "colour" in the system is Verified
       Green below. */

    --accent:          #ffffff;
    --accent-hover:    #ffffff;


    /* === SIGNATURE ACCENT (universal — same on web and mobile) ===========
       Reserved EXCLUSIVELY for the Verified Credits badge. Do not use this
       colour for buttons, links, hover states, or decoration anywhere else
       in the product. */

    --verified:        #29d96a;


    /* === SYSTEM STATUS ===================================================
       Not brand colours. Used only for system signals (notification dots,
       error states). Never apply to typography, buttons, or marketing. */

    --status-alert:    #ff3b30;


    /* === COMPONENT-SPECIFIC (messages/chat) ==============================
       The two chat bubble colours. These earn their own tokens because
       they're used across messages.html and connections.html. */

    --msg-sent:        #2a2a2a;   /* Outgoing message bubbles */
    --msg-received:    #1a1a1a;   /* Incoming message bubbles */


    /* === TYPOGRAPHY (universal) ==========================================
       One sans, one mono. Helvetica for identity and body: true Helvetica
       Neue on Apple devices (the overwhelming majority of Spark's
       audience), Arial on Windows, Roboto on Android. No webfont file, no
       load cost, and the fashion-canon register (SSENSE, print editorial).

       CHANGED July 2026: previously named 'Inter', but no Inter webfont
       was ever loaded, so visitors were seeing their system font all
       along. This stack makes the choice deliberate.

       The mono stack tries the system mono first via Courier New — keeps
       the typewriter feel everywhere. */

    --font-sans:       'Helvetica Neue', Helvetica, Arial, sans-serif;
    --font-mono:       'Courier New', Courier, monospace;


    /* === SPACING SCALE (universal) =======================================
       Rem-based, maps to a 4/8px grid. Use these tokens instead of
       arbitrary px values where possible. */

    --space-1:         0.3rem;    /* ~5px   micro */
    --space-2:         0.5rem;    /* ~8px   tight */
    --space-3:         0.7rem;    /* ~11px  compact */
    --space-4:         0.85rem;   /* ~14px  small */
    --space-5:         1rem;      /* 16px   base */
    --space-6:         1.25rem;   /* ~20px  medium */
    --space-7:         1.5rem;    /* 24px   large */
    --space-8:         2rem;      /* 32px   xl */


    /* === LAYOUT (mobile-only, but lives here for visibility) =============
       Native tab bar height. See _app.css and native.css for usage. */

    --tabbar-h:        64px;


    /* === USER-THEMABLE (profile pages only) =============================
       Profile owners override these via the Appearance editor on their
       own profile.html page. applyTheme() writes inline styles on :root
       at runtime per profile. */

    --bg-image:                none;
    --bg-overlay-opacity:      0.4;
    --layout-gap:              1.5rem;
    --layout-page-padding:     2rem;
}


/* === TEXTURE (universal: web and app) ======================================
   Film grain across every surface. Replaces the old per-page dot grids
   (radial-gradient patterns), which read as dev-tool blueprint; grain
   reads as darkroom, the right register for a photography-first product.

   Mechanics: a seamless feTurbulence tile, fixed, painted behind all
   content (negative z-index inside body's stacking order), click-through.
   Sections with opaque backgrounds (panels, cards, the white ticker)
   naturally cover it, which is correct: grain belongs to the canvas, not
   the components. Opacity 0.09 is the approved level; 0.07 if a screen
   renders it noisy, 0.035 for barely-there.

   WEB ONLY (decided Jul 4 2026): the app stays clean. Two-surface
   doctrine — web is the magazine (grain reads as paper stock on #121212
   at desk distance), the app is the tool (on near-black OLED at arm's
   length the same noise lifts blacks next to photography, and the
   native shell's anti-flash body background would need renegotiating
   to host it). The :not(.is-native) scope encodes the decision at the
   source; nav/footer overlays below are inside is-native-hidden chrome
   anyway, so they need no scoping.
   ========================================================================== */

body:not(.is-native)::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    opacity: 0.09;
    background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="180" height="180"><filter id="n"><feTurbulence type="fractalNoise" baseFrequency="0.8" numOctaves="2" stitchTiles="stitch"/></filter><rect width="100%" height="100%" filter="url(%23n)"/></svg>');
}

/* Header and footer carry the grain too (Jul 2026). They have opaque
   backgrounds (the nav must, content scrolls beneath it), which cover the
   body grain — so each gets its own overlay. It drapes over the bar's
   content as a 9% filmic wash; dropdown panels and other high-z children
   paint above it, and pointer-events: none keeps everything clickable.
   The position: relative below only affects navs/footers that don't set
   their own position — pages with fixed or sticky navs override it since
   their CSS loads after this file. */
nav, footer { position: relative; }
nav::before,
footer::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    opacity: 0.09;
    background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="180" height="180"><filter id="n"><feTurbulence type="fractalNoise" baseFrequency="0.8" numOctaves="2" stitchTiles="stitch"/></filter><rect width="100%" height="100%" filter="url(%23n)"/></svg>');
}