/* ============================================================================
   T-KON — Design system (stone x 360)
   ----------------------------------------------------------------------------
   Replaces the split between css/uv-theme.css (neon purple/cyan dark) and the
   hand-rolled light pages (#F4F5F7 + Trello blue). Those two were mixed inside
   single pages -- dashboard.html has a .page-dark body with a bg-white modal --
   which is most of why the app reads as cluttered.

   The goal here is not decoration. It is that every screen uses the same five
   surfaces, the same one accent, and the same spacing rhythm, so a user can tell
   at a glance what is a container, what is content, and what is clickable.

   USAGE
     <link rel="stylesheet" href="/css/tkon.css">   -- after Tailwind CDN
     <body class="tk">            app shell  (sidebar, js/shell.js)
     <body class="tk-page">       public     (marketing, legal, docs)
     <body class="tk-standalone"> focused    (OAuth callbacks, login, wizard)

   Every page is exactly one archetype, and every archetype uses the same tokens.
   Every class is prefixed .tk- and nothing overrides bare elements outside those
   three roots, so a page can adopt this incrementally without its markup breaking.

   FONTS
     Montserrat (headings) / Figtree (body) / JetBrains Mono are named in the
     stack but NOT self-hosted yet -- there are no .woff2 files in the repo and
     T-KON must not pull fonts from a third-party CDN (GDPR: that leaks visitor
     IPs to Google). Until the files are added under /fonts/ and the @font-face
     block below is filled in, browsers fall back to the system UI font, which
     is clean and costs nothing. Layout and hierarchy do the heavy lifting.
   ========================================================================== */

/* ── Tokens ───────────────────────────────────────────────────────────────── */
/* On :root, not on .tk. The tokens were originally scoped to the app shell, which
   meant the 29 pages outside the shell — every marketing page, every OAuth
   callback, every legal page — could not reach them and kept their own palettes.
   That is the mechanical reason the site read as four different products:
   .tk (indigo dark), .page-dark (uv-theme purple dark), Trello light (#F4F5F7),
   and Tailwind grey light. Tokens live at the root; the three body archetypes
   below apply them. */

:root {
  /* Surfaces, darkest to lightest */
  --tk-bg:        #020618;   /* page */
  --tk-bg-alt:    #0f172b;   /* sidebar, sunken areas */
  --tk-card:      rgba(15, 23, 43, 0.5);
  --tk-card-solid:#0f172b;   /* when a card sits on --tk-bg-alt */
  --tk-raised:    #1a2338;   /* hover / active row */

  /* Lines */
  --tk-border:    #1d293d;
  --tk-border-lt: #273449;   /* hover borders, dividers inside cards */

  /* Type */
  --tk-text:      #e2e8f0;
  --tk-muted:     #90a1b9;
  --tk-faint:     #64748b;

  /* One accent. Owner decision 2026-07-29. Used for the active nav item,
     primary buttons, focus rings -- and nothing else. If everything is
     accented, nothing is. */
  --tk-accent:    #6366f1;
  --tk-accent-hi: #818cf8;
  --tk-accent-dim:rgba(99, 102, 241, 0.14);

  /* Status. Deliberately desaturated -- these are signals, not decoration. */
  --tk-ok:        #34d399;
  --tk-warn:      #fbbf24;
  --tk-err:       #f87171;
  --tk-info:      #38bdf8;

  /* Rhythm */
  --tk-r-sm:      6px;
  --tk-r:         10px;
  --tk-r-lg:      14px;
  --tk-sidebar:   248px;
  --tk-topbar:    56px;

  --tk-font:      'Figtree', 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --tk-font-head: 'Montserrat', var(--tk-font);
  --tk-font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;
}

/* ── The three page archetypes ────────────────────────────────────────────── */
/* Every one of the 51 pages is exactly one of these. That is the whole point:
   a user clicking from the sidebar to Pricing to a Trello callback should not be
   able to tell they crossed a boundary.

     .tk             app shell   — sidebar + topbar, rendered by js/shell.js
     .tk-page        public      — marketing, legal, docs; own header, no sidebar
     .tk-standalone  focused     — one centred card, no nav: OAuth callbacks,
                                   login, onboarding, e-mail verification

   They differ in layout only. Background, ink and type are identical. */

.tk, .tk-page, .tk-standalone {
  background: var(--tk-bg);
  color: var(--tk-text);
  font-family: var(--tk-font);
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
}

.tk h1, .tk h2, .tk h3, .tk h4,
.tk-page h1, .tk-page h2, .tk-page h3, .tk-page h4,
.tk-standalone h1, .tk-standalone h2, .tk-standalone h3, .tk-standalone h4 {
  font-family: var(--tk-font-head);
  font-weight: 700;
  letter-spacing: -0.015em;
  color: #f1f5f9;
}

:is(.tk, .tk-page, .tk-standalone) :is(code, pre, .tk-mono) { font-family: var(--tk-font-mono); }

/* Focus is a single, always-identical ring. Keyboard users should never have to
   hunt for where they are. */
