/* ── Global: Force dark mode — light mode coming soon ── */
html {
  color-scheme: dark !important;
}
html:not(.dark) {
  /* Force dark class on page load via JS */
}

/*
 * EpiSAP Vault — Mobile & Light-Mode Fixes
 * Applied via after_request CSS injection (app.py)
 * Covers issues #1–16 from iPhone audit, April 2026
 */

/* ============================================================
   ISSUE #7 & GLOBAL: Prevent horizontal overflow everywhere
   ============================================================ */
html {
  overflow-x: hidden;
  max-width: 100%;
  /* v19_64.0 — anchor-link jumps must clear the sticky nav (h-16 = 4rem).
     Without this, anchor scrolls land BEHIND the nav and look like overlap. */
  scroll-padding-top: 4.5rem;
}
body {
  /* Use clip instead of hidden: same scroll prevention but does NOT create
     a new iOS-Safari scroll container that clips position:fixed elements
     (the mobile slide-out menu is position:fixed and was being clipped). */
  overflow-x: clip;
  max-width: 100%;
  /* v19_64.0 — Windows scrollbar (~17px) was pushing nav contents into
     overlap. Reserve gutter regardless of scroll state. Chrome 94+ /
     Firefox 97+ / Safari 18.2+; older Safari ignores silently — non-issue. */
  scrollbar-gutter: stable;
}

/* ============================================================
   ISSUE #8: Remove excessive bottom whitespace on all pages
   ============================================================ */
main, [role="main"], .min-h-screen {
  padding-bottom: 2rem !important;
}

/* Remove giant mb/pb utility classes that cause blank space */
.mb-32, .mb-24, .mb-20, .pb-32, .pb-24, .pb-20 {
  margin-bottom: 2rem !important;
  padding-bottom: 0 !important;
}

/* ============================================================
   MOBILE MENU PANEL: Ensure slide-out is fully visible when open
   (Fixes iOS Safari clipping bug caused by overflow:hidden on body)
   ============================================================ */
/* The menu panel itself — guarantee visibility and full height */
#mobile-menu {
  -webkit-overflow-scrolling: touch;
  overflow-y: auto;
  overflow-x: hidden;
  /* Prevent any ancestor overflow from clipping */
  will-change: transform;
  /* Explicit height and z-index to avoid iOS collapse */
  height: 100dvh !important; /* dvh = dynamic viewport height (avoids Safari chrome) */
  height: 100vh !important; /* fallback */
  z-index: 9999 !important;
}

/* When menu is open (translate-x-full removed), ensure content shows */
#mobile-menu:not([class*="translate-x-full"]) {
  display: block !important;
  visibility: visible !important;
}

/* Ensure the inner flex-col container fills the panel height */
#mobile-menu > div {
  min-height: 100%;
  display: flex !important;
  flex-direction: column !important;
}

/* Nav links inside the mobile menu — always visible when parent is shown */
#mobile-menu nav,
#mobile-menu nav a,
#mobile-menu nav button,
#mobile-menu .space-y-1 a,
#mobile-menu .space-y-1 button {
  display: flex !important;
  visibility: visible !important;
  opacity: 1 !important;
}

#mobile-menu nav {
  flex: 1 !important;
  display: flex !important;
  flex-direction: column !important;
  overflow-y: auto !important;
}

/* Mobile overlay — ensure it's above main content but below the menu */
#mobile-overlay {
  z-index: 9998 !important;
}

/* ============================================================
   ISSUE #9: Sticky nav — ensure it stays fixed on scroll
   ============================================================ */
nav.sticky, nav[class*="sticky"] {
  position: sticky !important;
  top: 0 !important;
  z-index: 50 !important;
  /* Force GPU layer for smooth sticky on iOS Safari */
  -webkit-transform: translateZ(0);
  transform: translateZ(0);
  will-change: transform;
  /* v19.42: Allow absolutely/fixed-positioned dropdown panels to render
     outside the nav's own height. overflow:hidden was clipping the panels
     at the nav's 64px boundary even when display:block was set correctly. */
  overflow: visible !important;
}

/* v19.42: Also ensure the nav's direct container div allows overflow */
nav.sticky > div, nav[class*="sticky"] > div {
  overflow: visible !important;
}

/* Theme toggle button — keep visible and accessible */
#theme-toggle,
button[onclick*="toggleTheme"],
button[aria-label*="theme"],
button[aria-label*="Theme"],
button[title*="theme"],
button[title*="Theme"] {
  position: relative !important;
  z-index: 55 !important;
  flex-shrink: 0 !important;
}

/* ============================================================
   ISSUE #2: AI Search mobile menu button — remove permanent
   gradient highlight (should only highlight on hover)
   ============================================================ */
/* Target the AI Search button in the mobile slide-out menu */
button[onclick*="openAISearch"],
a[onclick*="openAISearch"] {
  background: transparent !important;
  background-image: none !important;
}

button[onclick*="openAISearch"]:hover,
a[onclick*="openAISearch"]:hover {
  background-image: linear-gradient(to right, rgba(88,28,235,0.25), rgba(30,64,175,0.25)) !important;
}

/* ============================================================
   ISSUE #1: Badge overflow — "Quantum Cloaked" / "Post-Quantum Ready"
   Badge cards must not overflow horizontally
   ============================================================ */
/* Badge grid and individual badge cards */
.badge-grid,
[class*="badge-grid"],
.grid.grid-cols-2,
.grid.grid-cols-3,
.grid.grid-cols-4 {
  overflow: hidden;
}

/* Badge name text — truncate or wrap instead of overflowing */
.badge-card,
[class*="badge-card"],
.rounded-xl.p-4,
.rounded-2xl.p-4 {
  overflow: hidden;
  word-break: break-word;
}

/* Badge label text specifically */
.badge-card p,
.badge-card span,
.badge-card h3,
[class*="badge"] p,
[class*="badge"] span,
[class*="badge"] h3 {
  overflow-wrap: break-word;
  word-break: break-word;
  hyphens: auto;
}

/* Recent badges horizontal strip — make scrollable not clipped */
.flex.space-x-4.overflow-x-auto,
.flex.gap-4.overflow-x-auto,
[class*="recent-badges"],
.badges-strip {
  overflow-x: auto !important;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  flex-wrap: nowrap !important;
}

.flex.space-x-4.overflow-x-auto::-webkit-scrollbar,
.flex.gap-4.overflow-x-auto::-webkit-scrollbar {
  display: none;
}

/* Badge circle images — constrain to their container */
.badge-card img,
[class*="badge"] img,
img[alt*="badge"],
img[alt*="Badge"] {
  max-width: 100%;
  height: auto;
  object-fit: contain;
}

/* ============================================================
   ISSUE #3 & #11: Tab content overflow — Challenges, Admin
   dashboard, TTO, Grants — horizontal tab bars scroll,
   content panels don't bleed off screen
   ============================================================ */
/* Tab nav bars — scrollable on mobile */
[role="tablist"],
.tab-nav,
.flex.border-b,
.flex.space-x-1.border-b,
.flex.space-x-2.border-b,
nav[aria-label*="tab"],
nav[aria-label*="Tab"] {
  overflow-x: auto !important;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  flex-wrap: nowrap !important;
  padding-bottom: 1px; /* prevent clipping bottom border */
}

[role="tablist"]::-webkit-scrollbar,
.tab-nav::-webkit-scrollbar {
  display: none;
}

/* Tab buttons — prevent shrinking */
[role="tab"],
.tab-btn,
button[data-tab],
.flex.border-b button,
.flex.space-x-1.border-b button,
.flex.space-x-2.border-b button {
  flex-shrink: 0 !important;
  white-space: nowrap;
}

/* Tab panel content — no horizontal overflow */
[role="tabpanel"],
.tab-panel,
[id$="-tab"],
[id*="tab-content"],
[data-tab-content] {
  overflow-x: hidden;
  max-width: 100%;
}

/* Tables inside tabs — scrollable */
[role="tabpanel"] table,
.tab-panel table,
.overflow-x-auto table {
  min-width: 100%;
}

.overflow-x-auto {
  -webkit-overflow-scrolling: touch;
}

/* ============================================================
   ISSUE #4: API Key "Generate Key" — stack form on mobile
   ============================================================ */
@media (max-width: 640px) {
  /* The generate key form row — stack vertically */
  form[action*="api_key"] .flex.items-end.space-x-3,
  form[action*="api"] .flex.items-end.space-x-3,
  .flex.items-end.space-x-3:has(input[name*="key"]),
  .flex.items-end.space-x-3:has(input[placeholder*="key"]),
  .flex.items-end.space-x-3:has(input[placeholder*="Key"]) {
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 0.75rem !important;
    space-x: 0 !important;
  }

  form[action*="api_key"] .flex.items-end.space-x-3 > *,
  form[action*="api"] .flex.items-end.space-x-3 > *,
  .flex.items-end.space-x-3:has(input[name*="key"]) > * {
    width: 100% !important;
    margin-left: 0 !important;
  }

  /* General: any flex row with an input + button — stack on mobile */
  .flex.items-end > input + button,
  .flex.items-center > input + button {
    width: 100%;
  }
}

/* ============================================================
   ISSUE #6: Export CSV/JSON — ensure readable text on buttons
   ============================================================ */
/* Force white text on dark action buttons */
a[href*="audit_export"],
a[href*="export"],
button[onclick*="export"],
.bg-gray-700,
.bg-gray-800,
.bg-gray-600 {
  color: #ffffff !important;
}

a[href*="audit_export"]:hover,
a[href*="export"]:hover,
.bg-gray-700:hover,
.bg-gray-600:hover {
  color: #f3f4f6 !important;
}

/* In light mode, export buttons need explicit contrast */
html:not(.dark) a[href*="audit_export"],
html:not(.dark) a[href*="export"] {
  color: #ffffff !important;
}

/* ============================================================
   ISSUE #9 & GLOBAL: Font consistency — Inter everywhere,
   monospace only for code blocks
   ============================================================ */
body, html, *, *::before, *::after {
  font-family: 'Inter', ui-sans-serif, system-ui, -apple-system,
               BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
}

/* Restore monospace only for actual code elements */
code, pre, kbd, samp,
.font-mono:not([class*="badge"]):not([class*="name"]):not([class*="label"]) {
  font-family: 'JetBrains Mono', 'Fira Code', 'Fira Mono',
               ui-monospace, SFMono-Regular, Menlo, Monaco,
               Consolas, monospace !important;
}

/* Font size consistency on mobile */
@media (max-width: 640px) {
  body { font-size: 0.9375rem; }
  h1 { font-size: 1.5rem !important; }
  h2 { font-size: 1.25rem !important; }
  h3 { font-size: 1.1rem !important; }
  p, li, td, th, span:not(.text-xs):not(.text-sm) { font-size: 0.9375rem; }
  .text-2xl { font-size: 1.35rem !important; }
  .text-3xl { font-size: 1.5rem !important; }
  .text-4xl { font-size: 1.75rem !important; }
}

/* ============================================================
   ISSUE #10 & #16: Light mode — general text contrast
   ============================================================ */
