/* Tiny tweaks on top of Tailwind CDN. Most styling stays inline in templates. */
html, body { font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; }

/* The Tailwind CDN doesn't ship JIT; ring-0 may not be reachable without
   the JIT compiler. This shim makes focus rings invisible the way our
   forms expect. */
input:focus, textarea:focus, select:focus { box-shadow: none; outline: none; }

/* ─── Popup-modal hygiene ───────────────────────────────────────────
   Two flavors of modal live in the codebase:
     1. native <dialog> (stats.tmpl): browsers ship a default 1em
        padding + solid border + white background; without resetting,
        a visible white strip frames the inner card.
     2. <div class="fixed inset-0 ..."> Tailwind modals (contacts,
        pipeline, inbox, …): the white card is built from Tailwind
        utilities, but on mobile the safe-area inset bleeds a white
        sliver above the header.
   The rules below normalise both: the chrome is transparent, the
   backdrop is a dark blur, and the inner card carries its own
   white background + rounded corners. Modals stay flexible — pages
   can still inline-style their cards. */

dialog {
  border: 0;
  padding: 0;
  margin: auto;
  background: transparent;
  max-width: min(640px, 100vw);
  max-height: 100vh;
  overflow: visible;
  color: inherit;
}
dialog::backdrop {
  background: rgba(15, 23, 42, 0.6);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
/* Inner card: white background + rounded corners + scroll. The
   selector is intentionally narrow — it ONLY hits the direct child of
   a <dialog>, so existing Tailwind utility classes on the same
   element still win (rounded-2xl, p-5, etc). */
dialog > .modal-card,
dialog > form,
dialog > div {
  background: #fff;
  border-radius: 1rem;
  padding: 1.25rem;
  box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
  max-height: 90vh;
  overflow-y: auto;
}

/* Mobile div-modals already use `h-full sm:h-auto` so the white card
   covers the full viewport edge-to-edge below the sm breakpoint. We
   intentionally do NOT inject extra safe-area padding here — that
   would push the page's existing header down into ugly territory.
   Each modal that needs notch-safe layout opts in inline. */

/* ═══════════════════════════════════════════════════════════════════════
   THEME LAYER
   ═══════════════════════════════════════════════════════════════════════

   Why this exists, and why it is written this way.

   The app ships a PREBUILT tailwind.css that contains ZERO `dark:` variants
   (verified: `grep -c 'dark\:' tailwind.css` → 0). theme.js faithfully sets
   <html class="dark">, but no utility in any template responds to it, so dark
   mode flipped the class and almost nothing changed — while the handful of
   elements that carry hand-written dark styling DID change. That mismatch is
   what produced the "some elements dark, some white" screens, and why text
   disappeared: dark glyphs on a still-white surface, or the reverse.

   Adding `dark:` classes to 95 templates would not work — those classes are
   not in the prebuilt CSS, so they would be inert. Rebuilding Tailwind is not
   an option here either.

   So the theme is expressed as semantic tokens, and dark mode REMAPS the
   handful of colour utilities the templates actually use. That vocabulary is
   small and highly concentrated — the top ten account for the overwhelming
   majority of usage:
       text-slate-500 (1649)  border-slate-200 (1273)  bg-white (936)
       text-slate-900 (679)   text-slate-700 (524)     text-white (519)
       bg-slate-50 (492)      text-slate-600 (482)     bg-slate-100 (314)
   One rule per utility themes every page at once, with no template edits and
   no risk of a page being missed.

   LIGHT MODE IS DELIBERATELY UNTOUCHED. Every rule below is scoped under
   html.dark, so the default theme renders exactly as it does today and this
   layer cannot regress it.
   ═══════════════════════════════════════════════════════════════════════ */

:root {
  /* Light — mirrors the existing slate palette so nothing shifts. */
  --surface:        #ffffff;  /* cards, panels, the page itself   */
  --surface-sunken: #f8fafc;  /* slate-50  — inset areas, toolbars */
  --surface-raised: #f1f5f9;  /* slate-100 — chips, hover states   */
  --border:         #e2e8f0;  /* slate-200 — the default hairline  */
  --border-strong:  #cbd5e1;  /* slate-300 — inputs, dividers      */
  --text:           #0f172a;  /* slate-900 — headings, body        */
  --text-secondary: #334155;  /* slate-700                          */
  --text-muted:     #64748b;  /* slate-500 — labels, metadata      */
  --text-faint:     #94a3b8;  /* slate-400 — placeholders          */
  --accent:         #2563eb;
  --accent-weak:    #eff6ff;
  --input-bg:       #ffffff;
  --text-dim:       #cbd5e1;
  --shadow:         rgba(15, 23, 42, .08);
  --scrollbar-thumb: #cbd5e1;
  --scrollbar-track: transparent;

  /* Pin the light scheme. base.tmpl declares
     `<meta name="color-scheme" content="light dark">`, which tells the browser
     the page supports BOTH -- and html.dark pins dark, but nothing ever pinned
     light. So in the light theme the UA fell back to the OS preference when
     painting native controls, and on an OS-dark machine every <input>/<select>
     without an explicit background rendered near-black on a white page. That
     is the "some elements dark moded some white moded" symptom, and why it
     looked random: it depended on the viewer's OS setting, not the app's.
     html.dark below is (0,1,1) and still outranks this (0,1,0). */
  color-scheme: light;
}

html.dark {
  /* Dark — a neutral slate ramp. Surfaces stay close together so panels read
     as one continuous plane instead of a patchwork of competing greys, which
     is what made the current screens look broken. Text contrast targets
     WCAG AA against --surface. */
  --surface:        #131c2e;  /* cards and raised panels -- what .bg-white becomes */
  --surface-sunken: #0b1220;  /* the page itself, and inset areas             */
  --surface-raised: #1b2740;
  --border:         #243047;
  --border-strong:  #2e3c57;
  --input-bg:       #0f1729;  /* inputs read as wells, recessed below a card  */
  --text:           #e2e8f0;
  --text-secondary: #cbd5e1;
  --text-muted:     #94a3b8;
  --text-faint:     #7c8aa3;
  --text-dim:       #5b6880;  /* text-slate-300, used for de-emphasised labels */
  --accent:         #60a5fa;
  --accent-weak:    #172554;
  --shadow:         rgba(0, 0, 0, .5);
  --scrollbar-thumb: #334155;
  --scrollbar-track: transparent;

  color-scheme: dark; /* themes native controls: scrollbars, date pickers, etc. */
}

/* ── Dark remap of the utilities the templates actually use ──────────────
   Specificity note: `html.dark .bg-white` is (0,2,0) and beats a bare
   utility's (0,1,0), so these win without !important — which keeps a page
   free to override deliberately with an inline style when it must. */
html.dark, html.dark body  { background-color: var(--surface-sunken); color: var(--text); }
html.dark .bg-white       { background-color: var(--surface); }
html.dark .bg-slate-50    { background-color: var(--surface-sunken); }
html.dark .bg-slate-100   { background-color: var(--surface-raised); }
html.dark .bg-slate-200   { background-color: var(--border); }
/* Neutral hover states, ported from the skin this layer replaces. Without
   them every hoverable row (178 uses of hover:bg-slate-50 alone) flashes back
   to near-white under the cursor. */
html.dark .hover\:bg-slate-50:hover  { background-color: var(--surface-raised); }
html.dark .hover\:bg-slate-100:hover { background-color: var(--border); }
html.dark .hover\:text-slate-900:hover { color: #f1f5f9; }
html.dark .hover\:text-slate-700:hover { color: var(--text); }
/* Already-dark surfaces must NOT invert — they are dark by intent (the
   marketing shell, code blocks, the dark sidebar variant). Nudged to sit on
   the same ramp instead. */
html.dark .bg-slate-800,
html.dark .bg-slate-900   { background-color: var(--surface-sunken); }

html.dark .text-slate-900 { color: var(--text); }
html.dark .text-slate-800,
html.dark .text-slate-700 { color: var(--text-secondary); }
html.dark .text-slate-600,
html.dark .text-slate-500 { color: var(--text-muted); }
html.dark .text-slate-400 { color: var(--text-faint); }
html.dark .text-slate-300 { color: var(--text-dim); }

/* PRIMARY BUTTONS — the correction to the blanket .bg-slate-900 remap above.
   `bg-slate-900 text-white` is this app's primary action (plus a few avatar
   circles); the blanket rule would paint it --surface-sunken, i.e. DARKER than
   the page it sits on, making every primary button effectively invisible.
   Pairing with .text-white is what distinguishes a button from a code block
   (`bg-slate-900 text-slate-100`), which genuinely does want to read as an
   inset dark panel and is left to the blanket rule.
   Blue rather than an inverted light chip, so .text-white stays correct as
   written: #fff on #2563eb is 5.2:1. */
html.dark .bg-slate-900.text-white,
html.dark .bg-slate-800.text-white { background-color: #2563eb; }
/* Outranks the .hover\:bg-slate-700:hover utility, so the button does not
   flash back to near-black on hover. */
html.dark .bg-slate-900.text-white:hover,
html.dark .bg-slate-800.text-white:hover { background-color: #1d4ed8; }

/* Chip legibility. A muted text utility is fine on the page background but not
   on a raised chip: text-slate-600 (#94a3b8) on bg-slate-200 (#334155) is only
   3.4:1 — below AA, and these chips render at 10px. Lift the text only where
   the two land on the same element. */
html.dark .bg-slate-200.text-slate-600,
html.dark .bg-slate-200.text-slate-500 { color: var(--text-secondary); }

html.dark .border-slate-100,
html.dark .border-slate-200 { border-color: var(--border); }
html.dark .border-slate-300 { border-color: var(--border-strong); }
html.dark .divide-slate-100 > :not([hidden]) ~ :not([hidden]),
html.dark .divide-slate-200 > :not([hidden]) ~ :not([hidden]) { border-color: var(--border); }

/* Tinted status chips: keep the hue, drop the luminance so dark text on a
   pale wash stays legible instead of becoming black-on-near-white. */
html.dark .bg-blue-50    { background-color: #172554; }
html.dark .bg-emerald-50,
html.dark .bg-emerald-100{ background-color: #052e26; }
html.dark .bg-amber-50,
html.dark .bg-amber-100  { background-color: #3a2a06; }
html.dark .bg-red-50,
html.dark .bg-red-100    { background-color: #3f1418; }
html.dark .bg-indigo-50  { background-color: #1e1b4b; }
html.dark .bg-violet-50,
html.dark .bg-purple-50  { background-color: #2e1065; }
html.dark .text-blue-600,  html.dark .text-blue-700    { color: #93c5fd; }
html.dark .text-emerald-600, html.dark .text-emerald-700 { color: #6ee7b7; }
html.dark .text-amber-600,  html.dark .text-amber-700   { color: #fcd34d; }
html.dark .text-red-600,    html.dark .text-red-700     { color: #fca5a5; }
html.dark .text-indigo-600, html.dark .text-indigo-700  { color: #a5b4fc; }

/* The rest of the tinted family. Found by counting real template usage rather
   than guessing: bg-blue-100 (29 uses), bg-violet-100 (28), bg-rose-100 (16),
   bg-pink-100 (5), bg-orange-100 (4), bg-indigo-100 (3), bg-sky-100 (1) had NO
   dark rule at all, so 86 chips rendered as a pale light-mode wash carrying
   dark text -- pale-on-pale, the exact "some elements still white" symptom.
   The -50/-100 pair share a value here: at these luminances the one-step
   difference is invisible on a dark ground and not worth two tokens. */
html.dark .bg-blue-100                        { background-color: #172554; }
html.dark .bg-indigo-100                      { background-color: #1e1b4b; }
html.dark .bg-violet-100, html.dark .bg-purple-100 { background-color: #2e1065; }
html.dark .bg-rose-100,   html.dark .bg-rose-50    { background-color: #3f1420; }
html.dark .bg-pink-100,   html.dark .bg-pink-50    { background-color: #3f1533; }
html.dark .bg-orange-100, html.dark .bg-orange-50  { background-color: #3a2206; }
html.dark .bg-sky-100,    html.dark .bg-sky-50     { background-color: #0c2d48; }
html.dark .text-rose-600,   html.dark .text-rose-700   { color: #fda4af; }
html.dark .text-violet-600, html.dark .text-violet-700 { color: #c4b5fd; }
html.dark .text-pink-600,   html.dark .text-pink-700   { color: #f9a8d4; }
html.dark .text-orange-600, html.dark .text-orange-700 { color: #fdba74; }
html.dark .text-sky-600,    html.dark .text-sky-700    { color: #7dd3fc; }
html.dark .text-green-600,  html.dark .text-green-700  { color: #6ee7b7; }

/* The stronger tinted pair: `bg-<hue>-200` + `text-<hue>-800`, used for stage
   count pills and status chips. Without this the "Lost" pill stayed a pale
   pink chip from the light palette while everything around it went dark --
   legible, but visibly off-theme. Same treatment as the -50/-100 family above:
   keep the hue, invert the luminance. Only the hues actually used in the
   templates are listed; adding an unused one would be dead CSS. */
html.dark .bg-red-200                        { background-color: #4c1d24; }
html.dark .bg-amber-200, html.dark .bg-yellow-200 { background-color: #45320a; }
html.dark .bg-emerald-200                    { background-color: #06372c; }
html.dark .bg-blue-200                       { background-color: #1e3a8a; }
html.dark .bg-violet-200                     { background-color: #3b1178; }
html.dark .bg-pink-200                       { background-color: #4c1533; }
html.dark .text-red-800, html.dark .text-rose-800     { color: #fca5a5; }
html.dark .text-amber-800                             { color: #fcd34d; }
html.dark .text-emerald-800, html.dark .text-green-800{ color: #6ee7b7; }
html.dark .text-blue-800                              { color: #93c5fd; }
html.dark .text-violet-800                            { color: #c4b5fd; }
html.dark .text-pink-800                              { color: #f9a8d4; }

/* Form controls. The templates style inputs inconsistently, which is why the
   template-library search bar rendered dark on a light page — one element had
   hand-written dark styling while its neighbours did not. Theme them from one
   place so they always agree with their surroundings. */
html.dark input,
html.dark textarea,
html.dark select {
  background-color: var(--input-bg);
  border-color: var(--border-strong);
  color: var(--text);
}
/* A control carrying an explicit surface class (`bg-white`, `bg-slate-50` —
   templates add these so the field has a background in light mode regardless
   of the OS scheme) would otherwise win on specificity over the generic
   `html.dark input` rule above, and render as a CARD-coloured field next to
   sibling fields using the input well. Same element type, two different
   fills, in one form. Pin every control to the well. */
html.dark input.bg-white,    html.dark textarea.bg-white,    html.dark select.bg-white,
html.dark input.bg-slate-50, html.dark textarea.bg-slate-50, html.dark select.bg-slate-50
  { background-color: var(--input-bg); }

html.dark input:disabled,
html.dark textarea:disabled,
html.dark select:disabled { opacity: .6; }
/* Native checkbox/radio fills come from the UA; accent-color is the only hook. */
html.dark input[type="checkbox"],
html.dark input[type="radio"] { accent-color: #3b82f6; }
html.dark input::placeholder,
html.dark textarea::placeholder { color: var(--text-faint); }
html.dark option { background-color: var(--surface-raised); color: var(--text); }

/* Modals: the base rules above hardcode a white card. Theme it. */
html.dark dialog > .modal-card,
html.dark dialog > form,
html.dark dialog > div {
  background: var(--surface);
  color: var(--text);
  box-shadow: 0 25px 50px -12px var(--shadow);
}

/* Shadows read as dirty smudges on dark surfaces; soften them. */
html.dark .shadow,
html.dark .shadow-sm,
html.dark .shadow-md,
html.dark .shadow-lg,
html.dark .shadow-xl { box-shadow: 0 1px 3px var(--shadow); }

/* ── Scrollbars ─────────────────────────────────────────────────────────
   The shell nests three scroll containers (sidebar nav, <main>, and each
   page's own inner list), so up to three chunky native scrollbars stacked up
   on one screen. They cannot all be removed — the panes genuinely scroll
   independently — but they can stop shouting: thin, themed, and only visible
   on hover over the pane that owns them. */
* {
  scrollbar-width: thin;                                   /* Firefox */
  scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
}
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--scrollbar-track); }
::-webkit-scrollbar-thumb {
  background-color: var(--scrollbar-thumb);
  border-radius: 9999px;
  border: 3px solid transparent;   /* inset so the thumb reads as a slim pill */
  background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover { background-color: var(--border-strong); }
::-webkit-scrollbar-corner { background: transparent; }

/* Keyboard focus must stay visible in both themes — the global
   `outline: none` above removes it, which is an accessibility defect. */
html.dark input:focus-visible,
html.dark textarea:focus-visible,
html.dark select:focus-visible,
input:focus-visible, textarea:focus-visible, select:focus-visible,
a:focus-visible, button:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