:is(.tk, .tk-page, .tk-standalone) :focus-visible {
  outline: 2px solid var(--tk-accent);
  outline-offset: 2px;
  border-radius: var(--tk-r-sm);
}

/* ── .tk-page — public pages ──────────────────────────────────────────────── */
/* No sidebar (a visitor has nothing to navigate yet), but the same surfaces, so
   crossing from landing → pricing → login → dashboard is one continuous room. */

.tk-page-wrap   { max-width: 1120px; margin: 0 auto; padding: 0 24px; }
.tk-page-header {
  position: sticky; top: 0; z-index: 40;
  background: rgba(2, 6, 24, 0.86);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--tk-border);
}
.tk-page-header-inner {
  max-width: 1120px; margin: 0 auto; padding: 0 24px;
  height: 60px; display: flex; align-items: center; gap: 22px;
}
.tk-page-nav      { display: flex; align-items: center; gap: 4px; margin-left: auto; }
.tk-page-nav a {
  padding: 7px 12px; border-radius: var(--tk-r-sm);
  font-size: 13.5px; color: var(--tk-muted); text-decoration: none;
  transition: background .12s, color .12s;
}
.tk-page-nav a:hover           { background: var(--tk-raised); color: var(--tk-text); }
.tk-page-nav a[aria-current]   { color: var(--tk-text); font-weight: 600; }
.tk-page-section  { padding: 64px 0; }
.tk-page footer   { border-top: 1px solid var(--tk-border); background: var(--tk-bg-alt); color: var(--tk-muted); }
.tk-page hr       { border-color: var(--tk-border); }

@media (max-width: 720px) {
  .tk-page-nav a  { padding: 6px 8px; font-size: 12.5px; }
  .tk-page-section{ padding: 40px 0; }
}

/* ── .tk-standalone — one centred card ────────────────────────────────────── */
/* Callbacks and login used four different treatments: Trello-blue gradient,
   #F4F5F7 wash, gray-50, and a near-black #0A0F1E. One treatment now. */

.tk-standalone {
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.tk-standalone-card {
  width: 100%; max-width: 420px;
  background: var(--tk-card-solid);
  border: 1px solid var(--tk-border);
  border-radius: var(--tk-r-lg);
  padding: 32px 28px;
  text-align: center;
}
.tk-standalone-card--wide { max-width: 720px; text-align: left; }

/* ── App shell layout ─────────────────────────────────────────────────────── */
/* Rendered by js/shell.js. The sidebar is fixed and identical on every page --
   that constancy is the single biggest readability win over the old per-page
   navs, which had between 8 and 21 different links each. */

.tk-shell        { display: flex; min-height: 100vh; }

.tk-sidebar {
  position: fixed;
  inset: 0 auto 0 0;
  width: var(--tk-sidebar);
  background: var(--tk-bg-alt);
  border-right: 1px solid var(--tk-border);
  display: flex;
  flex-direction: column;
  z-index: 40;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.tk-main {
  flex: 1;
  min-width: 0;                       /* lets wide tables scroll instead of pushing the page */
  margin-left: var(--tk-sidebar);
}

.tk-content { padding: 28px 32px 64px; max-width: 1280px; }

@media (max-width: 1023px) {
  .tk-sidebar {
    transform: translateX(-100%);
    transition: transform 0.2s ease;
    box-shadow: 0 0 40px rgba(0, 0, 0, 0.5);
  }
  .tk-sidebar[data-open="true"] { transform: none; }
  .tk-main    { margin-left: 0; }
  .tk-content { padding: 20px 16px 56px; }
}

.tk-scrim {
  position: fixed;
  inset: 0;
  background: rgba(2, 6, 24, 0.6);
  z-index: 39;
}

/* ── Sidebar contents ─────────────────────────────────────────────────────── */

.tk-brand {
  display: flex;
  align-items: center;
  gap: 9px;
  height: var(--tk-topbar);
  padding: 0 16px;
  border-bottom: 1px solid var(--tk-border);
  font-family: var(--tk-font-head);
  font-weight: 800;
  letter-spacing: -0.02em;
  color: #f8fafc;
  text-decoration: none;
  flex: none;
}

.tk-brand-mark {
  width: 22px; height: 22px;
  border-radius: 6px;
  background: linear-gradient(135deg, var(--tk-accent) 0%, #4f46e5 100%);
  display: grid; place-items: center;
  font-size: 12px; color: #fff;
  flex: none;
}

.tk-nav       { padding: 12px 10px; flex: 1; }

.tk-nav-group { margin-bottom: 4px; }

.tk-nav-label {
  padding: 12px 8px 6px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--tk-faint);
}

.tk-nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 8px;
  margin-bottom: 1px;
  border-radius: var(--tk-r-sm);
  font-size: 13.5px;
  font-weight: 500;
  color: var(--tk-muted);
  text-decoration: none;
  transition: background-color 0.12s, color 0.12s;
}

.tk-nav-item:hover           { background: var(--tk-raised); color: var(--tk-text); }
.tk-nav-item svg             { width: 16px; height: 16px; flex: none; opacity: 0.85; }
.tk-nav-item[aria-current]   { background: var(--tk-accent-dim); color: #c7d2fe; font-weight: 600; }
.tk-nav-item[aria-current] svg { opacity: 1; color: var(--tk-accent-hi); }

/* Locked teaser. One line, one padlock, one link to pricing -- no modal, no
   popup. It should read as information, not as an obstacle. */
.tk-nav-item--locked         { color: var(--tk-faint); }
.tk-nav-item--locked:hover   { background: transparent; color: var(--tk-muted); }
.tk-nav-item--locked .tk-lock{ margin-left: auto; width: 13px; height: 13px; opacity: 0.75; }

.tk-sidebar-foot {
  border-top: 1px solid var(--tk-border);
  padding: 10px;
  flex: none;
}

/* ── Topbar ───────────────────────────────────────────────────────────────── */

.tk-topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  height: var(--tk-topbar);
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 20px 0 16px;
  background: rgba(2, 6, 24, 0.82);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--tk-border);
}