/* In light mode, pale grays are hard to read — boost contrast */
html:not(.dark) .text-gray-400 {
  color: #4B5563 !important; /* gray-600 — readable on white */
}

html:not(.dark) .text-gray-500 {
  color: #374151 !important; /* gray-700 */
}

html:not(.dark) .text-gray-300 {
  color: #4B5563 !important;
}

html:not(.dark) .text-gray-200 {
  color: #374151 !important;
}

/* Muted/secondary text in light mode */
html:not(.dark) .text-slate-400,
html:not(.dark) .text-slate-300 {
  color: #4B5563 !important;
}

/* Body text default in light mode */
html:not(.dark) body {
  color: #111827; /* gray-900 */
}

/* Card/surface text in light mode */
html:not(.dark) .bg-navy-light,
html:not(.dark) [class*="bg-navy"],
html:not(.dark) [class*="surface"] {
  color: #111827;
}

/* ============================================================
   ISSUE #9 (badge light mode): Unearned badge cards —
   faint text contrast fix
   ============================================================ */
html:not(.dark) .badge-card,
html:not(.dark) [class*="badge-card"],
html:not(.dark) .opacity-50,
html:not(.dark) .opacity-40 {
  color: #374151 !important; /* gray-700 — visible on light bg */
}

html:not(.dark) .badge-card p,
html:not(.dark) .badge-card span,
html:not(.dark) .badge-card h3 {
  color: #374151 !important;
}

/* Unearned state — slightly faded but still readable */
html:not(.dark) [class*="unearned"],
html:not(.dark) [data-earned="false"] {
  opacity: 0.65 !important;
  color: #374151 !important;
}

/* ============================================================
   ISSUE #15: Obfuscate page — monospace blue-purple
   unreadable in light mode
   ============================================================ */
/* Obfuscate output / code display areas in light mode */
html:not(.dark) .font-mono,
html:not(.dark) pre,
html:not(.dark) code {
  color: #111827 !important; /* near-black — readable on any bg */
  background-color: #F3F4F6 !important; /* gray-100 bg */
}

/* Specifically the purple/blue colored text on obfuscate page */
html:not(.dark) .text-purple-400,
html:not(.dark) .text-blue-400,
html:not(.dark) .text-indigo-400 {
  color: #4338CA !important; /* indigo-700 — dark enough on white */
}

html:not(.dark) .text-purple-300,
html:not(.dark) .text-blue-300,
html:not(.dark) .text-indigo-300 {
  color: #3730A3 !important; /* indigo-800 */
}

/* Obfuscated output textarea */
html:not(.dark) textarea[readonly],
html:not(.dark) [class*="obfuscat"] .font-mono,
html:not(.dark) #obfuscated-output,
html:not(.dark) [id*="obfuscat"] {
  color: #111827 !important;
  background-color: #F9FAFB !important;
  border-color: #D1D5DB !important;
}

/* ============================================================
   ISSUE #11: Admin dashboard — content overflow fix
   ============================================================ */
/* Admin tables and content boxes */
.admin-content,
[class*="admin"] table,
#admin-dashboard,
[id*="admin"] table {
  overflow-x: auto;
  max-width: 100%;
  display: block;
}

@media (max-width: 768px) {
  /* Stats cards grid — allow wrapping */
  .grid.grid-cols-4,
  .grid.grid-cols-3 {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  }

  .grid.grid-cols-5,
  .grid.grid-cols-6 {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  }
}

@media (max-width: 480px) {
  .grid.grid-cols-4,
  .grid.grid-cols-3,
  .grid.grid-cols-2 {
    grid-template-columns: repeat(1, minmax(0, 1fr)) !important;
  }
}

/* ============================================================
   ISSUE #12: TTO Dashboard — License tab cut off
   ============================================================ */
/* All tab content containers — ensure full width */
.tab-content,
[id*="license"],
[id*="pipeline"],
[id*="revenue"],
[id*="grants"] {
  overflow-x: hidden;
  max-width: 100%;
}

/* Long text in TTO tables — allow wrapping */
[id*="license"] td,
[id*="pipeline"] td,
[id*="revenue"] td {
  word-break: break-word;
  min-width: 80px;
}

/* ============================================================
   ISSUE #13: Revenue tab showing Pipeline content (JS fix)
   Force correct tab panel visibility using CSS
   ============================================================ */
/* If JS tab switching misfires, ensure only active panel shows */
[role="tabpanel"]:not(.active):not([aria-selected="true"]) {
  /* Don't override display — let JS handle it.
     This fallback catches panels that use opacity: */
}

/* Specific TTO tab fix — panels should be hidden by default */
.tab-panel:not(.active) {
  display: none !important;
}

.tab-panel.active {
  display: block !important;
}

/* ============================================================
   GLOBAL MOBILE: Ensure all page content stays within bounds
   ============================================================ */
@media (max-width: 768px) {
  /* Main content area */
  .container, .max-w-7xl, .max-w-6xl, .max-w-5xl,
  .max-w-4xl, .max-w-3xl, .max-w-2xl {
    padding-left: 1rem !important;
    padding-right: 1rem !important;
    overflow-x: hidden;
  }

  /* Cards and panels */
  .card, .panel, .rounded-xl, .rounded-2xl {
    max-width: 100%;
    overflow: hidden;
  }

  /* Wide flex rows — allow wrapping */
  .flex.items-center.justify-between {
    flex-wrap: wrap;
    gap: 0.5rem;
  }

  /* Full-width buttons on mobile */
  .btn-primary, .btn-secondary,
  button[type="submit"],
  a[class*="btn"] {
    min-width: 0;
  }

  /* Prevent long strings from overflowing */
  td, th, p, span, div {
    overflow-wrap: break-word;
    word-break: break-word;
  }

  /* Tables — horizontal scroll wrapper */
  table {
    display: block;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    width: 100%;
  }

  /* Input fields full width */
  input[type="text"],
  input[type="email"],
  input[type="password"],
  input[type="search"],
  select,
  textarea {
    max-width: 100% !important;
    box-sizing: border-box;
  }
}

/* ============================================================
   LIGHT MODE: Surface and card backgrounds
   ============================================================ */
html:not(.dark) {
  --c-bg: #F9FAFB;
  --c-surface: #FFFFFF;
  --c-text-primary: #111827;
  --c-text-secondary: #374151;
  --c-border: #E5E7EB;
}

html:not(.dark) body {
  background-color: var(--c-bg);
  color: var(--c-text-primary);
}

/* Nav in light mode — ensure contrast */
html:not(.dark) nav {
  background-color: #1E293B !important; /* keep dark navy nav */
}

html:not(.dark) nav a,
html:not(.dark) nav button {
  color: #E2E8F0 !important;
}

html:not(.dark) nav a:hover,
html:not(.dark) nav button:hover {
  color: #FFFFFF !important;
}

/* Nav SVG icons — keep visible on dark nav in light mode */
html:not(.dark) nav svg,
html:not(.dark) nav svg * {
  color: inherit !important;
  stroke: currentColor;
}

/* Override the global blue/purple/indigo text fixes inside nav — nav stays dark */
html:not(.dark) nav .text-blue-400,
html:not(.dark) nav .text-blue-300,
html:not(.dark) nav .text-purple-400,
html:not(.dark) nav .text-indigo-400,
html:not(.dark) nav .text-gray-400,
html:not(.dark) nav .text-gray-300,
html:not(.dark) nav .text-gray-200,
html:not(.dark) nav .text-slate-400,
html:not(.dark) nav .text-white {
  color: #E2E8F0 !important; /* keep nav text light on dark nav */
}

/* AI lightning bolt icon in nav — ensure visibility */
html:not(.dark) nav [class*="text-yellow"],
html:not(.dark) nav [class*="text-amber"] {
  color: #FCD34D !important; /* amber-300 — visible on dark nav */
}

/* ============================================================
   DAY MODE: Section icon containers
   bg-gray-800 / bg-gray-900 used as icon badge squares look
   jarring (dark square) on white card backgrounds in light mode.
   Convert to soft tinted light backgrounds.
   ============================================================ */
html:not(.dark) .bg-gray-800,
html:not(.dark) .bg-gray-900 {
  background-color: #F1F5F9 !important; /* slate-100 — soft light bg */
  border: 1px solid #E2E8F0;
}

/* Icon SVGs inside those containers: switch from light gray to dark */
html:not(.dark) .bg-gray-800 svg,
html:not(.dark) .bg-gray-900 svg {
  color: #475569 !important; /* slate-600 */
}

/* text-gray-500 icons inside gray-800 containers */
html:not(.dark) .bg-gray-800 .text-gray-500,
html:not(.dark) .bg-gray-900 .text-gray-500 {
  color: #64748B !important; /* slate-500 */
}

/* Green-tinted icon containers (enabled AI / MFA) — light mode */
html:not(.dark) .bg-green-900\/30,
html:not(.dark) [class*="bg-green-900"] {
  background-color: #DCFCE7 !important; /* green-100 */
  border: 1px solid #BBF7D0;
}

html:not(.dark) .bg-green-900\/30 svg,
html:not(.dark) [class*="bg-green-900"] svg {
  color: #16A34A !important; /* green-600 */
}

/* ============================================================
   DAY MODE: Card / section backgrounds
   bg-navy-light and bg-gray-800/50 sections should be white
   ============================================================ */
html:not(.dark) .bg-navy-light,
html:not(.dark) [class*="bg-navy"] {
  background-color: #FFFFFF !important;
  border-color: #E5E7EB !important;
}

/* text-white headings inside content cards — make dark in light mode */
html:not(.dark) :not(nav):not(header) > * .text-white,
html:not(.dark) main .text-white,
html:not(.dark) [role="main"] .text-white,
html:not(.dark) .rounded-xl .text-white,
html:not(.dark) .rounded-2xl .text-white,
html:not(.dark) .rounded-lg .text-white {
  color: #111827 !important; /* gray-900 — near black */
}

/* border-white/10 card borders — make visible in light mode */
html:not(.dark) .border-white\/10 {
  border-color: #E5E7EB !important; /* gray-200 */
}

html:not(.dark) .border-white\/5 {
  border-color: #F3F4F6 !important; /* gray-100 */
}

/* ============================================================
   DAY MODE: Dark-themed buttons (bg-gray-700, bg-gray-600)
   Export CSV / Export JSON and similar utility buttons
   ============================================================ */
html:not(.dark) .bg-gray-700:not(nav *),
html:not(.dark) .bg-gray-600:not(nav *) {
  background-color: #374151 !important; /* gray-700 stays — high contrast on white */
  color: #FFFFFF !important;
}

html:not(.dark) .bg-gray-700:not(nav *):hover,
html:not(.dark) .bg-gray-600:not(nav *):hover {
  background-color: #1F2937 !important;
}

/* ============================================================
   DAY MODE: "Always Active" + status badges
   bg-gray-500/20 badge backgrounds — improve contrast
   ============================================================ */
html:not(.dark) .bg-gray-500\/20 {
  background-color: #E5E7EB !important;
  color: #374151 !important;
}

