/* ============================================================================
   Dekmak portal — canonical design tokens
   ----------------------------------------------------------------------------
   One definition of the product's colour, type, spacing, radius, motion and
   layering scales. Extracted from dashboard.html, which was the only screen
   that had a complete, correctly structured two-theme token set; the other ten
   each carried a private partial copy, which is why the product had four page
   grounds, four body-text colours and one screen that was dark.

   HOW PAGES USE THIS
   Every token is namespaced --dkm-*. A page keeps its own :root block and
   repoints its values at these, e.g.

       :root { --bg: var(--dkm-bg); --text: var(--dkm-text); }

   That is deliberate. It means no selector in any page has to change, both
   spellings of a forked name can alias to the same value, and because custom
   properties resolve at use time the load order of this file versus a page's
   inline <style> does not matter.

   THEMES
   Light is the default and lives in the bare :root, so a page with no
   data-theme attribute renders light. [data-theme="dark"] overrides only the
   values that change. There is deliberately no prefers-color-scheme block:
   the dashboard's toggle defaults to light explicitly, and honouring the OS
   here would flip existing users into dark without them asking.

   Adding a token: define it in BOTH blocks if it is a colour, or in :root only
   if it is a scale. A colour defined in one theme only renders as an invalid
   value in the other, which is silent.
   ============================================================================ */