.tk-topbar h1 {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 0;
}

.tk-topbar-spacer { flex: 1; }

.tk-burger {
  display: none;
  background: none;
  border: 0;
  color: var(--tk-muted);
  padding: 6px;
  border-radius: var(--tk-r-sm);
  cursor: pointer;
}
.tk-burger:hover { background: var(--tk-raised); color: var(--tk-text); }
@media (max-width: 1023px) { .tk-burger { display: grid; place-items: center; } }

/* ── Page header ──────────────────────────────────────────────────────────── */

/* Flex so a page can hang one secondary action off the right of its title
   without a second wrapper. Pages with only a title/lead block are unaffected. */
.tk-page-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 22px;
}
.tk-page-head h1,
.tk-page-head h2 { font-size: 24px; line-height: 1.2; margin: 0 0 5px; }
.tk-page-head p  { color: var(--tk-muted); font-size: 13.5px; margin: 0; max-width: 68ch; }

/* ── Cards ────────────────────────────────────────────────────────────────── */

.tk-card {
  background: var(--tk-card);
  border: 1px solid var(--tk-border);
  border-radius: var(--tk-r-lg);
  padding: 18px;
}

.tk-card--flush { padding: 0; overflow: hidden; }

.tk-card-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--tk-border);
}
.tk-card-head h3 { font-size: 14px; font-weight: 600; margin: 0; }

.tk-grid {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}

/* ── Stat ─────────────────────────────────────────────────────────────────── */

.tk-stat-label {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--tk-faint);
  margin-bottom: 6px;
}
.tk-stat-value {
  font-family: var(--tk-font-head);
  font-size: 27px;
  font-weight: 700;
  line-height: 1.1;
  color: #f8fafc;
}
.tk-stat-sub { font-size: 12px; color: var(--tk-muted); margin-top: 4px; }

/* ── Buttons ──────────────────────────────────────────────────────────────── */
/* Exactly one primary per screen. That is the rule the old pages broke most
   often -- five equally loud buttons means the user has to read all five. */

.tk-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 8px 15px;
  border-radius: var(--tk-r-sm);
  border: 1px solid transparent;
  font-family: var(--tk-font);
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.25;
  cursor: pointer;
  text-decoration: none;
  transition: background-color 0.13s, border-color 0.13s, color 0.13s;
  white-space: nowrap;
}

.tk-btn:disabled, .tk-btn[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; }