html:not(.dark) [class*="bg-gray-500/20"],
html:not(.dark) [class*="bg-gray-700/50"],
html:not(.dark) [class*="bg-gray-800/50"] {
  background-color: #F3F4F6 !important;
  color: #374151 !important;
}

/* ============================================================
   DAY MODE: AI / feature toggle items
   ============================================================ */
/* Feature enabled "Enabled" green badges */
html:not(.dark) .bg-green-900\/20,
html:not(.dark) [class*="bg-green-900/20"] {
  background-color: #DCFCE7 !important;
  color: #15803D !important;
}

/* Feature disabled "Disabled" badges */
html:not(.dark) .bg-gray-500\/20 .text-gray-400,
html:not(.dark) [class*="bg-gray-500/20"] .text-gray-400 {
  color: #6B7280 !important;
}

/* ============================================================
   DAY MODE: Consent section "Always Active" badge
   ============================================================ */
html:not(.dark) [class*="always"] .text-gray-300,
html:not(.dark) [class*="always"] {
  color: #374151 !important;
}

/* Inline code in light mode (inside light cards) */
html:not(.dark) .bg-navy code,
html:not(.dark) [class*="bg-navy"] code {
  background-color: #F3F4F6 !important;
  color: #111827 !important;
}

/* ============================================================
   DAY MODE: Divider lines — border-white/10 etc
   ============================================================ */
html:not(.dark) hr,
html:not(.dark) [class*="divide-white"] > * + * {
  border-color: #E5E7EB !important;
}

/* ============================================================
   DAY MODE: Toggle switch tracks (bg-gray-700 for off-state)
   ============================================================ */
html:not(.dark) button[role="switch"][aria-checked="false"] {
  background-color: #D1D5DB !important; /* gray-300 — visible off state */
}

/* ============================================================
   DAY MODE: Admin Access Panel badge colors
   text-red-300 / text-violet-300 / text-indigo-300 are too pale
   on white card backgrounds — darken to readable equivalents.
   ============================================================ */
html:not(.dark) .text-red-300 {
  color: #B91C1C !important; /* red-700 */
}
html:not(.dark) .text-violet-300 {
  color: #6D28D9 !important; /* violet-700 */
}
html:not(.dark) .text-indigo-300 {
  color: #3730A3 !important; /* indigo-800 */
}
html:not(.dark) .text-indigo-400 {
  color: #4338CA !important; /* indigo-700 */
}
html:not(.dark) .text-purple-400 {
  color: #7C3AED !important; /* purple-700 */
}

/* Admin badge backgrounds — low-opacity on white looks washed out */
html:not(.dark) .bg-red-500\/10 {
  background-color: #FEE2E2 !important; /* red-100 */
  border-color: #FECACA !important;     /* red-200 */
}
html:not(.dark) .bg-violet-500\/10 {
  background-color: #EDE9FE !important; /* violet-100 */
  border-color: #DDD6FE !important;     /* violet-200 */
}
html:not(.dark) .bg-indigo-500\/10 {
  background-color: #E0E7FF !important; /* indigo-100 */
  border-color: #C7D2FE !important;     /* indigo-200 */
}

/* ============================================================
   DAY MODE: Flash / alert messages
   Success = green banner, Error = red banner — ensure readable
   on light backgrounds.
   ============================================================ */
html:not(.dark) [class*="flash"],
html:not(.dark) [role="alert"],
html:not(.dark) .alert-success,
html:not(.dark) .alert-error,
html:not(.dark) .alert-warning,
html:not(.dark) .alert-info {
  color: #111827 !important;
}

/* Green success flash — bg-green-900/30 is invisible on white */
html:not(.dark) .bg-green-900\/30,
html:not(.dark) [class*="bg-green-900/30"] {
  background-color: #DCFCE7 !important; /* green-100 */
  border-color: #86EFAC !important;
  color: #166534 !important; /* green-800 */
}
html:not(.dark) .bg-green-900\/30 *,
html:not(.dark) [class*="bg-green-900/30"] * {
  color: #166534 !important;
}

/* Red error flash */
html:not(.dark) .bg-red-900\/30,
html:not(.dark) [class*="bg-red-900/30"] {
  background-color: #FEE2E2 !important; /* red-100 */
  border-color: #FCA5A5 !important;
  color: #991B1B !important; /* red-800 */
}

/* Yellow warning flash */
html:not(.dark) .bg-yellow-900\/10,
html:not(.dark) [class*="bg-yellow-900/10"] {
  background-color: #FEF9C3 !important; /* yellow-100 */
  border-color: #FDE68A !important;
  color: #92400E !important; /* yellow-900 */
}
html:not(.dark) .bg-yellow-900\/10 *,
html:not(.dark) [class*="bg-yellow-900/10"] * {
  color: #92400E !important;
}

/* ============================================================
   DAY MODE: Page / section headers outside nav
   h1.text-white on dashboard, settings, etc.
   Ensure these are always dark in light mode regardless of parent.
   ============================================================ */
html:not(.dark) h1.text-white,
html:not(.dark) h2.text-white,
html:not(.dark) h3.text-white {
  color: #111827 !important;
}

html:not(.dark) p.text-gray-400,
html:not(.dark) span.text-gray-400 {
  color: #4B5563 !important;
}

/* Subtitle lines directly under page headings */
html:not(.dark) .mb-8 > p.text-gray-400,
html:not(.dark) .mb-6 > p.text-gray-400 {
  color: #6B7280 !important;
}

/* ============================================================
   DAY MODE: Consent section grant/withdraw buttons
   ============================================================ */
html:not(.dark) .bg-purple-700 {
  background-color: #7C3AED !important; /* purple-700 stays, already good */
  color: #FFFFFF !important;
}
html:not(.dark) .bg-purple-700:hover {
  background-color: #6D28D9 !important;
}

/* ============================================================
   v19.37 FIX: Mobile / Desktop menu — correct open behaviour
   Root causes fixed:
   (a) Desktop: FUSE-locked CSS has display:none on #mobile-menu
       at lg+ breakpoints. Clearing inline display (display='')
       falls back to CSS display:none — menu stays invisible.
       Fix: explicit display:block in JS open handler (done above
       in app.py). CSS here provides a belt-and-suspenders guard.
   (b) Mobile: nav links inside the panel are invisible because
       they may carry Tailwind 'hidden' class or inherit a text
       color that matches the panel background.
   ============================================================ */

/* Solid dark background — prevents transparent panel on desktop */
#mobile-menu {
  background-color: #0F172A !important; /* slate-900 = same as nav */
}

/* When menu is open (data-open="1" set by our JS patch):
   CSS-level guarantee that the panel and ALL its content is visible.
   This catches any Tailwind utility that CSS-specificity might win. */
#mobile-menu[data-open="1"] {
  display: block !important;
  visibility: visible !important;
  opacity: 1 !important;
  transform: translateX(0) !important;
  -webkit-transform: translateX(0) !important;
}

#mobile-menu[data-open="1"] > * {
  visibility: visible !important;
  opacity: 1 !important;
}

/* Every anchor and button inside the open menu — white text, visible */
#mobile-menu[data-open="1"] a,
#mobile-menu[data-open="1"] nav a,
#mobile-menu[data-open="1"] .space-y-1 a,
#mobile-menu[data-open="1"] .space-y-2 a {
  display: flex !important;
  color: #FFFFFF !important;
  opacity: 1 !important;
  visibility: visible !important;
}

#mobile-menu[data-open="1"] nav button,
#mobile-menu[data-open="1"] .space-y-1 button,
#mobile-menu[data-open="1"] .space-y-2 button {
  display: flex !important;
  opacity: 1 !important;
  visibility: visible !important;
}

#mobile-menu[data-open="1"] nav {
  display: flex !important;
  flex-direction: column !important;
  opacity: 1 !important;
  visibility: visible !important;
}

/* ============================================================
   v19.37 FIX: Idea page — grid layout gap (mobile + desktop)
   Root causes:
   (a) CSS Grid default align-items:stretch makes the shorter
       column expand to fill the taller column's height, creating
       a large blank area in the shorter column as you scroll.
       On desktop: right sidebar usually shorter → blank right.
       On mobile: stacked columns each stretch unnecessarily.
       Fix: align-items:start so each column is only as tall as
       its own content.
   (b) Mobile: gap-6 (1.5rem) between stacked grid rows looks
       proportionally larger on a narrow viewport. Reduce to 1rem.
   (c) Mobile: max-w-5xl container + outer base-template padding
       stack, making content narrower than needed on iPhone.
       Fix: reduce inner container padding on small screens.
   ============================================================ */

/* Prevent column height stretching — fixes blank gap in shorter column */
.grid.grid-cols-1.lg\:grid-cols-3 {
  align-items: start !important;
}

/* Mobile (<1024px): tighten vertical gap between stacked grid items */
@media (max-width: 1023px) {
  .grid.grid-cols-1.lg\:grid-cols-3.gap-6 {
    gap: 1rem !important;
  }

  /* Ensure both columns go full-width with no accidental left offset */
  .grid.grid-cols-1.lg\:grid-cols-3 > div {
    width: 100% !important;
    box-sizing: border-box !important;
    margin-left: 0 !important;
    padding-left: 0 !important;
  }
}

/* iPhone: reduce idea page container padding so content isn't squeezed */
@media (max-width: 640px) {
  .max-w-5xl.mx-auto {
    padding-left: 0.5rem !important;
    padding-right: 0.5rem !important;
    max-width: 100% !important;
  }

  /* Evolution chain cards: reduce inner padding on very narrow screens */
  .max-w-5xl .rounded-xl.p-4,
  .max-w-5xl .rounded-xl.p-5 {
    padding: 0.75rem !important;
  }
}

/* Withdraw button bg-gray-700 in consent — already handled above,
   but ensure the hover red variant is readable */
html:not(.dark) .hover\:bg-red-800:hover {
  background-color: #991B1B !important;
  color: #FFFFFF !important;
}

/* ============================================================
   DAY MODE: Breadcrumb contrast
   ============================================================ */
html:not(.dark) .breadcrumbs a,
html:not(.dark) nav[aria-label="Breadcrumb"] a {
  color: #374151 !important;
}
html:not(.dark) .breadcrumbs .current,
html:not(.dark) nav[aria-label="Breadcrumb"] .current {
  color: #111827 !important;
}
html:not(.dark) .breadcrumbs .sep {
  color: #9CA3AF !important;
}

/* ============================================================
   DAY MODE: text-gray-300 in content areas
   NDA banner text, notification cards, stat card hover labels —
   #D1D5DB on white = contrast ratio ~1.5:1, practically invisible.
   ============================================================ */
html:not(.dark) :not(nav):not(header) .text-gray-300,
html:not(.dark) main .text-gray-300,
html:not(.dark) .rounded-xl .text-gray-300,
html:not(.dark) .rounded-2xl .text-gray-300,
html:not(.dark) .rounded-lg .text-gray-300 {
  color: #374151 !important; /* gray-700 */
}

/* ============================================================
   DAY MODE: group-hover:text-white in content areas
   Stat card labels turn white on hover over white card = invisible.
   Override to near-black hover state.
   ============================================================ */