:root {

  /* ── Surfaces & text — light ─────────────────────────────────────────────
     Adopted from dashboard.html's [data-theme="light"] block, which keeps the
     whole palette in one colour family (Tailwind slate) rather than mixing a
     custom navy with Tailwind gray. This also means no visual change on the
     dashboard or campaigns, the two largest surfaces. */
  --dkm-bg:         #f0f2f7;
  --dkm-surface:    #ffffff;
  --dkm-surface-2:  #f6f8fb;
  --dkm-surface-3:  #eef1f6;
  --dkm-border:     #e3e7ef;
  --dkm-border-2:   #edf0f5;

  --dkm-text:       #0f172a;
  --dkm-text-2:     #475569;
  /* Was #64748b, which measures 4.25:1 on --dkm-bg and so failed AA on the
     tinted page ground while passing on white cards. Darkened one step to pass
     on both (4.93:1 and 5.52:1) while staying clearly lighter than --text-2. */
  --dkm-muted:      #5b6a7d;
  --dkm-muted-2:    #94a3b8;

  /* ── Brand ───────────────────────────────────────────────────────────────
     Two tokens, because one colour cannot do both jobs. The brand green was
     chosen for a dark interface: white-on-#3db54a is 2.66:1 on a light ground,
     under the 4.5:1 that UI text needs. Use --brand for decoration (dots,
     chart series, tints) where contrast does not apply.

     The other two are NOT interchangeable, which is the trap this file exists
     to close. A colour bearing text on a tinted chip has to move with the
     theme: dark green on a light tint, light green on a dark one. A colour used
     as a FILL under white text must stay dark in both, because white-on-green
     is 2.66:1 no matter what is behind the button. Trying to serve both from
     one token broke every primary button in dark mode.

       --brand-ink   text on a tint. Follows the theme.
       --brand-fill  a solid fill with white text on it. Same in both themes.
   */
  --dkm-brand:      #3db54a;
  --dkm-brand-ink:  #24722f;   /* 4.82:1 on its own tint (light) */
  --dkm-brand-fill: #24722f;   /* 5.96:1 with white text, both themes */
  /* A filled button's hover must go DARKER, not lighter: --brand-h (#32a140)
     was being used for this and drops white text to 3.33:1. */
  --dkm-brand-fill-h: #1f6329; /* 7.30:1 with white text */
  --dkm-brand-h:    #32a140;
  --dkm-brand-50:   #e9f6ec;
  --dkm-brand-100:  #d1eed6;

  /* ── Semantic state ──────────────────────────────────────────────────────
     Delta ink and its tint travel together: pairing a fixed ink with a
     theme-following alpha tint is what made the dark pills unreadable. */
  --dkm-pos-ink:    #15803d;
  --dkm-pos-bg:     rgba(34,197,94,.10);
  --dkm-neg-ink:    #b91c1c;
  --dkm-neg-bg:     rgba(239,68,68,.08);
  --dkm-neg-fill:   #b91c1c;   /* 6.47:1 with white text, both themes */
  /* One step darker than #b45309, which read 4.19:1 as text on its own tint
     over the page ground. Now 4.95:1. */
  --dkm-warn-ink:   #a34a08;
  --dkm-warn-bg:    rgba(245,158,11,.10);

  /* Role/category accents. Needed because the user roles have to be
     distinguishable at a glance, and the shipped blue (#4a9eff) and violet
     (#9b7dff) were picked for a dark ground: they measure 2.40:1 and 2.67:1 as
     text on their own light tints. The dark values below keep the originals
     exactly, so dark is unchanged and only light is corrected. */
  --dkm-info-ink:   #1a63bd;
  --dkm-info-bg:    rgba(59,130,246,.12);
  --dkm-violet-ink: #6d3fd4;
  --dkm-violet-bg:  rgba(139,92,246,.12);

  /* ── Channel colours ─────────────────────────────────────────────────────
     Platform brand colours, identical in both themes on purpose: they identify
     a channel in charts and legends, so shifting them for contrast would break
     recognition and chart-to-legend matching. Where one of these carries text,
     use a filled pill rather than darkening the hue. */
  --dkm-meta:       #1877f2;
  /* Meta blue bearing text. #1877f2 is 4.23:1 with white as a fill and
     3.86:1 as text on its own tint, so the launch buttons needed a darker
     one. #1565d8 was already in campaigns.html as the launch hover, so this
     is a colour the product already uses, not a new one. */
  --dkm-meta-ink:   #1565d8;
  --dkm-meta-ink-h: #1258b8;
  --dkm-gads:       #ea4335;
  --dkm-ga4:        #e8710a;
  --dkm-shopify:    #96bf48;
  --dkm-tiktok:     #010101;
  --dkm-snapchat:   #fffc00;

  /* ── Chart furniture ─────────────────────────────────────────────────────── */
  /* Skeleton placeholders. The dashboard's shimmer was a white highlight at
     5.5% over var(--surface); on a white surface that is white on white, so
     it was invisible in light mode. Base and highlight are both explicit. */
  --dkm-skel-base:  #e7ebf1;
  --dkm-skel-hi:    #f3f6fa;

  --dkm-chart-grid: rgba(15,23,42,0.05);
  --dkm-chart-tick: #94a3b8;

  /* ── Elevation ───────────────────────────────────────────────────────────── */
  --dkm-shadow-sm:  0 1px 2px rgba(15,20,40,.04), 0 1px 1px rgba(15,20,40,.03);
  --dkm-shadow:     0 1px 3px rgba(15,23,42,0.06), 0 1px 2px rgba(15,23,42,0.04);
  --dkm-shadow-md:  0 4px 16px rgba(15,23,42,0.08), 0 2px 4px rgba(15,23,42,0.04);

  /* ── Hover fill ──────────────────────────────────────────────────────────
     Derived from the page's own text colour so it is correct on any ground in
     either theme. The global nav previously hardcoded #f1f5f9 here, which
     rendered white-on-white on the dark screens. */
  /* Modal scrim. Nine overlays across four files had eight different
     appearances: opacity from 0.40 to 0.65, five blur values, and one navy
     while the rest were black. Opening a dialog dimmed the page by a different
     amount depending which screen you were on. Appearance only -- position,
     z-index and stacking stay with each overlay, because those are behaviour. */
  --dkm-scrim:      rgba(15,23,42,.55);
  --dkm-scrim-blur: blur(4px);

  --dkm-hover:      rgba(128,128,128,.16);
  --dkm-hover:      color-mix(in srgb, var(--dkm-text) 8%, transparent);

  /* ══ SCALES ══════════════════════════════════════════════════════════════
     Theme-independent, so defined once.

     These steps are measured from the codebase, not chosen in the abstract. An
     earlier draft of this file guessed a tighter scale (7 type steps, 4-8-12-16
     spacing, 6-10-14 radius) and the numbers rejected it: 6px and 10px gaps are
     150 declarations between them, so snapping to 4-8-12 would have tightened
     the whole interface by 2px in 150 places. A scale that fights the design it
     describes is not a scale, it is a redesign. These are the steps the product
     actually reaches for, with the in-between values removed. */

  /* Type. Half-pixel steps (8.5 … 13.5) and the near-duplicate pairs (15/16,
     17/16, 19/18, 23/22, 27/26) are gone; 8-13 carries ~800 of the 877
     declarations so the small end needs every step it has. The three display
     one-offs (36, 40, 44) are single hero figures and stay outside the scale. */
  --dkm-text-3xs:   9px;
  --dkm-text-2xs:   10px;
  --dkm-text-xs:    11px;
  --dkm-text-sm:    12px;
  --dkm-text-base:  13px;
  --dkm-text-md:    14px;
  --dkm-text-lg:    16px;
  --dkm-text-xl:    18px;
  --dkm-text-2xl:   20px;
  --dkm-text-3xl:   22px;
  --dkm-text-4xl:   26px;
  --dkm-text-5xl:   30px;

  /* Space. A 2px increment to 16, then jumps. The odd values (1,3,5,7,9,11,13)
     were the noise: 143 declarations, none of them distinguishable from their
     even neighbour. */
  --dkm-space-px:   2px;
  --dkm-space-1:    4px;
  --dkm-space-2:    6px;
  --dkm-space-3:    8px;
  --dkm-space-4:    10px;
  --dkm-space-5:    12px;
  --dkm-space-6:    16px;
  --dkm-space-7:    20px;
  --dkm-space-8:    24px;

  /* Radius. --radius-pill exists because 999px, 100px, 99px and 40px were four
     spellings of the same intent; they collapse to one. 1px and 2px are kept:
     those are hairline rules and meters, not corners. */
  --dkm-radius-hair: 2px;
  --dkm-radius-sm:  4px;
  --dkm-radius:     6px;
  --dkm-radius-md:  8px;
  --dkm-radius-lg:  10px;
  --dkm-radius-xl:  12px;
  --dkm-radius-2xl: 14px;
  --dkm-radius-3xl: 20px;
  --dkm-radius-pill: 999px;

  /* Motion. Transitions only. The long durations in the pages (0.5s to 2.5s,
     and one 120s) are keyframe animations: spinners, pulses, ambient loops.
     Those are not interaction feedback and are deliberately not on this scale. */
  --dkm-dur-fast:   120ms;
  --dkm-dur:        150ms;
  --dkm-dur-slow:   200ms;
  --dkm-dur-slower: 250ms;
  --dkm-ease:       cubic-bezier(.4, 0, .2, 1);

  /* Layering. Named so a new overlay does not get an arbitrary number. The
     global nav sits at 1000/1001 with its panel at 2000, and the dashboard
     independently uses 1100 and 1200, which is why these need naming. */
  /* Layering. The global nav sits at --dkm-z-nav on EVERY authenticated page,
     so any dialog that must cover the page has to clear it: anything modal
     belongs at --dkm-z-modal or above, never below. Pages that layer several
     dialogs express the order as calc(var(--dkm-z-modal) + N) so the intent is
     legible in the value. Page chrome (sticky bars, bottom nav, popovers that
     never coexist with a dialog) stays under the nav. */
  --dkm-z-base:     1;
  --dkm-z-sticky:   900;
  --dkm-z-nav:      1000;
  --dkm-z-dropdown: 1001;
  --dkm-z-panel:    2000;
  --dkm-z-modal:    9000;
  --dkm-z-toast:    9999;
}