.tk-btn--primary  { background: var(--tk-accent); color: #fff; }
.tk-btn--primary:hover:not(:disabled) { background: var(--tk-accent-hi); color: #fff; }

.tk-btn--ghost    { background: transparent; border-color: var(--tk-border-lt); color: var(--tk-text); }
.tk-btn--ghost:hover:not(:disabled) { background: var(--tk-raised); border-color: #33445e; }

.tk-btn--quiet    { background: transparent; color: var(--tk-muted); }
.tk-btn--quiet:hover:not(:disabled) { background: var(--tk-raised); color: var(--tk-text); }

.tk-btn--danger   { background: transparent; border-color: rgba(248,113,113,0.4); color: var(--tk-err); }
.tk-btn--danger:hover:not(:disabled) { background: rgba(248,113,113,0.1); }

.tk-btn--sm { padding: 5px 11px; font-size: 12.5px; }
.tk-btn svg { width: 15px; height: 15px; }

/* ── Forms ────────────────────────────────────────────────────────────────── */

.tk-field { margin-bottom: 15px; }

.tk-label {
  display: block;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--tk-text);
  margin-bottom: 5px;
}

.tk-hint { font-size: 12px; color: var(--tk-faint); margin-top: 5px; }

.tk-input, .tk-select, .tk-textarea {
  width: 100%;
  padding: 8px 11px;
  background: #060b1c;
  border: 1px solid var(--tk-border);
  border-radius: var(--tk-r-sm);
  color: var(--tk-text);
  font-family: var(--tk-font);
  font-size: 13.5px;
  transition: border-color 0.13s;
}
.tk-input::placeholder, .tk-textarea::placeholder { color: #4d5f78; }
.tk-input:hover, .tk-select:hover, .tk-textarea:hover { border-color: var(--tk-border-lt); }
.tk-input:focus, .tk-select:focus, .tk-textarea:focus { border-color: var(--tk-accent); outline: none; }
.tk-textarea { min-height: 92px; resize: vertical; }

/* ── Table ────────────────────────────────────────────────────────────────── */
/* Always inside .tk-table-wrap: wide tables must scroll in their own box, never
   push the page sideways. */

.tk-table-wrap { overflow-x: auto; }

.tk-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }

.tk-table th {
  text-align: left;
  padding: 9px 14px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--tk-faint);
  border-bottom: 1px solid var(--tk-border);
  white-space: nowrap;
}

.tk-table td { padding: 11px 14px; border-bottom: 1px solid var(--tk-border); }
.tk-table tbody tr:last-child td { border-bottom: 0; }
.tk-table tbody tr:hover { background: rgba(26, 35, 56, 0.5); }

/* ── Badge ────────────────────────────────────────────────────────────────── */

.tk-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 600;
  border: 1px solid transparent;
}
.tk-badge--neutral { background: var(--tk-raised);              color: var(--tk-muted); }
.tk-badge--ok      { background: rgba(52,211,153,0.12);  color: var(--tk-ok);   border-color: rgba(52,211,153,0.28); }
.tk-badge--warn    { background: rgba(251,191,36,0.12);  color: var(--tk-warn); border-color: rgba(251,191,36,0.28); }
.tk-badge--err     { background: rgba(248,113,113,0.12); color: var(--tk-err);  border-color: rgba(248,113,113,0.28); }
.tk-badge--info    { background: rgba(56,189,248,0.12);  color: var(--tk-info); border-color: rgba(56,189,248,0.28); }
.tk-badge--accent  { background: var(--tk-accent-dim);   color: var(--tk-accent-hi); border-color: rgba(99,102,241,0.3); }

/* ── Notice ───────────────────────────────────────────────────────────────── */

.tk-notice {
  display: flex;
  gap: 11px;
  padding: 12px 14px;
  border-radius: var(--tk-r);
  border: 1px solid var(--tk-border);
  background: var(--tk-card);
  font-size: 13px;
  color: var(--tk-muted);
  margin-bottom: 18px;
}
.tk-notice strong { color: var(--tk-text); font-weight: 600; }
.tk-notice--accent { border-color: rgba(99,102,241,0.35); background: var(--tk-accent-dim); }
.tk-notice--warn   { border-color: rgba(251,191,36,0.3);  background: rgba(251,191,36,0.07); }
.tk-notice--err    { border-color: rgba(248,113,113,0.3); background: rgba(248,113,113,0.07); }

/* ── Empty state ──────────────────────────────────────────────────────────── */
/* An empty screen must say what it is and what to do next. A blank panel reads
   as a broken page. */

.tk-empty { text-align: center; padding: 48px 24px; }
.tk-empty svg   { width: 34px; height: 34px; color: var(--tk-faint); margin: 0 auto 14px; }
.tk-empty h3    { font-size: 15px; margin: 0 0 6px; }
.tk-empty p     { color: var(--tk-muted); font-size: 13.5px; margin: 0 auto 18px; max-width: 46ch; }

/* ── Skeleton ─────────────────────────────────────────────────────────────── */