html:not(.dark) :not(nav) .group:hover .group-hover\:text-white {
  color: #111827 !important;
}
html:not(.dark) :not(nav) .group:hover .group-hover\:text-gray-300 {
  color: #374151 !important;
}

/* ============================================================
   DAY MODE: text-amber-300 / text-amber-400 — NDA banners
   Amber-300 (#FCD34D) on white = ratio ~1.1:1, near invisible.
   Darken to amber-700/900 for adequate contrast.
   ============================================================ */
html:not(.dark) :not(nav) .text-amber-300 {
  color: #92400E !important; /* amber-900 */
}
html:not(.dark) :not(nav) .text-amber-400 {
  color: #B45309 !important; /* amber-700 */
}

/* ============================================================
   DAY MODE: text-teal-400 / text-blue-400 — stat card numbers
   Teal-400 and blue-400 wash out on white backgrounds.
   ============================================================ */
html:not(.dark) :not(nav) .text-teal-400 {
  color: #0F766E !important; /* teal-700 */
}
html:not(.dark) :not(nav) .text-blue-400 {
  color: #1D4ED8 !important; /* blue-700 */
}

/* ============================================================
   DAY MODE: text-purple-300 / text-cyan-300 — collab / NDA badges
   ============================================================ */
html:not(.dark) :not(nav) .text-purple-300 {
  color: #6D28D9 !important; /* purple-700 */
}
html:not(.dark) :not(nav) .text-cyan-300 {
  color: #0E7490 !important; /* cyan-700 */
}
html:not(.dark) :not(nav) .text-teal-300 {
  color: #0F766E !important; /* teal-700 */
}

/* ============================================================
   DAY MODE: Low-opacity colored badge backgrounds
   bg-amber-500/20, bg-purple-500/20, bg-cyan-500/20 etc.
   Nearly invisible on white — convert to solid light tints.
   ============================================================ */
html:not(.dark) :not(nav) [class*="bg-amber-500\/20"],
html:not(.dark) :not(nav) [class*="bg-amber-500/20"] {
  background-color: #FEF3C7 !important; /* amber-100 */
}
html:not(.dark) :not(nav) [class*="bg-amber-500\/30"],
html:not(.dark) :not(nav) [class*="bg-amber-500/30"] {
  background-color: #FDE68A !important; /* amber-200 */
}
html:not(.dark) :not(nav) [class*="bg-purple-500\/20"],
html:not(.dark) :not(nav) [class*="bg-purple-500/20"] {
  background-color: #EDE9FE !important; /* violet-100 */
}
html:not(.dark) :not(nav) [class*="bg-cyan-500\/20"],
html:not(.dark) :not(nav) [class*="bg-cyan-500/20"] {
  background-color: #CFFAFE !important; /* cyan-100 */
}
html:not(.dark) :not(nav) [class*="bg-teal-500\/20"],
html:not(.dark) :not(nav) [class*="bg-teal-500/20"] {
  background-color: #CCFBF1 !important; /* teal-100 */
}

/* ============================================================
   DAY MODE: Notification banner borders — amber/purple
   Low-opacity borders on white become invisible.
   ============================================================ */
html:not(.dark) [class*="border-amber-500\/20"],
html:not(.dark) [class*="border-amber-500/20"] {
  border-color: #FCD34D !important; /* amber-300 */
}
html:not(.dark) [class*="border-amber-500\/30"],
html:not(.dark) [class*="border-amber-500/30"] {
  border-color: #FCD34D !important;
}
html:not(.dark) [class*="border-amber-500\/50"],
html:not(.dark) [class*="border-amber-500/50"] {
  border-color: #F59E0B !important; /* amber-500 */
}
html:not(.dark) [class*="border-purple-500\/30"],
html:not(.dark) [class*="border-purple-500/30"] {
  border-color: #C4B5FD !important; /* violet-300 */
}
html:not(.dark) [class*="border-cyan-500\/20"],
html:not(.dark) [class*="border-cyan-500/20"] {
  border-color: #A5F3FC !important; /* cyan-200 */
}
html:not(.dark) [class*="border-indigo-500\/20"],
html:not(.dark) [class*="border-indigo-500/20"] {
  border-color: #C7D2FE !important; /* indigo-200 */
}

/* ============================================================
   DAY MODE: Nav dropdown panels
   The dropdown menus (Tools, Workspace) are absolutely-positioned
   divs inside <nav> with classes: absolute top-full z-50.
   In light mode they must be white with dark text — not dark navy.
   These rules must come AFTER the base nav rules to win on !important.
   ============================================================ */

/* Dropdown panel background — white card with subtle border/shadow */
html:not(.dark) nav .absolute.top-full {
  background-color: #FFFFFF !important;
  border-color: #E2E8F0 !important;       /* slate-200 */
  box-shadow: 0 10px 15px -3px rgba(0,0,0,0.12), 0 4px 6px -2px rgba(0,0,0,0.07) !important;
}

/* Dropdown links + buttons — dark text on white panel */
html:not(.dark) nav .absolute.top-full a,
html:not(.dark) nav .absolute.top-full button {
  color: #111827 !important;              /* gray-900 */
}

/* Dropdown hover state — subtle gray highlight */
html:not(.dark) nav .absolute.top-full a:hover,
html:not(.dark) nav .absolute.top-full button:hover {
  background-color: #F1F5F9 !important;  /* slate-100 */
  color: #111827 !important;
}

/* Dropdown secondary / subtitle text (e.g. "Browse & discover ideas") */
html:not(.dark) nav .absolute.top-full .text-gray-400,
html:not(.dark) nav .absolute.top-full .text-gray-300,
html:not(.dark) nav .absolute.top-full .text-gray-500,
html:not(.dark) nav .absolute.top-full .text-slate-400,
html:not(.dark) nav .absolute.top-full [class*="text-gray"] {
  color: #6B7280 !important;             /* gray-500 — readable subtitle */
}

/* Dropdown SVG icons */
html:not(.dark) nav .absolute.top-full svg {
  color: #374151 !important;             /* gray-700 */
}

/* Dropdown separator lines */
html:not(.dark) nav .absolute.top-full hr,
html:not(.dark) nav .absolute.top-full [class*="border-white"] {
  border-color: #E5E7EB !important;
}

/* ============================================================
   DAY MODE: Nav bar link / icon contrast boost
   Some nav items use text-gray-500 / text-slate-300 etc. which
   our existing rule misses — ensure ALL text inside the nav bar
   itself (NOT dropdowns) is visible on the dark navy background.
   ============================================================ */
html:not(.dark) nav .text-gray-500,
html:not(.dark) nav .text-gray-600,
html:not(.dark) nav .text-slate-300,
html:not(.dark) nav .text-slate-200 {
  color: #CBD5E1 !important;             /* slate-300 — visible on #1E293B */
}

/* Logout / AI text links that might use text-gray-200 or similar */
html:not(.dark) nav .text-gray-200 {
  color: #E2E8F0 !important;
}

/* Gear and moon icons — ensure full brightness on dark nav */
html:not(.dark) nav svg {
  opacity: 1 !important;
}

/* Keyboard shortcut badge (⌘K) */
html:not(.dark) nav kbd,
html:not(.dark) nav [class*="kbd"],
html:not(.dark) nav .rounded.border {
  background-color: rgba(255,255,255,0.12) !important;
  border-color: rgba(255,255,255,0.25) !important;
  color: #CBD5E1 !important;
}

/* ============================================================
   STICKY NAV: keep the nav bar and mobile hamburger visible
   as the user scrolls down on any screen size.
   ============================================================ */
nav {
  position: sticky !important;
  top: 0 !important;
  z-index: 100 !important;
}

/* ============================================================
   IDEA PAGE — PILL TABS: light mode visibility fix.
   The three pill-tab <a> buttons use text-gray-400 which is
   nearly invisible on a white background (~2.5:1 contrast).
   Force them to a legible slate tone in day mode.
   ============================================================ */
html:not(.dark) a.text-gray-400 {
  color: #475569 !important;   /* slate-600 — 7:1 on white */
}
html:not(.dark) a.text-gray-400:hover {
  color: #1E293B !important;   /* slate-900 */
}

/* ============================================================
   v19.31 FIX: TTO pages — comprehensive iPhone/mobile layout
   fixes for tables, cards, status badges, buttons, and spacing.
   All TTO pages: /tto/dashboard, /tto/disclosures, /tto/grants,
   /challenges. JS handles table wrapping; CSS catches the rest.
   ============================================================ */

/* ── Global table safety net (belt + braces with JS wrapper) ── */
/* Force all th/td text horizontal — catches any CSS vertical-text bug */
th, td {
  writing-mode: horizontal-tb !important;
  text-orientation: mixed !important;
  vertical-align: middle !important;
}

/* Tables that haven't been JS-wrapped yet — still try to scroll */
table {
  border-collapse: collapse;
}

/* JS wraps tables in [data-tto-wrap] divs — style the wrapper */
[data-tto-wrap] {
  overflow-x: auto !important;
  -webkit-overflow-scrolling: touch !important;
  max-width: 100% !important;
  border-radius: 8px;
  scrollbar-width: thin;
  scrollbar-color: rgba(249,115,22,0.4) transparent;
}
[data-tto-wrap]::-webkit-scrollbar {
  height: 4px;
}
[data-tto-wrap]::-webkit-scrollbar-thumb {
  background: rgba(249,115,22,0.4);
  border-radius: 4px;
}