/* ── Dark ──────────────────────────────────────────────────────────────────
   Overrides only what changes. Scales, channel colours and --brand are shared
   with light and are deliberately absent here. */
:root[data-theme="dark"] {
  --dkm-bg:         #0c0c0c;
  --dkm-surface:    #161616;
  --dkm-surface-2:  #1f1f1f;
  --dkm-surface-3:  #2a2a2a;
  --dkm-border:     rgba(255,255,255,0.08);
  --dkm-border-2:   rgba(255,255,255,0.06);

  --dkm-text:       #f4f4f5;
  --dkm-text-2:     #a1a1aa;
  --dkm-muted:      #a1a1aa;
  --dkm-muted-2:    #71717a;

  /* Inks lighten with the theme; fills deliberately do not. --brand-fill and
     --neg-fill are absent from this block on purpose, so they keep their light
     values and white text on them still passes. An earlier version overrode
     --brand-ink to #3db54a here, reasoning that the brand reads 6.41:1 against
     a dark ground; that is the ink measurement, and applying it to the fill
     broke every primary button in dark mode at 2.66:1. */
  --dkm-brand-ink:  #3db54a;   /* 6.37:1 on its own tint (dark) */
  --dkm-brand-h:    #3db54a;
  --dkm-brand-50:   rgba(61,181,74,0.12);
  --dkm-brand-100:  rgba(61,181,74,0.2);

  /* Verified on --dkm-surface: 7.58:1 and 5.41:1. The light values measured
     3.08:1 here, which is the bug this pairing fixes. */
  --dkm-pos-ink:    #4ade80;
  --dkm-pos-bg:     rgba(34,197,94,.18);
  --dkm-neg-ink:    #f87171;
  --dkm-neg-bg:     rgba(239,68,68,.18);
  --dkm-warn-ink:   #fbbf24;
  --dkm-warn-bg:    rgba(245,158,11,.18);

  /* 5.30:1 and 4.79:1 on their tints over --dkm-surface. */
  --dkm-info-ink:   #4a9eff;
  --dkm-info-bg:    rgba(59,130,246,.18);
  --dkm-violet-ink: #9b7dff;
  --dkm-violet-bg:  rgba(139,92,246,.18);

  /* A black scrim over a near-black page reads as nothing, so it goes darker
     and more opaque rather than lighter. */
  --dkm-scrim:      rgba(0,0,0,.72);

  --dkm-skel-base:  #1f1f1f;
  --dkm-skel-hi:    #2b2b2b;

  --dkm-chart-grid: rgba(255,255,255,0.05);
  --dkm-chart-tick: #71717a;

  --dkm-shadow-sm:  0 1px 2px rgba(0,0,0,0.3);
  --dkm-shadow:     0 1px 6px rgba(0,0,0,0.5);
  --dkm-shadow-md:  0 4px 20px rgba(0,0,0,0.4);
}

/* ── Channel logos (static/js/channel-logos.js) ───────────────────────────────
   One rule for every page, because this file is the one stylesheet every
   authenticated page has. The files are square canvases; contain keeps the
   wide Meta mark in proportion inside them. */
img.ch-logo {
  display: inline-block;
  flex-shrink: 0;
  object-fit: contain;
  vertical-align: middle;
}
/* The TikTok mark is black. On the dark theme it disappears, so it sits on a
   small white tile there, the way TikTok itself shows it on dark grounds. */
:root[data-theme="dark"] img.ch-logo[data-ch="tiktok"] {
  background: #fff;
  border-radius: 22%;
  padding: 8%;
  box-sizing: border-box;
}