.tk-skeleton {
  background: linear-gradient(90deg, #101a2e 25%, #16213a 50%, #101a2e 75%);
  background-size: 200% 100%;
  animation: tk-shimmer 1.3s linear infinite;
  border-radius: var(--tk-r-sm);
}
@keyframes tk-shimmer { to { background-position: -200% 0; } }

@media (prefers-reduced-motion: reduce) {
  .tk-skeleton { animation: none; }
  .tk-sidebar  { transition: none; }
}

/* ── Utilities ────────────────────────────────────────────────────────────── */

.tk-muted  { color: var(--tk-muted); }
.tk-faint  { color: var(--tk-faint); }
.tk-hidden { display: none !important; }

.tk-row    { display: flex; align-items: center; gap: 10px; }
.tk-row--between { justify-content: space-between; }
.tk-stack  { display: flex; flex-direction: column; gap: 14px; }

/* Screen-reader-only, for icon-only controls. */
.tk-sr {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Scrollbars: thin and quiet, so they stop competing with content. */
.tk ::-webkit-scrollbar        { width: 9px; height: 9px; }
.tk ::-webkit-scrollbar-track  { background: transparent; }
.tk ::-webkit-scrollbar-thumb  { background: #1e2b42; border-radius: 5px; border: 2px solid var(--tk-bg); }
.tk ::-webkit-scrollbar-thumb:hover { background: #2b3b57; }

/* ══════════════════════════════════════════════════════════════════════════
   Legacy palette bridge
   --------------------------------------------------------------------------
   Roughly 30 pages were built on Trello's light palette (`bg-[#F4F5F7]
   text-[#172B4D]`) or on Tailwind's grey scale, and carried their text colour
   on <body>. When a page adopts a dark archetype that body class goes away, so
   anything without an explicit colour inherits --tk-text and goes light-on-white
   — headings on admin.html were all but invisible after the first pass.

   Rather than rewrite 30 pages of markup at once, the finite legacy palette is
   mapped onto the design tokens here. Two things at once: contrast is correct,
   and those pages stop looking like a different application.

   Scoped to the three archetype roots (inside .tk it is narrowed further to
   .tk-content, so it can never touch the shell chrome itself). A page that has
   not adopted an archetype is untouched. As pages are properly restyled to .tk-*
   components they stop matching these rules — this block shrinks to nothing and
   gets deleted. It is a bridge, not a foundation.

   Deliberately NOT remapped: text-white and bg-black/NN, which the legacy dark
   pages and modal scrims rely on and which are already correct.
   ══════════════════════════════════════════════════════════════════════════ */

/* Surfaces ─ white cards and the old page wash become shell surfaces. */
:is(.tk, .tk-page, .tk-standalone) .bg-white,
:is(.tk, .tk-page, .tk-standalone) .bg-\[\#FFFFFF\],
:is(.tk, .tk-page, .tk-standalone) .bg-\[\#F4F5F7\] {
  background-color: var(--tk-card-solid);
  border-color: var(--tk-border);
}
:is(.tk, .tk-page, .tk-standalone) .bg-gray-50,
:is(.tk, .tk-page, .tk-standalone) .bg-gray-100,
:is(.tk, .tk-page, .tk-standalone) .bg-gray-200,
:is(.tk, .tk-page, .tk-standalone) .bg-slate-50,
:is(.tk, .tk-page, .tk-standalone) .bg-slate-100 { background-color: var(--tk-bg-alt); }

:is(.tk, .tk-page, .tk-standalone) .hover\:bg-gray-50:hover,
:is(.tk, .tk-page, .tk-standalone) .hover\:bg-gray-100:hover,
:is(.tk, .tk-page, .tk-standalone) .hover\:bg-gray-200:hover { background-color: var(--tk-raised); }

/* Text ─ Trello ink and the neutral greys. */
:is(.tk, .tk-page, .tk-standalone) .text-\[\#172B4D\],
:is(.tk, .tk-page, .tk-standalone) .text-black,
:is(.tk, .tk-page, .tk-standalone) .text-gray-700,
:is(.tk, .tk-page, .tk-standalone) .text-gray-800,
:is(.tk, .tk-page, .tk-standalone) .text-gray-900,
:is(.tk, .tk-page, .tk-standalone) .text-slate-700,
:is(.tk, .tk-page, .tk-standalone) .text-slate-800,
:is(.tk, .tk-page, .tk-standalone) .text-slate-900 { color: var(--tk-text); }

:is(.tk, .tk-page, .tk-standalone) .text-\[\#5E6C84\],
:is(.tk, .tk-page, .tk-standalone) .text-gray-400,
:is(.tk, .tk-page, .tk-standalone) .text-gray-500,
:is(.tk, .tk-page, .tk-standalone) .text-gray-600,
:is(.tk, .tk-page, .tk-standalone) .text-slate-500,
:is(.tk, .tk-page, .tk-standalone) .text-slate-600 { color: var(--tk-muted); }

:is(.tk, .tk-page, .tk-standalone) .text-gray-300 { color: var(--tk-faint); }
:is(.tk, .tk-page, .tk-standalone) .hover\:text-\[\#172B4D\]:hover { color: var(--tk-text); }

/* Borders and dividers. */
:is(.tk, .tk-page, .tk-standalone) .border,
:is(.tk, .tk-page, .tk-standalone) .border-gray-100,
:is(.tk, .tk-page, .tk-standalone) .border-gray-200,
:is(.tk, .tk-page, .tk-standalone) .border-gray-300,
:is(.tk, .tk-page, .tk-standalone) .border-slate-200,
:is(.tk, .tk-page, .tk-standalone) .border-slate-300 { border-color: var(--tk-border); }
:is(.tk, .tk-page, .tk-standalone) .divide-gray-100 > * + *,
:is(.tk, .tk-page, .tk-standalone) .divide-gray-200 > * + * { border-color: var(--tk-border); }

/* Accents ─ Trello blue answers to the locked indigo; status colours to tokens. */
:is(.tk, .tk-page, .tk-standalone) .text-\[\#0079BF\]                { color: var(--tk-accent-hi); }
:is(.tk, .tk-page, .tk-standalone) .hover\:text-\[\#0079BF\]:hover   { color: var(--tk-accent-hi); }
:is(.tk, .tk-page, .tk-standalone) .border-\[\#0079BF\]              { border-color: var(--tk-accent); }
:is(.tk, .tk-page, .tk-standalone) .bg-\[\#0079BF\]                  { background-color: var(--tk-accent); color: #fff; }
:is(.tk, .tk-page, .tk-standalone) .hover\:bg-\[\#026AA7\]:hover     { background-color: #4f46e5; }
:is(.tk, .tk-page, .tk-standalone) .text-\[\#EB5A46\]                { color: var(--tk-err); }
:is(.tk, .tk-page, .tk-standalone) .bg-\[\#EB5A46\]                  { background-color: var(--tk-err); color: #1b0f0f; }
:is(.tk, .tk-page, .tk-standalone) .text-\[\#61BD4F\]                { color: var(--tk-ok); }
:is(.tk, .tk-page, .tk-standalone) .bg-\[\#61BD4F\]                  { background-color: var(--tk-ok); color: #04231a; }

/* Form controls ─ legacy inputs were white boxes with a grey rule. */
:is(.tk, .tk-page, .tk-standalone) input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
:is(.tk, .tk-page, .tk-standalone) select,
:is(.tk, .tk-page, .tk-standalone) textarea {
  background-color: var(--tk-bg-alt);
  border-color: var(--tk-border);
  color: var(--tk-text);
}
:is(.tk, .tk-page, .tk-standalone) input::placeholder,
:is(.tk, .tk-page, .tk-standalone) textarea::placeholder { color: var(--tk-faint); }

/* Interaction states ─ the ones that only break on hover, so a screenshot of the
   resting page looks fine and the bug ships. A hover must not turn the surface
   light under light text (admin's table rows), and it must not darken an icon
   into the card it sits on (the "×" close buttons went gray-400 → gray-600). */
:is(.tk, .tk-page, .tk-standalone) .hover\:bg-\[\#F4F5F7\]:hover  { background-color: var(--tk-raised); }
:is(.tk, .tk-page, .tk-standalone) .hover\:text-gray-600:hover,
:is(.tk, .tk-page, .tk-standalone) .hover\:text-gray-700:hover    { color: var(--tk-text); }

/* Trello blue on the edges and tints the rules above did not reach. */
:is(.tk, .tk-page, .tk-standalone) .hover\:border-\[\#0079BF\]:hover { border-color: var(--tk-accent); }
:is(.tk, .tk-page, .tk-standalone) .border-\[\#0079BF\]\/30          { border-color: rgba(99, 102, 241, .35); }
:is(.tk, .tk-page, .tk-standalone) .border-\[\#EB5A46\]              { border-color: var(--tk-err); }
:is(.tk, .tk-page, .tk-standalone) .bg-\[\#E4F0FB\]                  { background-color: rgba(99, 102, 241, .12); }
:is(.tk, .tk-page, .tk-standalone) .hover\:bg-\[\#C8E0F5\]:hover     { background-color: rgba(99, 102, 241, .22); }

/* bg-white/60 is opaque enough to swallow light text (ai.html's code block).
   The low alphas — bg-white/5, /10, border-white/10 — are dark-surface overlays
   and already correct, so they are left alone. */
:is(.tk, .tk-page, .tk-standalone) .bg-white\/60 { background-color: var(--tk-bg-alt); }

/* purple-600 (#9333ea) is a light-mode accent. On --tk-card-solid it lands near
   3:1 — arguably survivable for a 2xl bold stat number, but not for the 10px
   plan-override note in the admin table. Lifted to purple-400. The solid
   `bg-purple-600 text-white` badges are unaffected: white on that fill is fine. */
:is(.tk, .tk-page, .tk-standalone) .text-purple-600 { color: #c084fc; }

/* NOTE on the bridge scope, applied to all 104 selectors above and below.
   These were originally scoped `.tk .tk-content`, but .tk-content does not
   exist in any page's markup — js/shell.js creates it when it mounts. So every
   bridge rule was silently conditional on the shell having mounted, and a page
   whose shell failed (API error, offline, an unauthenticated render) fell back
   to white cards on a dark body: the original bug, restored by a failure path.
   Scoping to .tk instead makes the palette a property of the page, not of a
   script that ran. Verified safe: js/shell.js emits no Tailwind utility classes
   at all, so widening cannot reach the shell's own chrome. */

/* ── Tailwind neutral scale ──────────────────────────────────────────────────
   The last layer of the four-palette problem, and the one no token change can
   reach: 1095 Tailwind utility classes across 37 pages, written when those
   pages were light. `bg-white` is a literal #fff in Tailwind's own stylesheet,
   so a page can sit on --tk-bg and still show white cards. That is the
   "egyszer feher - egyszer kek masszor fekete" report, exactly.

   Why a bridge and not an edit: rewriting 1095 call-sites across 37 files is a
   large diff over live pages for no behavioural gain, and every new page would
   reintroduce the problem. Two nested class selectors (0,2,0) outrank
   Tailwind's single utility (0,1,0) regardless of load order, so this needs no
   !important and stays inert on any page that is not an archetype.

   Not remapped on purpose: text-white / border-white / bg-white with a low
   alpha (bg-white/5, /10) are already dark-surface idioms and read correctly.
   -------------------------------------------------------------------------- */

/* Surfaces */
:is(.tk, .tk-page, .tk-standalone) .bg-white      { background-color: var(--tk-card-solid); }
:is(.tk, .tk-page, .tk-standalone) .bg-gray-50    { background-color: var(--tk-bg-alt); }
:is(.tk, .tk-page, .tk-standalone) .bg-gray-100   { background-color: var(--tk-raised); }
:is(.tk, .tk-page, .tk-standalone) .bg-gray-200,
:is(.tk, .tk-page, .tk-standalone) .bg-gray-300   { background-color: var(--tk-raised); }
:is(.tk, .tk-page, .tk-standalone) .bg-gray-500,
:is(.tk, .tk-page, .tk-standalone) .bg-gray-600   { background-color: var(--tk-border-lt); }
/* bg-black is off-palette rather than wrong — it reads as a seam against
   --tk-bg (#020618), which is a blue-black, not a true black. */
:is(.tk, .tk-page, .tk-standalone) .bg-black      { background-color: var(--tk-bg); }

/* Tinted status surfaces — kept as tints, moved onto the palette's hues. */
:is(.tk, .tk-page, .tk-standalone) .bg-blue-50,
:is(.tk, .tk-page, .tk-standalone) .bg-blue-100,
:is(.tk, .tk-page, .tk-standalone) .bg-indigo-50,
:is(.tk, .tk-page, .tk-standalone) .bg-indigo-100,
:is(.tk, .tk-page, .tk-standalone) .bg-purple-100 { background-color: var(--tk-accent-dim); }
:is(.tk, .tk-page, .tk-standalone) .bg-green-50,
:is(.tk, .tk-page, .tk-standalone) .bg-green-100  { background-color: rgba(52, 211, 153, .14); }
:is(.tk, .tk-page, .tk-standalone) .bg-red-50,
:is(.tk, .tk-page, .tk-standalone) .bg-red-100    { background-color: rgba(248, 113, 113, .14); }
:is(.tk, .tk-page, .tk-standalone) .bg-yellow-50,
:is(.tk, .tk-page, .tk-standalone) .bg-yellow-100 { background-color: rgba(251, 191, 36, .12); }

/* Edges */
:is(.tk, .tk-page, .tk-standalone) .border-gray-50,
:is(.tk, .tk-page, .tk-standalone) .border-gray-100,
:is(.tk, .tk-page, .tk-standalone) .border-gray-200,
:is(.tk, .tk-page, .tk-standalone) .border-gray-300 { border-color: var(--tk-border); }
:is(.tk, .tk-page, .tk-standalone) .border-gray-500 { border-color: var(--tk-border-lt); }
/* The neutral member of organization.html's plan-badge set — its blue, green
   and amber siblings are tinted above, so leaving this one at Tailwind's grey
   made "free" the only badge with a different weight. */
:is(.tk, .tk-page, .tk-standalone) .bg-gray-600\/30    { background-color: rgba(144, 161, 185, .16); }
:is(.tk, .tk-page, .tk-standalone) .border-gray-500\/30 { border-color: var(--tk-border-lt); }
:is(.tk, .tk-page, .tk-standalone) .divide-gray-50 > * + *,
:is(.tk, .tk-page, .tk-standalone) .divide-gray-100 > * + * { border-color: var(--tk-border); }

/* Ink. text-black is the outright invisible one; the gray ramp is a contrast
   question — gray-600 on --tk-card-solid is about 2.7:1. */
:is(.tk, .tk-page, .tk-standalone) .text-black,
:is(.tk, .tk-page, .tk-standalone) .text-gray-700,
:is(.tk, .tk-page, .tk-standalone) .text-gray-800,
:is(.tk, .tk-page, .tk-standalone) .text-gray-900 { color: var(--tk-text); }
:is(.tk, .tk-page, .tk-standalone) .text-gray-300,
:is(.tk, .tk-page, .tk-standalone) .text-gray-400,
:is(.tk, .tk-page, .tk-standalone) .text-gray-500,
:is(.tk, .tk-page, .tk-standalone) .text-gray-600 { color: var(--tk-muted); }
:is(.tk, .tk-page, .tk-standalone) .text-blue-800   { color: var(--tk-accent-hi); }
:is(.tk, .tk-page, .tk-standalone) .text-green-800  { color: var(--tk-ok); }
:is(.tk, .tk-page, .tk-standalone) .text-red-800    { color: var(--tk-err); }
:is(.tk, .tk-page, .tk-standalone) .text-yellow-800 { color: var(--tk-warn); }
:is(.tk, .tk-page, .tk-standalone) .placeholder-gray-600::placeholder { color: var(--tk-faint); }

/* Hover states. These outrank the resting rules above on their own (two class
   selectors plus :hover), so they have to be restated, not inherited. */
:is(.tk, .tk-page, .tk-standalone) .hover\:bg-white:hover    { background-color: var(--tk-raised); }
:is(.tk, .tk-page, .tk-standalone) .hover\:bg-gray-50:hover,
:is(.tk, .tk-page, .tk-standalone) .hover\:bg-gray-100:hover,
:is(.tk, .tk-page, .tk-standalone) .hover\:bg-gray-200:hover { background-color: var(--tk-raised); }
:is(.tk, .tk-page, .tk-standalone) .hover\:text-gray-300:hover { color: var(--tk-text); }
:is(.tk, .tk-page, .tk-standalone) .hover\:border-gray-300:hover { border-color: var(--tk-border-lt); }

/* ── Tailwind blue ramp ──────────────────────────────────────────────────────
   The last hue outside the palette. 21 pages still carry Tailwind blue
   (#2563eb and its ramp) next to the locked indigo #6366f1: two blues, close
   enough to look like a mistake and far enough apart to see. It is the literal
   "egyszer kek" half of the owner's report, and the neutral-scale block above
   does not touch it because blue is not a neutral.

   Folded onto the one accent. The dark end (600/700/800) additionally has to
   move because those were ink for a *light* surface — text-blue-700 on
   --tk-card-solid is about 2.4:1, i.e. unreadable, not merely off-palette.

   The alpha variants are listed one by one rather than matched loosely: they
   are status-badge tints (`bg-blue-500/20 text-blue-300 border-blue-500/40`),
   and a badge that keeps its tint but loses its border reads as broken. Blue
   there means "in progress"; against green/amber/red it stays distinguishable
   as indigo, so no signal is lost by moving the hue. */

/* Ink — the light end stays light, the dark end has to move to stay legible. */
:is(.tk, .tk-page, .tk-standalone) .text-blue-100,
:is(.tk, .tk-page, .tk-standalone) .text-blue-200,
:is(.tk, .tk-page, .tk-standalone) .text-blue-300,
:is(.tk, .tk-page, .tk-standalone) .text-blue-400,
:is(.tk, .tk-page, .tk-standalone) .text-blue-600,
:is(.tk, .tk-page, .tk-standalone) .text-blue-700 { color: var(--tk-accent-hi); }
:is(.tk, .tk-page, .tk-standalone) .hover\:text-blue-200:hover,
:is(.tk, .tk-page, .tk-standalone) .hover\:text-blue-600:hover { color: var(--tk-accent-hi); }

/* Solid fills — these are primary buttons wearing the wrong blue. */
:is(.tk, .tk-page, .tk-standalone) .bg-blue-500,
:is(.tk, .tk-page, .tk-standalone) .bg-blue-600 { background-color: var(--tk-accent); color: #fff; }
:is(.tk, .tk-page, .tk-standalone) .hover\:bg-blue-700:hover { background-color: #4f46e5; }

/* Tints — badge and callout surfaces. */
:is(.tk, .tk-page, .tk-standalone) .bg-blue-500\/10,
:is(.tk, .tk-page, .tk-standalone) .bg-blue-950\/40 { background-color: rgba(99, 102, 241, .10); }
:is(.tk, .tk-page, .tk-standalone) .bg-blue-500\/20,
:is(.tk, .tk-page, .tk-standalone) .bg-blue-600\/30 { background-color: rgba(99, 102, 241, .20); }
:is(.tk, .tk-page, .tk-standalone) .hover\:bg-blue-50:hover,
:is(.tk, .tk-page, .tk-standalone) .hover\:bg-blue-50\/40:hover { background-color: var(--tk-accent-dim); }

/* Edges and rings. */
:is(.tk, .tk-page, .tk-standalone) .border-blue-100,
:is(.tk, .tk-page, .tk-standalone) .border-blue-200,
:is(.tk, .tk-page, .tk-standalone) .border-blue-300 { border-color: rgba(99, 102, 241, .30); }
:is(.tk, .tk-page, .tk-standalone) .border-blue-500\/30,
:is(.tk, .tk-page, .tk-standalone) .border-blue-500\/40,
:is(.tk, .tk-page, .tk-standalone) .border-blue-700\/30 { border-color: rgba(99, 102, 241, .38); }
:is(.tk, .tk-page, .tk-standalone) .hover\:border-blue-500:hover { border-color: var(--tk-accent); }
:is(.tk, .tk-page, .tk-standalone) .ring-blue-100,
:is(.tk, .tk-page, .tk-standalone) .focus\:ring-blue-300:focus { --tw-ring-color: var(--tk-accent); }

/* ── The one place a literal white is still correct ──────────────────────────
   A switch knob is the moving part of a control, read against its track, not a
   surface — so it is the single element on the site that must stay #fff. The
   .bg-white rule above turned pricing.html's billing toggle into a dark dot on
   a light track, i.e. invisible in its "off" state. It carries this class
   *instead of* .bg-white; adding one would lose, since the bridge selector is
   two classes deep. */
.tk-knob { background-color: #fff; }

/* ── Ink that sits on a light fill, not on a surface ─────────────────────────
   The bridge lifts .text-black / .text-gray-900 to near-white, because on a
   dark card that ink was invisible. But seven elements had it on a *light*
   fill on purpose — pricing's indigo "BEST VALUE" pill and Stripe CTA,
   settings' and admin's amber plan badges — and lifting it there produced the
   mirror-image bug: near-white on light indigo/amber.

   CSS cannot see what an element's fill is (it arrives via an inline style or
   a bg utility), so these opt out by name rather than by guesswork. */
.tk-ink-on-light { color: #0b1020; }