/* ── Mobile-specific TTO layout ── */
@media (max-width: 768px) {
  /* Page-level padding tighten on iPhone */
  .tto-page,
  body > main > div,
  .container.mx-auto {
    padding-left: 12px !important;
    padding-right: 12px !important;
  }

  /* TTO stat/metric cards — stack to single column */
  .grid.grid-cols-2.gap-4,
  .grid.grid-cols-3.gap-4,
  .grid.grid-cols-4.gap-4,
  .grid.grid-cols-2.gap-6,
  .grid.grid-cols-3.gap-6 {
    grid-template-columns: 1fr 1fr !important;
    gap: 8px !important;
  }

  /* Stat card text sizing */
  .rounded-xl.p-6 .text-3xl,
  .rounded-xl.p-4 .text-3xl,
  [class*="stat"] .text-3xl,
  [class*="metric"] .text-3xl {
    font-size: 1.5rem !important;
  }

  /* Table header cells — min width + no wrap */
  th {
    min-width: 90px !important;
    padding: 8px 10px !important;
    font-size: 11px !important;
    white-space: nowrap !important;
  }

  /* Table data cells */
  td {
    padding: 8px 10px !important;
    font-size: 12px !important;
    white-space: nowrap !important;
  }

  /* Long text cells (title/description) — allow wrap */
  td:first-child,
  td[class*="title"],
  td[class*="name"],
  td[class*="desc"] {
    min-width: 160px !important;
    max-width: 200px !important;
    white-space: normal !important;
    word-break: break-word !important;
  }

  /* Status/type pill badges in tables */
  td span,
  td .rounded-full,
  td [class*="badge"],
  td [class*="status"],
  td [class*="pill"] {
    display: inline-flex !important;
    align-items: center !important;
    white-space: nowrap !important;
    font-size: 10px !important;
    padding: 2px 8px !important;
  }

  /* Action buttons in table rows */
  td a,
  td button {
    display: inline-flex !important;
    align-items: center !important;
    white-space: nowrap !important;
    font-size: 11px !important;
    padding: 4px 10px !important;
    min-height: 32px !important;
  }

  /* Page title + action button row — stack on mobile */
  .flex.items-center.justify-between,
  .flex.justify-between.items-center {
    flex-wrap: wrap !important;
    gap: 10px !important;
  }

  /* Filter/search row — stack inputs */
  .flex.gap-4 > input,
  .flex.gap-4 > select,
  .flex.space-x-4 > input,
  .flex.space-x-4 > select {
    width: 100% !important;
    min-width: 0 !important;
  }

  /* Section headings — prevent overflow */
  h1, h2, h3 {
    word-break: break-word !important;
    overflow-wrap: break-word !important;
  }

  /* Disclosure/grant card detail rows */
  dl.grid,
  .grid.grid-cols-2 dt,
  .grid.grid-cols-2 dd {
    font-size: 12px !important;
  }

  /* Empty state messages — centre properly */
  [class*="empty"],
  .text-center.py-12,
  .text-center.py-16 {
    padding: 40px 16px !important;
  }

  /* ── Filter/status tab buttons (e.g. All / Active / Pending / Suspended) ──
     Root cause: flex container with gap but no min-width on buttons causes
     them to shrink below text width → word breaks mid-word.
     Fix: nowrap + flex-shrink:0 so buttons keep their natural text width.  */
  [role="tablist"] button,
  [role="tablist"] a,
  .flex.gap-2 > button,
  .flex.gap-1 > button,
  .flex.gap-3 > button,
  .flex.space-x-1 > button,
  .flex.space-x-2 > button,
  .flex.space-x-3 > button,
  button[class*="rounded-lg"],
  button[class*="rounded-md"],
  button[class*="rounded-xl"] {
    white-space: nowrap !important;
    word-break: keep-all !important;
    flex-shrink: 0 !important;
  }

  /* ── Grant / Disclosure list-cards (e.g. Grant Workspace card) ──
     Root cause: the card uses a multi-column flex row with no min-width
     so narrow columns cause "A R C" and "Ryan Living ston" to stack.
     Fix: allow flex wrap + give each column a comfortable min-width.    */
  .rounded-xl .flex:not([class*="justify-between"]):not([class*="items-center"]),
  .rounded-lg .flex:not([class*="justify-between"]):not([class*="items-center"]) {
    flex-wrap: wrap !important;
    gap: 6px !important;
  }

  /* Individual info columns inside grant/disclosure cards */
  .rounded-xl .flex > div,
  .rounded-xl .flex > span,
  .rounded-xl .flex > p,
  .rounded-lg .flex > div,
  .rounded-lg .flex > span {
    min-width: 60px !important;
    flex-shrink: 1 !important;
    word-break: break-word !important;
    white-space: normal !important;
  }

  /* Abbreviation/agency columns (very short text like "ARC") — don't collapse */
  .rounded-xl .flex > div:not(:first-child):not(:last-child),
  .rounded-lg .flex > div:not(:first-child):not(:last-child) {
    min-width: 40px !important;
  }

  /* Grant card metadata row (sections, date, progress) */
  .rounded-xl .flex.items-center,
  .rounded-lg .flex.items-center {
    flex-wrap: wrap !important;
    row-gap: 4px !important;
  }
}

/* ── Extra-small screens (iPhone SE, 375px) ── */
@media (max-width: 390px) {
  th { min-width: 80px !important; font-size: 10px !important; }
  td { font-size: 11px !important; }

  /* Single-column stat cards on very small screens */
  .grid.grid-cols-2.gap-4,
  .grid.grid-cols-2.gap-6 {
    grid-template-columns: 1fr !important;
  }
}

/* ============================================================
   v19.31 FIX: Footer badge labels — prevent mid-word breaks.
   "Immuta ble", "Audita ble", "Tamper-Proof" seen breaking
   on iPhone. Root cause: footer flex shrinks below text width.
   ============================================================ */
footer,
footer .flex,
[class*="footer"] {
  flex-wrap: wrap !important;
}

footer span,
footer li,
footer a,
footer [class*="text"],
[class*="footer"] span,
[class*="footer"] li {
  white-space: nowrap !important;
  word-break: keep-all !important;
  flex-shrink: 0 !important;
}

/* Footer icon + label pairs — keep together */
footer .flex.items-center,
[class*="footer"] .flex.items-center {
  flex-wrap: nowrap !important;
  white-space: nowrap !important;
}

@media (max-width: 640px) {
  /* Footer — stack badge row into 2 columns */
  footer .flex.gap-4,
  footer .flex.gap-6,
  footer .flex.space-x-4,
  footer .flex.space-x-6,
  [class*="footer"] .flex {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: 8px !important;
    align-items: start !important;
  }
}

/* ============================================================
   v19.31 FIX: Mobile nav — prevent horizontal overflow that
   pushes the hamburger button off-screen.
   Root cause: deep flex rows with long text can exceed 100vw
   causing the page to scroll right and the hamburger to be
   unreachable without zoom / scroll-right.
   ============================================================ */
html, body {
  max-width: 100vw;
  overflow-x: hidden;
}
nav,
nav > div,
nav .container,
nav [class*="max-w-"] {
  max-width: 100vw;
  overflow-x: hidden;
}

/* Hamburger button — never shrink or clip */
#hamburger-btn {
  flex-shrink: 0 !important;
  min-width: 44px !important;
  min-height: 44px !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
}

/* Desktop nav links — allow text to shrink on narrow viewports */
@media (max-width: 1024px) {
  nav a, nav span {
    white-space: nowrap;
  }
}

/* ============================================================
   v19.31 FIX: Achievements badges — fix vertical text overflow.
   Root cause: badge grid cols too narrow on mobile, forcing text
   into a near-zero-width column which renders character-by-character.
   Fix: force horizontal writing mode + reduce to 2-col grid on xs.
   ============================================================ */
@media (max-width: 640px) {
  /* Cap badges at 2 columns on small screens */
  .grid.grid-cols-3,
  .grid.grid-cols-4,
  [class*="grid-cols-3"],
  [class*="grid-cols-4"] {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  }

  /* Force horizontal text direction on all badge text */
  .badge-card p,
  .badge-card span,
  .badge-card h3,
  [class*="badge"] p,
  [class*="badge"] span,
  [class*="badge"] h3 {
    writing-mode: horizontal-tb !important;
    text-orientation: mixed !important;
    font-size: 10px !important;
    line-height: 1.3 !important;
    text-align: center !important;
    white-space: normal !important;
    word-break: break-word !important;
    overflow-wrap: break-word !important;
    hyphens: auto !important;
    max-width: 100% !important;
    display: block !important;
  }

  /* Constrain badge icon size */
  .badge-card img,
  [class*="badge"] img,
  img[alt*="badge"],
  img[alt*="Badge"] {
    width: 40px !important;
    height: 40px !important;
    object-fit: contain !important;
  }

  /* Badge card padding — tighten on mobile */
  .badge-card,
  [class*="badge-card"] {
    padding: 8px 4px !important;
  }
}

/* Catch any writing-mode:vertical accidentally applied anywhere */
[class*="badge"] * {
  writing-mode: horizontal-tb !important;
}

/* ============================================================
   v19.31 FIX: Settings page — AI Base URL code block black box.
   Root cause: <code> element inside the Deployment Recommendations
   card gets a dark/black background from browser defaults or
   Tailwind's prose/code styling, creating a pasted black rectangle
   over the already-dark card background.
   Fix: transparent background on code/pre/kbd in card contexts.
   ============================================================ */
code, kbd, samp, pre {
  background-color: transparent !important;
  background: transparent !important;
  box-shadow: none !important;
  border: none !important;
  padding: 0 !important;
}

/* But keep distinct styling for actual code blocks in idea descriptions */
pre code,
.prose code,
[class*="code-block"] code,
[class*="syntax"] code {
  background-color: rgba(255,255,255,0.06) !important;
  border-radius: 4px !important;
  padding: 2px 6px !important;
}

/* ============================================================
   v19.31 FIX: Mobile menu scroll lock — CSS companion.
   The JS sets position:fixed + overflow:hidden on body when menu
   is open. These rules ensure the menu panel itself is scrollable
   and scroll doesn't bleed through to the locked body.
   ============================================================ */
#mobile-menu {
  overflow-y: auto !important;
  -webkit-overflow-scrolling: touch !important;
  overscroll-behavior: contain !important;
}

/* When body is locked by menu, ensure nav stays on screen */
body[style*="position: fixed"] nav,
body[style*="position:fixed"] nav {
  position: sticky !important;
  top: 0 !important;
}

/* ============================================================
   MOBILE AUDIT — BATCH 2 (April 2026)
   New issues found across dashboard, idea, settings, badges,
   challenges, NDA, search, capture pages.
   ============================================================ */

/* ── ISSUE M1 (HIGH): dashboard Innovation Pipeline — grid-cols-6
   on mobile collapses each cell to ~55px, number + label illegible.
   Root: grid-cols-2 override already handles 3/4 cols but not 6.
   Fix: force 3-col on mobile, 6-col only from md up.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 767px) {
  .grid.grid-cols-2.md\:grid-cols-6 {
    grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
    gap: 6px !important;
  }
  .grid.grid-cols-2.md\:grid-cols-6 .text-2xl {
    font-size: 1.2rem !important;
  }
  .grid.grid-cols-2.md\:grid-cols-6 .text-xs {
    font-size: 9px !important;
    line-height: 1.2 !important;
  }
}

/* ── ISSUE M2 (HIGH): dashboard NDA notification card — action button
   "Review & Sign" is right-side flex-shrink-0 in a flex items-start
   gap-4 row. On 375px the button is pushed fully off-screen or clips.
   Fix: wrap the row and ensure button goes below content on xs.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  /* NDA + Collab notification cards — stack icon+text / button */
  .bg-navy-light.rounded-xl.border.border-amber-500\/30 .flex.items-start.gap-4,
  .bg-navy-light.rounded-xl.border.border-purple-500\/30 .flex.items-start.gap-4 {
    flex-wrap: wrap !important;
  }
  /* The action button (Review & Sign / Review) — full width when wrapped */
  .bg-navy-light.rounded-xl.border.border-amber-500\/30 .flex.items-start.gap-4 > a[href*="nda"],
  .bg-navy-light.rounded-xl.border.border-purple-500\/30 .flex.items-start.gap-4 > a[href*="collab"] {
    width: 100% !important;
    justify-content: center !important;
    margin-top: 4px !important;
  }
  /* Generic: any notification card's action link that is flex-shrink-0 */
  .space-y-3 .flex.items-start.gap-4 > a.flex-shrink-0,
  .space-y-3 .flex.items-start.gap-4 > button.flex-shrink-0 {
    flex-shrink: 1 !important;
    min-width: 0 !important;
    width: 100% !important;
    justify-content: center !important;
    margin-top: 6px !important;
  }
}

/* ── ISSUE M3 (HIGH): dashboard Discover tabs — "Institution" /
   "Public" pill buttons use space-x-2 inline, no flex-wrap.
   On 375px with a count badge they can overflow.
   Already partially handled by filter-button fix, but the Discover
   tabs use a specific pattern that needs explicit overflow scroll.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  .flex.items-center.space-x-2:has(#discover-tab-institution),
  div:has(> #discover-tab-institution) {
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch !important;
    flex-wrap: nowrap !important;
    scrollbar-width: none !important;
  }
}

/* ── ISSUE M4 (HIGH): idea.html — Action button bar (Evolution Tree /
   Audit Trail / Export JSON / TTO Disclosure / Draft Patent etc.)
   flex items-center flex-wrap gap-2 is fine, but "Draft Patent (.docx)▾"
   dropdown uses group-hover:block which is hover-only — unusable on touch.
   Additional: buttons overflow on 375px as they don't stack.
   Fix: ensure flex-wrap works + min touch targets.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  /* Idea action button bar — full width buttons on smallest screens */
  .max-w-5xl .flex.items-center.flex-wrap.gap-2 > a,
  .max-w-5xl .flex.items-center.flex-wrap.gap-2 > button,
  .max-w-5xl .flex.items-center.flex-wrap.gap-2 > form > button,
  .max-w-5xl .flex.items-center.flex-wrap.gap-2 > .relative {
    min-height: 40px !important;
    padding-top: 8px !important;
    padding-bottom: 8px !important;
  }

  /* Draft Patent dropdown — make it tap-accessible on mobile.
     Change from hover to focus/active trigger via CSS (JS fallback
     in base.html handles the rest; this ensures it's at least tappable). */
  .max-w-5xl .relative.group .hidden.group-hover\:block {
    /* On touch devices, show on focus instead */
    position: absolute !important;
    right: 0 !important;
    min-width: 200px !important;
    z-index: 60 !important;
  }
}

/* ── ISSUE M5 (HIGH): idea.html — Lock Info section uses
   grid grid-cols-1 md:grid-cols-3. On mobile the hash strings
   (break-all) are fine but the 3-col grid inside the quantum-resistant
   section uses md:grid-cols-2 — all OK. However the anchor_proofs
   section uses raw style="display:flex" with justify-content:space-between
   which wraps the Polygonscan link off-screen on 375px.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  /* Blockchain anchor proof rows — stack label and link */
  .mt-3.pt-3.border-t > div[style*="display: flex"][style*="justify-content: space-between"],
  .mt-3.pt-3.border-t > div[style*="display:flex"][style*="justify-content:space-between"] {
    flex-wrap: wrap !important;
    gap: 4px !important;
  }
  /* Polygonscan / Blockstream links — align left when wrapped */
  .mt-3.pt-3.border-t a[href*="polygonscan"],
  .mt-3.pt-3.border-t a[href*="blockstream"] {
    margin-top: 2px !important;
    display: block !important;
  }
}

/* ── ISSUE M6 (HIGH): idea.html — Research stage progress bar.
   Uses a flex row of 9 stages with whitespace-nowrap labels.
   Already has overflow-x-auto but the dots + connector lines
   render at ~360px total so it scrolls off. The [10px] font
   labels ("Lit Review", "Manuscript") stay nowrap — fine.
   Add explicit scroll snap so user can read stages.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  .flex.items-center.space-x-1.overflow-x-auto.py-1 {
    scroll-snap-type: x mandatory !important;
    padding-bottom: 8px !important;
    gap: 0 !important;
  }
  .flex.items-center.space-x-1.overflow-x-auto.py-1 > div {
    scroll-snap-align: start !important;
    flex-shrink: 0 !important;
  }
}

/* ── ISSUE M7 (HIGH): idea.html — sidebar is lg:col-span-1 inside
   grid grid-cols-1 lg:grid-cols-3. On mobile it flows below the
   main content (correct) but the "Maturity Stage Updater", "Patent
   Status", "Collaborators" cards have no side padding.
   The parent .max-w-5xl has proper padding but the sidebar divs
   use p-5 — fine. No issue here. Mark CLEAR.

   Real issue: idea.html — Comments row (line 1051):
   .flex.items-center.justify-between mt-2 wraps the "Post Comment"
   button off the bottom-right on 375px when the help text is long.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  /* Comment post bar — stack help text above button */
  form[action*="comment"] .flex.items-center.justify-between {
    flex-direction: column !important;
    align-items: flex-start !important;
    gap: 8px !important;
  }
  form[action*="comment"] .flex.items-center.justify-between button[type="submit"] {
    width: 100% !important;
    justify-content: center !important;
  }
}

/* ── ISSUE M8 (MEDIUM): idea.html — Tier Escalation inline-style
   form uses raw style="display:flex; gap:8px; flex-wrap:wrap"
   with a min-width:200px input. On 375px the input, select, and
   button don't stack correctly — the input enforces 200px even
   when total width < 375px minus padding.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  /* Tier escalation flex row — force full-width children */
  div[style*="display:flex"][style*="align-items:flex-end"] > div[style*="min-width:200px"],
  div[style*="display: flex"][style*="align-items: flex-end"] > div[style*="min-width: 200px"] {
    min-width: 0 !important;
    width: 100% !important;
    flex: 1 1 100% !important;
  }
  div[style*="display:flex"][style*="align-items:flex-end"] > div:first-child,
  div[style*="display: flex"][style*="align-items: flex-end"] > div:first-child {
    flex: 1 1 100% !important;
  }
  /* Escalate button — full width */
  div[style*="display:flex"][style*="align-items:flex-end"] > button[type="submit"],
  div[style*="display: flex"][style*="align-items: flex-end"] > button[type="submit"] {
    width: 100% !important;
    margin-top: 4px !important;
  }
}

/* ── ISSUE M9 (MEDIUM): settings.html — AI toggle row
   flex items-start justify-between with the toggle button right-side.
   On 375px with long status text the toggle button can be clipped.
   The form wraps: form.flex-shrink-0.ml-4. ml-4 eats ~16px.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  /* AI toggle row — allow the text area to shrink and toggle to stay right */
  .bg-navy-light .flex.items-start.justify-between {
    gap: 12px !important;
  }
  /* Ensure toggle button (w-14 = 56px) never clips */
  .bg-navy-light .flex.items-start.justify-between > form.flex-shrink-0 {
    flex-shrink: 0 !important;
    margin-left: 8px !important;
  }
}

/* ── ISSUE M10 (MEDIUM): settings.html — MFA disable form
   uses flex items-end space-x-3. On 375px the password input
   (flex-1) + "Disable MFA" button stack awkwardly.
   Fix: already handled by Issue #4 partial fix, but the MFA
   form specifically uses items-end which doesn't get caught.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  /* MFA disable form — stack input then button */
  form[action*="mfa_disable"] .flex.items-end.space-x-3,
  form[action*="mfa-disable"] .flex.items-end.space-x-3 {
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 10px !important;
  }
  form[action*="mfa_disable"] .flex.items-end.space-x-3 > *,
  form[action*="mfa-disable"] .flex.items-end.space-x-3 > * {
    width: 100% !important;
    margin-left: 0 !important;
  }
}

/* ── ISSUE M11 (MEDIUM): settings.html — Blockchain Anchor Stats
   grid grid-cols-3 gap-4 text-center inside a card.
   On 375px each cell is ~108px — the 2xl number + xs label just
   fits, but if anchor_stats.total is 4+ digits it will truncate.
   Force word-break on the numbers.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  .grid.grid-cols-3.gap-4.text-center .text-2xl {
    font-size: 1.25rem !important;
    word-break: break-all !important;
  }
}

/* ── ISSUE M12 (MEDIUM): settings.html — "Your Data Rights" flex-wrap
   gap-3 row with two button-like anchor links. On 375px the two
   long labels ("Download My Data", "Request Erasure") can cause
   the row to wrap into 2 lines which is fine, but the flex-wrap
   isn't explicitly set — it uses the global fix. Verify the consent
   toggle "Grant" / "Withdraw" button rows also stack properly.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 480px) {
  /* Consent toggle rows — ensure Grant/Withdraw buttons are tappable */
  .flex.items-start.justify-between.gap-4.py-2 {
    flex-wrap: wrap !important;
  }
  .flex.items-start.justify-between.gap-4.py-2 > .flex.gap-2.flex-shrink-0 {
    width: 100% !important;
    margin-top: 6px !important;
  }
  .flex.items-start.justify-between.gap-4.py-2 > .flex.gap-2.flex-shrink-0 form,
  .flex.items-start.justify-between.gap-4.py-2 > .flex.gap-2.flex-shrink-0 button {
    flex: 1 !important;
    text-align: center !important;
    justify-content: center !important;
  }
}

/* ── ISSUE M13 (MEDIUM): badges.html — Header row uses
   flex items-center justify-between with two stat counters.
   On 375px, "Achievements" h1 (text-3xl) + two counters
   (text-3xl each) overflow. The flex doesn't wrap.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 480px) {
  /* Badges header — stack title and counter row */
  .max-w-5xl > .flex.items-center.justify-between.mb-8 {
    flex-wrap: wrap !important;
    gap: 12px !important;
  }
  /* Badge counters row — keep together as a unit */
  .max-w-5xl > .flex.items-center.justify-between.mb-8 > .flex.items-center.gap-3 {
    gap: 20px !important;
  }
  /* Header h1 on badges page */
  .max-w-5xl > .flex.items-center.justify-between.mb-8 h1 {
    font-size: 1.5rem !important;
  }
}

/* ── ISSUE M14 (MEDIUM): badges.html — Badge grid is
   grid-cols-1 md:grid-cols-2 lg:grid-cols-3. On mobile it goes
   single column per JS render — GOOD. But the badge cards rendered
   by JS use a fixed flex layout with a large emoji + text.
   The category filter buttons (cat-btn) use flex gap-2 flex-wrap
   which is fine. No additional fix needed for grid.
   REAL ISSUE: Badge modal (#badge-modal) is fixed inset-0 flex
   items-center justify-center p-4. The inner card is max-w-md w-full p-6.
   On 375px p-6 = 24px each side, inner content fits but the share
   button row "Share on X" / "LinkedIn" / "Copy Link" uses flex gap-2
   justify-center — three buttons at ~110px each = 330px + 16px gaps
   = 346px. Just fits at 375-32px=343px. VERY tight, will clip on 360px.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  /* Badge modal inner card — reduce padding on small screens */
  #badge-modal > div {
    padding: 1.25rem !important;
    margin: 0.75rem !important;
  }
  /* Share button row — wrap to 2 buttons per row */
  #modal-share {
    flex-wrap: wrap !important;
    gap: 8px !important;
  }
  #modal-share button {
    flex: 1 1 calc(50% - 4px) !important;
    min-width: 0 !important;
    font-size: 12px !important;
    padding: 8px 10px !important;
    justify-content: center !important;
  }
  /* Modal icon — slightly smaller */
  #modal-icon {
    width: 60px !important;
    height: 60px !important;
    font-size: 2rem !important;
  }
}

/* ── ISSUE M15 (MEDIUM): badges.html — Toast notification
   uses fixed bottom-6 right-6 max-w-sm. On 375px, right-6 = 24px
   and max-w-sm = 384px, so toast is 375-24=351px wide — overflows
   left edge. Fix: use left+right anchoring on mobile.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 480px) {
  #badge-toast {
    left: 12px !important;
    right: 12px !important;
    bottom: 16px !important;
    max-width: none !important;
  }
}

/* ── ISSUE M16 (HIGH): challenges/detail.html — Sponsor Controls
   action button row: flex flex-wrap gap-3. The invite form inside
   has an email input w-56 (224px fixed) + button side by side.
   On 375px: 224px input + gap + ~60px button = 292px but the card
   has p-6 = 48px total padding leaving ~327px. Very tight with
   border. The input overflows on 360px phones.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  /* Challenge invite email form — stack input + button */
  form[action*="invite_researcher"] .flex.items-center.gap-2,
  form[action*="invite-researcher"] .flex.items-center.gap-2 {
    flex-direction: column !important;
    align-items: stretch !important;
  }
  form[action*="invite_researcher"] input[name="invite_email"],
  form[action*="invite-researcher"] input[name="invite_email"] {
    width: 100% !important;
  }
  form[action*="invite_researcher"] button[type="submit"],
  form[action*="invite-researcher"] button[type="submit"] {
    width: 100% !important;
  }
}

/* ── ISSUE M17 (MEDIUM): challenges/detail.html — Solution cards
   flex items-start justify-between gap-4. The right-side action
   column (Review / Shortlist / Award / Reject buttons as a flex-col)
   has flex-shrink-0 but the left content has no min-width:0, so on
   375px the action column can push the approach_summary text into a
   ~160px wide column.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  /* Solution card — stack content above action buttons */
  .space-y-4 .bg-navy-light .flex.items-start.justify-between.gap-4 {
    flex-direction: column !important;
  }
  .space-y-4 .bg-navy-light .flex.items-start.justify-between.gap-4 > .flex-1 {
    width: 100% !important;
  }
  /* Action button column — become a horizontal row at bottom */
  .space-y-4 .bg-navy-light .flex.items-start.justify-between.gap-4 > .flex.flex-col.gap-2 {
    flex-direction: row !important;
    flex-wrap: wrap !important;
    width: 100% !important;
    gap: 6px !important;
  }
  .space-y-4 .bg-navy-light .flex.items-start.justify-between.gap-4 > .flex.flex-col.gap-2 button,
  .space-y-4 .bg-navy-light .flex.items-start.justify-between.gap-4 > .flex.flex-col.gap-2 a {
    flex: 1 1 auto !important;
    text-align: center !important;
    justify-content: center !important;
  }
}

/* ── ISSUE M18 (HIGH): NDA dashboard — table with 6 columns
   (Idea / Invitee / Status / Sent / Expires / Actions).
   Already wrapped by JS [data-tto-wrap] horizontal scroll, but the
   "Idea" column uses max-w-[200px] truncate which is fine.
   The real issue: the table is inside a rounded-xl overflow-hidden
   border div. The overflow-hidden clips the horizontal scroll.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
  /* NDA dashboard table container — allow horizontal scroll */
  .rounded-xl.overflow-hidden.border:has(table) {
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch !important;
  }
  /* NDA table wrapper inside nda_dashboard */
  section > .rounded-xl.overflow-hidden {
    border-radius: 8px !important;
    overflow-x: auto !important;
  }
}

/* ── ISSUE M19 (MEDIUM): search.html — filter collapse button is
   ".sm:hidden" correctly, but the hidden filter panel uses
   display:none by default and JS toggles "hidden" class.
   When revealed on mobile the grid grid-cols-2 sm:flex layout
   works but the "Clear filters" link uses col-span-2 which is fine.
   REAL ISSUE: tab bar uses flex items-center gap-0.5 with 4 tabs.
   On 375px: 4 tabs × ~95px = 380px — just overflows. The overflow-x-auto
   is present but -mx-1 px-1 may cause clipping at page edge.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 480px) {
  /* Search tabs — ensure scrollable, no clip */
  .flex.items-center.gap-0\.5.mb-4.sm\:mb-5.border-b {
    -webkit-overflow-scrolling: touch !important;
    scrollbar-width: none !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    padding-left: 0 !important;
    padding-right: 0 !important;
  }
  .flex.items-center.gap-0\.5.mb-4.sm\:mb-5.border-b a {
    padding-left: 10px !important;
    padding-right: 10px !important;
    font-size: 11px !important;
  }
}

/* ── ISSUE M20 (MEDIUM): dashboard.html — Project Filter Tabs
   .flex items-center gap-1 mb-6 bg-navy-light rounded-lg p-1
   border border-white/10 w-fit. The "w-fit" causes the container
   to potentially overflow the viewport on 375px if the tabs are
   wide (e.g. "IP / Invention 12"). Also, "w-fit" breaks
   the global overflow-x:hidden.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  /* Project filter tabs — make scrollable instead of w-fit overflowing */
  .flex.items-center.gap-1.mb-6.bg-navy-light.rounded-lg.p-1.border.w-fit {
    width: 100% !important;
    max-width: 100% !important;
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch !important;
    scrollbar-width: none !important;
  }
  .flex.items-center.gap-1.mb-6.bg-navy-light.rounded-lg.p-1.border.w-fit a {
    flex-shrink: 0 !important;
    white-space: nowrap !important;
    font-size: 12px !important;
    padding: 6px 10px !important;
  }
}

/* ── ISSUE M21 (LOW): dashboard.html — idea list card: hash display
   "hidden sm:block" div correctly hides on mobile. But the tag/badge
   strip (.flex.items-center.flex-wrap.gap-2.mt-3) can have 6+ tags
   on one card making the card very tall on mobile. The tags are tiny
   (text-xs badge). This is acceptable — just ensure they wrap not
   overflow.
   REAL NEW ISSUE: capture CTA cards (.grid.grid-cols-1.md:grid-cols-2)
   use p-6. On mobile, the icon div is text-3xl text-white/50 w-8 h-8.
   The flex items-center justify-between makes a side-by-side layout.
   Fine. No fix needed there.

   REAL ISSUE: The empty-state onboarding card uses p-12 which wastes
   space on mobile — already caught by global .mb-32 etc? No, p-12
   is not in the override list.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  /* Empty state card — reduce excessive padding */
  .rounded-xl.border-dashed.p-12 {
    padding: 2rem 1.25rem !important;
  }
  /* Empty state icon — slightly smaller */
  .rounded-xl.border-dashed.p-12 svg.w-16 {
    width: 48px !important;
    height: 48px !important;
  }
}

/* ── ISSUE M22 (LOW): idea.html — Breadcrumb truncation
   max-w-[200px] on the idea title. On 375px this is fine (200px
   out of 375-32 padding = 343px). No fix needed.

   REAL LOW ISSUE: idea.html — "Share & Invite" bar on mobile
   already uses flex-col sm:flex-row, so it stacks correctly.
   BUT: the URL input (id="share-url") uses "select-all truncate"
   and on tap-to-select mobile it selects the full hidden URL —
   good. However the Copy Link button text "Copy Link" is fine.
   The "Add Contributor" button (flex-shrink-0) stacks below —
   already fixed. CLEAR.

   REAL LOW: settings.html — Section headings use text-3xl
   "Institution Settings" on mobile — already covered by
   global h1 { font-size: 1.5rem } fix. CLEAR.

   REAL LOW: settings.html — "Data & Privacy" section has flex-wrap
   gap-3 for the GDPR rights buttons. On 375px "Download My Data"
   (~140px) + "Request Erasure" (~125px) + 12px gap = 277px. Fits
   on 375-32=343px. Fine. CLEAR.
   ────────────────────────────────────────────────────────────── */

/* ── ISSUE M23 (LOW): idea.html — Evolution chain "Evolve" button
   col (right side): hash-display "hidden sm:block" correctly hides
   on mobile so only the Evolve button shows. The button is
   inline-flex items-center space-x-1 — fine at 375px.
   No fix needed.

   REAL ISSUE: idea.html — "Evolve This Idea" / "Upload Files"
   bottom button row: .flex.items-center.flex-wrap.gap-3. On 375px
   this wraps to 2 lines (each button ~160px). Fine. But the
   buttons have px-6 py-2.5 — touch target is 40px height which
   meets the 44px standard just barely. Add explicit min-height.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  /* Evolve / Upload buttons — ensure 44px touch target */
  .mt-4.flex.items-center.flex-wrap.gap-3 > a,
  .mt-4.flex.items-center.flex-wrap.gap-3 > button {
    min-height: 44px !important;
    display: inline-flex !important;
    align-items: center !important;
  }
  /* Full width on very small screens */
  .mt-4.flex.items-center.flex-wrap.gap-3 > a,
  .mt-4.flex.items-center.flex-wrap.gap-3 > button {
    flex: 1 1 calc(50% - 6px) !important;
    justify-content: center !important;
  }
}

/* ── ISSUE M24 (LOW): settings.html — "Always Active" span pill
   .text-xs.text-gray-500.bg-gray-700\/50.px-2.py-1.rounded-full.
   The flex items-center justify-between on the required processing
   rows wraps fine, but on 375px the "Always Active" pill and long
   label text stack awkwardly. The global flex-wrap fix handles it.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 480px) {
  /* Required processing rows — stack label/desc left, badge right */
  .flex.items-center.justify-between.py-2.border-b,
  .flex.items-center.justify-between.py-2:not(.border-b) {
    align-items: flex-start !important;
    gap: 8px !important;
  }
  /* "Always Active" pill — keep on same line as adjacent text, flex-shrink-0 */
  .flex.items-center.justify-between.py-2 > span.rounded-full {
    flex-shrink: 0 !important;
    white-space: nowrap !important;
  }
}

/* ── ISSUE M25 (LOW): challenges/detail.html — Challenge header
   flex items-start justify-between gap-4. Right side has a
   solution counter (text-3xl text-sap-orange). On 375px with a
   long title (h1 text-2xl) + sponsor badge row, the counter
   pushes to right of a ~300px column which is fine, but the
   counter is flex-shrink-0 — correct. No issue here.

   REAL LOW: challenge_detail solution submit form — "Select Your
   Locked Idea" select has option text up to 80 chars + a date.
   On mobile the select is w-full — fine. No overflow.

   REAL LOW: In nda_dashboard the table Actions column has a
   revoke form with a tiny "Revoke" text button. Touch target is
   too small (~20px). Fix with min-height.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
  /* NDA table action links/buttons — minimum touch target */
  .rounded-xl.overflow-hidden table td form button,
  .rounded-xl.overflow-hidden table td a,
  [data-tto-wrap] table td form button,
  [data-tto-wrap] table td a {
    min-height: 36px !important;
    display: inline-flex !important;
    align-items: center !important;
    padding: 6px 10px !important;
  }
}

/* ── ISSUE M26 (LOW): dashboard.html — "Recent Activity" feed
   items use .flex.items-start.space-x-3 with a dot indicator,
   user name, action, idea title all inline in one div.text-sm.
   Long idea titles with no truncation wrap correctly (word-break
   already set globally). No new issue.

   REAL LOW: dashboard.html — Achievements widget row:
   #badge-widget .flex.items-center.gap-4. The #badge-recent
   div (ml-auto) renders 5 badge pills. Each pill is ~100-140px.
   At 375px: count text (~80px) + gap-4 (16px) + 5×120px = 696px
   — massively overflows. The pills need to scroll or wrap.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  /* Badge widget — make the recent badges strip scrollable */
  #badge-widget {
    flex-wrap: wrap !important;
    gap: 8px !important;
  }
  #badge-recent {
    display: flex !important;
    flex-wrap: wrap !important;
    gap: 6px !important;
    margin-left: 0 !important;
    width: 100% !important;
  }
  #badge-recent > div {
    flex: 1 1 auto !important;
    min-width: 0 !important;
    max-width: calc(50% - 3px) !important;
    font-size: 10px !important;
    padding: 4px 8px !important;
    text-align: center !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    white-space: nowrap !important;
  }
}

/* =============================================================================
   v19.31 FIX M27 (HIGH): Idea page desktop — sticky sidebar, no blank gap.
   The lg:grid-cols-3 two-column layout leaves a visible blank area in the
   left (lg:col-span-2) column once Discussion ends, because the right sidebar
   (Provenance / AI Assistant / Actions) is taller than the left content.
   Fix: align-items:start on the grid (columns shrink to natural height) +
   sticky sidebar so it travels with the scroll rather than anchoring the row.
   Mobile (< 1024px): grid is already single-column stack, no change needed.
   ============================================================================= */
@media (min-width: 1024px) {
  /* Grid container — don't stretch columns to equal height */
  .grid.lg\:grid-cols-3.gap-6,
  .grid.gap-6.mt-6 {
    align-items: start !important;
  }

  /* Sidebar column (the one that is NOT the lg:col-span-2 main column) —
     stick to viewport top so it scrolls alongside the main column content */
  .grid.lg\:grid-cols-3.gap-6 > div:not([class*="col-span-2"]),
  .grid.gap-6.mt-6 > div:not([class*="col-span-2"]) {
    position: sticky !important;
    top: 76px !important;
    max-height: calc(100vh - 84px) !important;
    overflow-y: auto !important;
    /* hide scrollbar visually but keep scroll functional */
    scrollbar-width: none !important;
  }
  .grid.lg\:grid-cols-3.gap-6 > div:not([class*="col-span-2"])::-webkit-scrollbar,
  .grid.gap-6.mt-6 > div:not([class*="col-span-2"])::-webkit-scrollbar {
    display: none !important;
  }
}

/* =============================================================================
   v19.33 TTO FIXES
   ============================================================================= */

/* TTO tab bar — scroll fade hint so users see tabs are off-screen on mobile */
@media (max-width: 768px) {
  .flex.space-x-1.mb-6.border-b.overflow-x-auto {
    -webkit-mask-image: linear-gradient(to right, black 75%, transparent 100%) !important;
    mask-image: linear-gradient(to right, black 75%, transparent 100%) !important;
    padding-bottom: 2px !important; /* prevent border-b from being clipped */
  }
  /* Ensure active tab is always fully visible (override fade if needed) */
  .flex.space-x-1.mb-6.border-b.overflow-x-auto a.border-b-2 {
    opacity: 1 !important;
  }
}

/* TTO review modal — scrollable on short/keyboard-open viewports */
#reviewModal {
  overflow-y: auto !important;
}
#reviewModal > div {
  max-height: calc(100vh - 2rem) !important;
  overflow-y: auto !important;
}

/* De-conflict tto-quick-nav pill and episap-admin-bar on TTO pages:
   Admin bar stays at bottom-right; quick-nav floats above it */
#tto-quick-nav {
  bottom: 80px !important; /* clear the episap-admin-bar which is at bottom:24px */
}
@media (max-width: 768px) {
  #tto-quick-nav {
    bottom: 72px !important;
    right: 12px !important;
  }
}

/* ============================================================
   v19.34 FIX: Mobile menu nav links invisible on dark panel
   Root cause: FUSE-locked template applies Tailwind dark text
   classes (text-gray-800 / text-gray-900) to nav links which
   renders as invisible on the dark #mobile-menu background.
   Also: sections inside the menu panel may have display:none
   via inline style — force them visible so nav links show.
   ============================================================ */

/* Force all direct children of the inner flex wrapper visible */
#mobile-menu > div > * {
  display: block !important;
  visibility: visible !important;
  opacity: 1 !important;
}

/* Nav containers */
#mobile-menu nav,
#mobile-menu ul,
#mobile-menu ol {
  display: flex !important;
  flex-direction: column !important;
  visibility: visible !important;
  opacity: 1 !important;
}

/* All links and buttons inside the menu — white text on dark panel */
#mobile-menu a,
#mobile-menu nav a,
#mobile-menu nav button,
#mobile-menu .space-y-1 > a,
#mobile-menu .space-y-1 > button,
#mobile-menu li a,
#mobile-menu li button {
  display: flex !important;
  align-items: center !important;
  visibility: visible !important;
  opacity: 1 !important;
  color: rgba(255, 255, 255, 0.90) !important;
  text-decoration: none !important;
  padding: 0.625rem 1rem !important;
  border-radius: 0.375rem !important;
}

#mobile-menu a:hover,
#mobile-menu nav a:hover,
#mobile-menu nav button:hover {
  background-color: rgba(255, 255, 255, 0.08) !important;
  color: #ffffff !important;
}

/* Active nav item */
#mobile-menu a[class*="bg-"],
#mobile-menu a[aria-current="page"] {
  background-color: rgba(255, 255, 255, 0.12) !important;
  color: #ffffff !important;
}

/* ============================================================
   v19.34 FIX: Footer tagline overflows right edge on mobile
   Root cause: "EpiSAP Quantum Vault — Quantum Lock. Evolve. Protect."
   is a long single-line string with no break opportunity.
   Fix: allow wrapping + constrain to viewport width.
   ============================================================ */
@media (max-width: 640px) {
  footer p,
  footer [class*="text"],
  [class*="footer"] p,
  [class*="footer"] [class*="tagline"],
  [class*="footer"] h2,
  [class*="footer"] h3 {
    white-space: normal !important;
    word-break: break-word !important;
    overflow-wrap: break-word !important;
    max-width: 100% !important;
    text-align: center !important;
  }

  footer {
    overflow-x: hidden !important;
    max-width: 100vw !important;
    padding-left: 1rem !important;
    padding-right: 1rem !important;
    box-sizing: border-box !important;
  }
}

/* ============================================================
   v19.43 FIX: Footer slogan text overflow on mobile.
   Root cause: white-space:nowrap !important on footer span /
   footer [class*="text"] (v19.31 rule, ~line 1472) prevents
   the slogan paragraph "EpiSAP Quantum Vault — Quantum Lock.
   Evolve. Protect." from wrapping — it bleeds off the right
   edge of the screen on iPhone. The "Quantum" badge label is
   also cut because the same nowrap rule applies to its span.
   Fix: (a) allow <p> elements inside footer to wrap; (b) allow
   spans that are CHILDREN of footer <p> elements to wrap;
   (c) on narrow screens let the text inside icon+label badge
   pairs wrap so long labels (e.g. "Tamper-Proof") don't push
   the grid cell wider than the viewport.
   The icon+label flex-nowrap pairs (flex.items-center) are
   already kept together by the v19.31 rule — we only relax
   wrapping for the text node inside them on very small screens.
   ============================================================ */

/* --- Slogan paragraph: always allow wrap --- */
footer p,
[class*="footer"] p {
  white-space: normal !important;
  word-break: break-word !important;
  overflow-wrap: break-word !important;
  max-width: 100% !important;
}

/* Override the broad "footer span { nowrap }" for spans that
   live INSIDE a paragraph — these are slogan text fragments,
   not icon+label pairs. Higher specificity wins at !important. */
footer p span,
footer p [class*="text"],
[class*="footer"] p span {
  white-space: normal !important;
  word-break: break-word !important;
  flex-shrink: 1 !important;
}

@media (max-width: 640px) {
  /* Badge label spans inside icon+label pairs:
     allow text to wrap so a wide label doesn't bust the grid cell. */
  footer .flex.items-center span,
  [class*="footer"] .flex.items-center span {
    white-space: normal !important;
    word-break: break-word !important;
    max-width: calc(100% - 28px) !important;
  }
}

/* ============================================================
   v19.44 FIX: Footer trust-badge row uses space-x-3 (not -4/-6).
   The v19.31 grid rule only catches space-x-4 / space-x-6, so on
   mobile the four badges (Immutable / Auditable / Tamper-Proof /
   Quantum-Resistant) stay on a single horizontal row that
   overflows the viewport — "Quantum-Resistant" gets clipped off
   the right edge.
   Fix: on <=640px, force the .flex.items-center.space-x-3
   container in the footer into a 2-column grid so all four
   badges fit within the viewport without clipping.
   ============================================================ */
@media (max-width: 640px) {
  footer .flex.items-center.space-x-3,
  footer .flex.space-x-3,
  [class*="footer"] .flex.items-center.space-x-3,
  [class*="footer"] .flex.space-x-3 {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: 8px 12px !important;
    width: 100% !important;
    max-width: 100% !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    justify-items: start !important;
  }

  /* Reset Tailwind's space-x-3 negative-margin reset so grid layout works */
  footer .flex.items-center.space-x-3 > *,
  footer .flex.space-x-3 > *,
  [class*="footer"] .flex.items-center.space-x-3 > *,
  [class*="footer"] .flex.space-x-3 > * {
    margin-left: 0 !important;
    margin-right: 0 !important;
  }

  /* Each badge stays as icon + label pair, no wrap inside the cell */
  footer .flex.items-center.space-x-3 > span,
  [class*="footer"] .flex.items-center.space-x-3 > span {
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    max-width: 100% !important;
  }
}

/* ============================================================
   v19.44 FIX: TTO quick-nav pill covers modal Save buttons.
   The injected #tto-quick-nav pill is fixed bottom-right with
   z-index:9999, which sits above any z-50 modal (e.g. the New
   Disclosure modal) and blocks the action buttons.
   Fix: when a modal backdrop (.fixed.inset-0 without .hidden)
   is present in the DOM, hide the pill. Uses :has() selector
   (Safari 15.4+, Chrome 105+ — supported on all current targets).
   Also lowers the pill's effective z-index as a fallback so
   regular Tailwind z-50 modals naturally cover it on browsers
   without :has() support.
   ============================================================ */
body:has(.fixed.inset-0:not(.hidden)) #tto-quick-nav,
body:has([role="dialog"]:not(.hidden)) #tto-quick-nav,
body.modal-open #tto-quick-nav {
  display: none !important;
}
