/* ============================================================================
   APP CSS — runtime styles + theme-aware overrides for third-party widgets
   ----------------------------------------------------------------------------
   Two-theme architecture: tailwind.input.css declares the `--ink-X` palette
   variables for `:root.dark` and `:root.light`; this file consumes them via
   `rgb(var(--ink-X))` so every selector below tracks the active theme.

   Hex literals are reserved for accent colors (emerald / rose / amber / violet
   / sky), which keep their meaning across themes.
   ============================================================================ */

html {
    background-color: rgb(var(--ink-950));
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    /* color-scheme is set per-theme in tailwind.input.css */
}

html, body {
    margin: 0;
    padding: 0;
    font-family: 'Inter', 'Geist', system-ui, -apple-system, sans-serif;
    font-feature-settings: 'cv11', 'ss01';
    background-color: rgb(var(--ink-950));
    color: rgb(var(--ink-50));
}

/* Lock background scroll while any modal is open. All app modals share a
   `fixed inset-0 ... backdrop-blur-sm` overlay shell, so :has() catches them
   without needing a marker class on each modal. */
html:has(.fixed.inset-0.backdrop-blur-sm),
body:has(.fixed.inset-0.backdrop-blur-sm) {
    overflow: hidden;
}

/* mammoth.js renders .docx into plain semantic HTML; minimal prose styling
   for the preview modal — uses theme tokens so it reads correctly in both
   light and dark modes. */
.app-docx-preview { color: rgb(var(--ink-100)); line-height: 1.55; font-size: 13px; }
.app-docx-preview h1 { font-size: 1.5rem; font-weight: 600; color: rgb(var(--ink-50)); margin: 0.8em 0 0.4em; }
.app-docx-preview h2 { font-size: 1.25rem; font-weight: 600; color: rgb(var(--ink-50)); margin: 0.8em 0 0.4em; }
.app-docx-preview h3 { font-size: 1.1rem; font-weight: 600; color: rgb(var(--ink-50)); margin: 0.7em 0 0.3em; }
.app-docx-preview h4, .app-docx-preview h5, .app-docx-preview h6 { font-weight: 600; color: rgb(var(--ink-50)); margin: 0.6em 0 0.3em; }
.app-docx-preview p { margin: 0.5em 0; }
.app-docx-preview ul, .app-docx-preview ol { margin: 0.5em 0; padding-left: 1.4em; }
.app-docx-preview ul { list-style: disc; }
.app-docx-preview ol { list-style: decimal; }
.app-docx-preview li { margin: 0.2em 0; }
.app-docx-preview a { color: var(--brand-hex); text-decoration: underline; }
.app-docx-preview strong { font-weight: 600; color: rgb(var(--ink-50)); }
.app-docx-preview em { font-style: italic; }
.app-docx-preview table { border-collapse: collapse; margin: 0.6em 0; width: 100%; }
.app-docx-preview th, .app-docx-preview td { border: 1px solid rgb(var(--ink-700)); padding: 6px 8px; text-align: left; vertical-align: top; }
.app-docx-preview th { background: rgb(var(--ink-800)); font-weight: 600; }
.app-docx-preview img { max-width: 100%; height: auto; }
.app-docx-preview blockquote { border-left: 3px solid rgb(var(--ink-600)); padding-left: 0.8em; margin: 0.6em 0; color: rgb(var(--ink-300)); }

/* Range sliders with custom gradient background to paint forbidden zones.
   The track normally has its own colour; clear it so the inline-style
   gradient shows through across all browsers. */
input[type="range"] {
    -webkit-appearance: none;
    appearance: none;
    height: 6px;
    border-radius: 9999px;
    outline: none;
}
input[type="range"]::-webkit-slider-runnable-track {
    background: transparent;
    height: 6px;
    border-radius: 9999px;
}
input[type="range"]::-moz-range-track {
    background: transparent;
    height: 6px;
    border-radius: 9999px;
}
input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 14px;
    height: 14px;
    border-radius: 9999px;
    background: var(--brand-hex);
    border: 2px solid rgb(var(--ink-950));
    margin-top: -4px;
    cursor: pointer;
}
input[type="range"]::-moz-range-thumb {
    width: 14px;
    height: 14px;
    border-radius: 9999px;
    background: var(--brand-hex);
    border: 2px solid rgb(var(--ink-950));
    cursor: pointer;
}

/* UI-Skalierung: konstant 1×. Früher gab es bei ≥1900px einen
   `body { zoom: 1.5 }`-Sprung, der zwei Probleme verursachte:
   – beim Verkleinern des Fensters wirkte die UI plötzlich winzig, sobald
     1900px unterschritten wurden;
   – wer per Browser-Zoom heranzoomte, fiel beim selben Schwellwert zurück
     und musste erneut zoomen.
   Die `--app-vh-scale`-Variable bleibt für die `.app-*-panel`-Höhen-
   Formeln erhalten, ist aber jetzt fix 1 — kein conditional Override. */
:root {
    --app-vh-scale: 1;
}

.app-min-h-screen {
    min-height: calc(100vh / var(--app-vh-scale));
}

/* Fixed viewport height counterpart — locks the workspace shell to one
   screen so the sidebar (and its sticky user/theme/lang menus) stay put
   while a long board/list scrolls inside <main>. */
.app-h-screen {
    height: calc(100vh / var(--app-vh-scale));
}

/* Overlay panels (command palette, modals) need to compensate body { zoom }
   so their max-height stays inside one visual viewport at 1900px+. The
   formula is: visual viewport (100vh / scale) minus the overlay's own
   vh-based top padding (uncompensated) minus the bottom padding minus a
   small breathing margin. Mobile assumes pt-[4vh] + p-3, sm assumes
   pt-[6vh] + p-4 — keep this aligned with CommandPalette.razor's overlay. */
.app-overlay-panel {
    max-height: calc(100vh / var(--app-vh-scale) - 4vh - 1.25rem);
}
@media (min-width: 640px) {
    .app-overlay-panel {
        max-height: calc(100vh / var(--app-vh-scale) - 6vh - 1.5rem);
    }
}

/* Centered overlay modals (issue detail, …) — same zoom compensation as
   .app-overlay-panel but for the simpler "centered with p-4 padding"
   layout. Mobile fills the viewport (no overlay padding); sm caps at the
   visible viewport minus the overlay's p-4 padding plus a small buffer. */
.app-modal-panel {
    height: calc(100vh / var(--app-vh-scale));
}
@media (min-width: 640px) {
    .app-modal-panel {
        height: auto;
        max-height: calc(100vh / var(--app-vh-scale) - 2.5rem);
    }
}


/* Tiny-viewport stretch: unter 350px werden Text-Buttons und Eingabefelder
   in mit `.app-toolbar` markierten Toolbars auf 100% Breite gezogen,
   damit sie bei Wrap nicht schief untereinander stehen. Ausgenommen sind
   Icon-Only-Buttons (haben w-7/w-8/w-9) und die Segmented-Picker innerhalb
   von Dropdown-Menus (matchen den Direct-Child-Selector nicht).
   `.h-5.w-px`-Separatoren werden ausgeblendet, weil sie beim vertikalen
   Stacking keinen visuellen Mehrwert mehr bieten. */
@media (max-width: 349px) {
    /* Direkte Toolbar-Kinder (z.B. Search/Filter-Zeile) */
    .app-toolbar > .relative,
    .app-toolbar > .relative > button.inline-flex,
    .app-toolbar > button.inline-flex:not([class~="w-7"]):not([class~="w-8"]):not([class~="w-9"]),
    /* Toolbar-Kinder mit Zwischen-Gruppe (Tabs/Aktionen-Zeile) */
    .app-toolbar > * > .relative,
    .app-toolbar > * > .relative > button.inline-flex,
    .app-toolbar > * > button.inline-flex:not([class~="w-7"]):not([class~="w-8"]):not([class~="w-9"]) {
        width: 100%;
        justify-content: center;
    }
    .app-toolbar input[type="text"],
    .app-toolbar input[type="search"],
    .app-toolbar input[type="number"],
    .app-toolbar select,
    .app-toolbar textarea {
        width: 100%;
    }
    .app-toolbar .h-5.w-px {
        display: none;
    }
}

::selection {
    /* Theme-aware: white-tint in dark, black-tint in light. */
    background-color: rgb(var(--ink-50) / 0.18);
}

/* Suppress browser focus ring for programmatically focused elements
   (Blazor's <FocusOnNavigate> sets tabindex="-1" + .focus() on the
   matched heading after each navigation). */
[tabindex="-1"]:focus,
[tabindex="-1"]:focus-visible {
    outline: none;
    box-shadow: none;
}

/* Decorative gradient mesh behind the marketing/auth pages.
   Uses brand-color hints — same in both themes (hue carries identity). */
.gradient-mesh {
    background:
        radial-gradient(ellipse 80% 60% at 50% -10%, color-mix(in srgb, var(--brand-hex) 10%, transparent), transparent 60%),
        radial-gradient(ellipse 60% 50% at 80% 110%, color-mix(in srgb, var(--brand-hex) 6%, transparent), transparent 60%);
}

/* Subtle glassmorphism — works in both themes by tinting from the inverse end
   of the scale at low alpha. */
.glass {
    background: linear-gradient(180deg, rgb(var(--ink-50) / 0.04) 0%, rgb(var(--ink-50) / 0.015) 100%);
    backdrop-filter: blur(8px);
}

/* ============== AI Assistant FAB + drawer ============== */
.ai-fab {
    position: fixed;
    isolation: isolate;
}
/* Dark-mode atmospheric glow behind the FAB. Hidden in light mode —
   the 14px blur + 55% opacity colour-mix becomes invisible on the warm
   canvas and would just burn CPU on every browser tab. */
.ai-fab-glow {
    position: absolute;
    inset: -6px;
    border-radius: 9999px;
    background: conic-gradient(from 0deg,
        color-mix(in srgb, var(--brand-hex) 50%, transparent),
        rgba(124,58,237,0.5),
        color-mix(in srgb, var(--brand-hex) 50%, transparent));
    filter: blur(14px);
    opacity: 0.55;
    animation: ai-fab-spin 8s linear infinite;
    z-index: -1;
}
.ai-fab:hover .ai-fab-glow { opacity: 0.85; }
.ai-fab-open .ai-fab-glow { opacity: 0.3; }

:root.light .ai-fab-glow,
:root:not(.dark) .ai-fab-glow {
    display: none;
}
@keyframes ai-fab-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}
.ai-fab-inner {
    transition: transform 200ms cubic-bezier(.2,.7,.3,1);
}
.ai-fab:hover .ai-fab-inner { transform: scale(1.04); }

.ai-drawer {
    animation: ai-drawer-in 220ms cubic-bezier(.2,.7,.3,1);
}
@keyframes ai-drawer-in {
    from { transform: translateX(100%); opacity: 0; }
    to   { transform: translateX(0);    opacity: 1; }
}

/* Markdown rendering inside chat bubbles + AI panels — theme-aware */
.markdown { word-wrap: break-word; }
.markdown p { margin: 0 0 0.5em; }
.markdown p:last-child { margin-bottom: 0; }
.markdown h1, .markdown h2, .markdown h3, .markdown h4 {
    margin: 0.6em 0 0.3em;
    font-weight: 600;
    color: rgb(var(--ink-50));
    letter-spacing: -0.005em;
}
.markdown h1 { font-size: 1.05em; }
.markdown h2 { font-size: 1em; }
.markdown h3 { font-size: 0.95em; }
.markdown ul, .markdown ol { margin: 0.3em 0 0.5em; padding-left: 1.25em; }
.markdown ul { list-style: disc; }
.markdown ol { list-style: decimal; }
.markdown li { margin: 0.15em 0; }
.markdown li > input[type="checkbox"] { margin-right: 0.4em; }
.markdown code {
    background: rgb(var(--ink-50) / 0.07);
    border: 1px solid rgb(var(--ink-50) / 0.06);
    border-radius: 4px;
    padding: 0.05em 0.35em;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.92em;
    color: rgb(var(--ink-100));
}
.markdown pre {
    background: rgb(var(--ink-925));
    border: 1px solid rgb(var(--ink-50) / 0.06);
    border-radius: 8px;
    padding: 0.6em 0.8em;
    overflow-x: auto;
    margin: 0.5em 0;
}
.markdown pre code {
    background: transparent;
    border: 0;
    padding: 0;
    font-size: 0.88em;
}
.markdown a {
    color: var(--brand-hex);
    text-decoration: underline;
    text-underline-offset: 2px;
}
.markdown strong { color: rgb(var(--ink-50)); font-weight: 600; }
.markdown blockquote {
    border-left: 2px solid color-mix(in srgb, var(--brand-hex) 45%, transparent);
    padding-left: 0.7em;
    color: rgb(var(--ink-300));
    margin: 0.5em 0;
}
.markdown hr {
    border: 0;
    border-top: 1px solid rgb(var(--ink-50) / 0.08);
    margin: 0.8em 0;
}

/* Bilder im Markdown-Render UND im WYSIWYG-Editor begrenzen, sonst sprengt
   ein hochkant geknipstes Phone-Foto den Issue-Dialog und Text vor/ihm ist
   gar nicht mehr lesbar ohne wildes Scrollen. width:auto+max-width hält
   die Original-Aspect-Ratio, max-height verhindert das Riesen-Banner
   auf Querformat. Pointer-Cursor signalisiert klickbar (Lightbox kommt
   später — fürs erste reicht das Begrenzen). */
.markdown img,
.toastui-editor-contents img,
.toastui-editor-ww-container img,
.ProseMirror img {
    display: block;
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: 360px;
    margin: 0.5em 0;
    border-radius: 6px;
    object-fit: contain;
}

/* ============== Command palette ============== */
.cmdk-overlay { animation: cmdk-fade-in 140ms ease-out; }
.cmdk-panel {
    animation: cmdk-pop-in 180ms cubic-bezier(.2,.7,.3,1);
    transform-origin: top center;
}

/* KI-Intake-Review-Overlay (Issue-Modal). Eigene Animationen statt der
   cmdk-Klassen, weil das Pop hier aus der Mitte aufpoppt (transform-
   origin: center) und damit zentraler/präsenter wirkt — die cmdk-
   Variante kommt von oben, das passt für ein Command-Palette, nicht
   für einen modalen Status-Dialog. */
.vt-intake-fade { animation: cmdk-fade-in 160ms ease-out; }
.vt-intake-pop {
    animation: vt-intake-pop-in 220ms cubic-bezier(.2,.7,.3,1);
    transform-origin: center;
}
@keyframes vt-intake-pop-in {
    from { opacity: 0; transform: scale(0.94); }
    to   { opacity: 1; transform: scale(1); }
}
@keyframes cmdk-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}
@keyframes cmdk-pop-in {
    from { opacity: 0; transform: translateY(-8px) scale(0.98); }
    to   { opacity: 1; transform: translateY(0)    scale(1); }
}
kbd {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* AI suggestion preview — gradient border (brand colours, theme-stable) */
.ai-suggestion {
    background: linear-gradient(135deg, color-mix(in srgb, var(--brand-hex) 45%, transparent), rgba(124,58,237,0.45));
    box-shadow: 0 8px 24px -10px color-mix(in srgb, var(--brand-hex) 25%, transparent);
}

/* ============== Toast UI Editor — theme-aware polish ============== */
.toastui-editor-defaultUI {
    border-radius: 8px;
    border-color: rgb(var(--ink-700) / 0.9) !important;
    background: rgb(var(--ink-900) / 0.6) !important;
    overflow: hidden;
}
/* Toast UI's own toolbar is suppressed via toolbarItems: [] — we render our
   own SVG-based toolbar in Razor (see app-md-toolbar). Anything Toast UI
   re-injects (e.g. the empty defaultUI-toolbar shell) is collapsed flat. */
.toastui-editor-toolbar,
.toastui-editor-defaultUI-toolbar {
    display: none !important;
}
.toastui-editor-tooltip { display: none !important; }

/* Custom markdown toolbar — sits above the editor mount point, wraps freely
   on narrow viewports so every action stays reachable without a More menu. */
.app-md-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 8px; /* row-gap 4px / column-gap 8px — wider gap between groups
                     replaces the divider so wrapped lines don't show a stray
                     vertical bar at the left edge. */
    padding: 4px 6px;
    border: 1px solid rgb(var(--ink-700) / 0.7);
    border-bottom: 0;
    border-top-left-radius: 8px;
    border-top-right-radius: 8px;
    background: rgb(var(--ink-850) / 0.6);
}
.app-md-toolbar-group {
    display: flex;
    align-items: center;
    gap: 2px;
}
.app-md-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 6px;
    color: rgb(var(--ink-300));
    background: transparent;
    border: 0;
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease;
    font-family: inherit;
    font-weight: 600;
    font-size: 12.5px;
    flex-shrink: 0;
}
.app-md-btn:hover {
    background: rgb(var(--ink-50) / 0.07);
    color: rgb(var(--ink-100));
}
.app-md-btn.is-active {
    background: color-mix(in srgb, var(--brand-hex) 18%, transparent);
    color: rgb(110, 231, 183);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--brand-hex) 55%, transparent);
}
.app-md-btn.is-active:hover {
    background: color-mix(in srgb, var(--brand-hex) 26%, transparent);
    color: rgb(167, 243, 208);
}
:root.light .app-md-btn.is-active {
    background: color-mix(in srgb, var(--brand-hex) 16%, transparent);
    color: rgb(4, 120, 87);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--brand-hex) 45%, transparent);
}
.app-md-btn:active { transform: translateY(1px); }
.app-md-btn svg { width: 14px; height: 14px; }
@media (max-width: 640px) {
    .app-md-btn { width: 38px; height: 38px; }
    .app-md-toolbar { padding: 6px 8px; }
}

/* Editor wrapper has the toolbar's bottom-edge attached, so its top corners
   should not round (otherwise a double-border kink appears). Toast UI mounts
   .toastui-editor-defaultUI *inside* our mount div (.app-md-editor-mount),
   so the selector must descend into the mount — a plain `+` combinator never
   matches the Toast UI element directly. */
.app-md-toolbar + .app-md-editor-mount,
.app-md-toolbar + .app-md-editor-mount .toastui-editor-defaultUI,
.app-md-toolbar + .app-md-editor-mount .toastui-editor-ww-container,
.app-md-toolbar + .app-md-editor-mount .toastui-editor-md-container,
.app-md-toolbar + .app-md-editor-mount .toastui-editor {
    margin-top: 0 !important;
    border-top-left-radius: 0 !important;
    border-top-right-radius: 0 !important;
}

/* ── Foldable section ──────────────────────────────────────────────────────
   Used inside the issue-detail modal to group secondary fields under a
   collapsible header. Native <details>/<summary> for state, custom CSS to
   hide the default disclosure marker and rotate our chevron.

   The container styling — full border, rounded, padded — lives here so
   every foldable in the sidebar visually frames "what belongs to whom"
   without per-instance Tailwind classes. When open, a thin divider
   separates the summary from the body. */
.app-foldable {
    border: 1px solid rgb(var(--ink-800));
    background: rgb(var(--ink-900) / 0.3);
    border-radius: 0.375rem; /* matches Tailwind rounded-md */
    padding: 0.5rem 0.75rem; /* py-2 px-3 */
    /* Animate hover-state in/out so the highlight feels deliberate
       rather than snapping on. */
    transition: border-color 150ms ease,
                background-color 150ms ease,
                box-shadow 150ms ease;
}
/* Hover-highlight in the modal's teal accent — works for both [open] and
   collapsed states, so the user can always tell which foldable their
   cursor is on. The outer box-shadow gives the "leichtes Leuchten" without
   shifting layout. Teal-500 (#14b8a6) at low alpha matches the rest of
   the modal's accent palette without competing for attention. */
.app-foldable:hover {
    border-color: color-mix(in srgb, var(--brand-hex) 40%, transparent);
    background: color-mix(in srgb, var(--brand-hex) 6%, transparent);
    box-shadow: 0 0 12px -4px color-mix(in srgb, var(--brand-hex) 28%, transparent);
}
.app-foldable > summary {
    list-style: none;
    cursor: pointer;
    user-select: none;
}
.app-foldable[open] > summary {
    padding-bottom: 0.5rem;
    margin-bottom: 0.5rem;
    border-bottom: 1px solid rgb(var(--ink-800) / 0.6);
}
/* Open-state divider picks up the teal tint while hovered so the inner
   line doesn't look out of place against the glowing border. */
.app-foldable[open]:hover > summary {
    border-bottom-color: color-mix(in srgb, var(--brand-hex) 25%, transparent);
}
.app-foldable > summary::-webkit-details-marker { display: none; }
.app-foldable > summary::marker { display: none; }
.app-foldable > summary .chev {
    transition: transform 150ms ease;
}
.app-foldable[open] > summary .chev {
    transform: rotate(180deg);
}
/* Flush-Variante: am Spaltenende gestapelte Foldables sollen als EIN
   zusammenhängender Block wirken statt als einzelne, sich mit 0-Gap
   berührende Karten. Keine Rundung; die Naht zwischen zwei flush-Foldables
   teilt sich eine Border (kein doppelter 2px-Strich). */
.app-foldable--flush { border-radius: 0; }
.app-foldable--flush + .app-foldable--flush { border-top: 0; }

/* ── Marquee on hover ──────────────────────────────────────────────────────
   Single-line text that scrolls horizontally when hovered. Pure CSS via
   duplicated content (two copies of the same text inside a track that
   translates by -50% - gap). Used in cramped contexts (sub-issue title
   rows, etc.) where wrapping would blow up row height — combine with the
   `title="..."` attribute for the native tooltip fallback. */
.app-marquee {
    overflow: hidden;
    white-space: nowrap;
    min-width: 0;
}
.app-marquee-track {
    display: inline-block;
    will-change: transform;
}
.app-marquee-text {
    display: inline-block;
}
/* Standardmäßig: nur erste Kopie sichtbar, kein Padding rechts (sonst
   bleibt nach kurzem Text immer ein weißer Streifen). Marquee-Animation +
   zweite Kopie + Padding-Spalt werden ausschließlich aktiviert, wenn das
   JS (marquee-overflow.js) festgestellt hat, dass der Text überläuft. Bei
   Texten, die in den Container passen, gibt es kein „Sliden" — der Text
   bleibt statisch und liefert den vollständigen Inhalt per title-Tooltip. */
.app-marquee-text + .app-marquee-text {
    display: none;
}
.app-marquee[data-overflowing="true"] .app-marquee-text {
    padding-right: 2rem;
}
.app-marquee[data-overflowing="true"]:hover .app-marquee-text + .app-marquee-text {
    display: inline-block;
}
.app-marquee[data-overflowing="true"]:hover .app-marquee-track {
    animation: app-marquee-scroll 8s linear infinite;
}
@keyframes app-marquee-scroll {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}
.toastui-editor-main { background: transparent !important; }
.toastui-editor-md-container,
.toastui-editor-ww-container { background: transparent !important; }
.toastui-editor-contents,
.toastui-editor .ProseMirror {
    color: rgb(var(--ink-100)) !important;
    font-family: 'Inter', system-ui, sans-serif !important;
    font-size: 13px !important;
    line-height: 1.6 !important;
    padding: 14px 16px !important;
}
.toastui-editor-contents h1,
.toastui-editor-contents h2,
.toastui-editor-contents h3,
.toastui-editor-contents h4 {
    color: rgb(var(--ink-50)) !important;
    border-bottom: 0 !important;
    margin: 0.7em 0 0.35em !important;
    padding-bottom: 0 !important;
    font-weight: 600 !important;
    letter-spacing: -0.005em !important;
}
.toastui-editor-contents h1 { font-size: 1.4em !important; }
.toastui-editor-contents h2 { font-size: 1.2em !important; }
.toastui-editor-contents h3 { font-size: 1.05em !important; }
.toastui-editor-contents p {
    margin: 0.35em 0 !important;
    color: rgb(var(--ink-200)) !important;
}
.toastui-editor-contents ul,
.toastui-editor-contents ol { padding-left: 1.4em !important; }
.toastui-editor-contents li > p { margin: 0.1em 0 !important; }
.toastui-editor-contents code {
    background: rgb(var(--ink-50) / 0.06) !important;
    border: 1px solid rgb(var(--ink-50) / 0.05) !important;
    border-radius: 4px !important;
    padding: 0.05em 0.4em !important;
    color: rgb(var(--ink-100)) !important;
    font-size: 0.9em !important;
}
.toastui-editor-contents pre {
    background: rgb(var(--ink-925)) !important;
    border: 1px solid rgb(var(--ink-50) / 0.06) !important;
    border-radius: 8px !important;
    padding: 0.7em 0.9em !important;
}
.toastui-editor-contents blockquote {
    border-left: 2px solid color-mix(in srgb, var(--brand-hex) 45%, transparent) !important;
    color: rgb(var(--ink-300)) !important;
    background: color-mix(in srgb, var(--brand-hex) 4%, transparent) !important;
    padding: 0.4em 0.9em !important;
    border-radius: 0 6px 6px 0 !important;
    margin: 0.4em 0 !important;
}
.toastui-editor-contents a {
    color: var(--brand-hex) !important;
    text-underline-offset: 2px;
}
.toastui-editor-contents .task-list-item { padding-left: 0 !important; }
.toastui-editor-contents .task-list-item:before {
    border-color: color-mix(in srgb, var(--brand-hex) 45%, transparent) !important;
    background: transparent !important;
}
.toastui-editor-contents .task-list-item.checked:before {
    background: var(--brand-hex) !important;
    border-color: var(--brand-hex) !important;
}
.toastui-editor-mode-switch { display: none !important; }
.toastui-editor-tooltip {
    border-radius: 4px !important;
    background: rgb(var(--ink-850) / 0.95) !important;
    border: 1px solid rgb(var(--ink-600) / 0.6) !important;
    color: rgb(var(--ink-200)) !important;
}
.toastui-editor-popup {
    background: rgb(var(--ink-900) / 0.95) !important;
    border: 1px solid rgb(var(--ink-600) / 0.6) !important;
    border-radius: 8px !important;
    color: rgb(var(--ink-200)) !important;
}

/* Force placeholders to wrap and break long tokens: some browsers default to
   white-space: pre on ::placeholder, which creates a horizontal scrollbar
   inside an empty textarea. */
textarea::placeholder,
textarea::-webkit-input-placeholder,
textarea::-moz-placeholder {
    white-space: pre-wrap !important;
    overflow-wrap: anywhere !important;
    word-break: break-all !important;
    text-overflow: clip !important;
}

/* overflow-x: clip (vs hidden) also blocks programmatic/drag-selection
   auto-scroll inside an otherwise-empty textarea. */
textarea {
    overflow-x: clip;
    overflow-wrap: anywhere;
    word-break: break-all;
}

/* Marquee for the running-timer bar title. JS clones the single span when its
   content overflows the wrap; -50% slides the doubled track exactly one copy
   so the loop is seamless. */
.marquee-active {
    animation: marquee-scroll 14s linear infinite;
    will-change: transform;
}
@keyframes marquee-scroll {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}

/* ============================================================================
   LIGHT MODE — accent-text overrides
   ----------------------------------------------------------------------------
   Tailwind's `text-{color}-{100..400}` shades are designed for DARK
   backgrounds — pastel/soft so they pop against ink-900. In light mode they
   land near-white-on-white and become illegible (e.g. the "Owner" badge,
   @-mention pill, tag chips, "Sign out" link, expired-due chip, etc.).

   Inverting the Tailwind scale for accent-text works because tints with
   matching hue at darker values keep the semantic colour cue (red still reads
   "danger", green still "success") while restoring contrast.

   Rule of thumb applied here:
     {100,200,300}  →  shift to 700–800 (saturated, dark-on-light)
     {400}          →  shift to 600     (still vivid, slightly punchier)
     {500}          →  unchanged        (mid value works in both)
     {50}           →  NOT overridden   (paired exclusively with bg-{color}-{600,700}
                                          — the avatar pattern; it MUST stay near-white
                                          so initials read on the saturated dark bg)

   Backgrounds (`bg-{color}-500/15`) and rings (`ring-{color}-400/30`) need
   no override — they're alpha tints that re-read against the new canvas.

   Specificity: `:root.light .text-…` is (0,0,3,0) = 30, beating Tailwind's
   `.text-…` = (0,0,1,0) = 10 without `!important`.
   ============================================================================ */

/* ---- emerald (success / primary action) ---- */
:root.light .text-emerald-100 { color: rgb(6   95  70); }
:root.light .text-emerald-200 { color: rgb(4   120 87); }
:root.light .text-emerald-300 { color: rgb(4   120 87); }
:root.light .text-emerald-400 { color: rgb(5   150 105); }
:root.light .hover\:text-emerald-100:hover { color: rgb(6   95  70); }
:root.light .hover\:text-emerald-200:hover { color: rgb(4   120 87); }
:root.light .hover\:text-emerald-300:hover { color: rgb(4   120 87); }
:root.light .group:hover .group-hover\:text-emerald-200 { color: rgb(4   120 87); }

/* ---- rose (danger / destructive) ---- */
:root.light .text-rose-100 { color: rgb(159 18  57); }
:root.light .text-rose-200 { color: rgb(190 18  60); }
:root.light .text-rose-300 { color: rgb(190 18  60); }
:root.light .text-rose-400 { color: rgb(225 29  72); }
:root.light .hover\:text-rose-100:hover { color: rgb(159 18  57); }
:root.light .hover\:text-rose-200:hover { color: rgb(190 18  60); }
:root.light .hover\:text-rose-300:hover { color: rgb(190 18  60); }

/* ---- amber (warning / pending) ---- */
:root.light .text-amber-100 { color: rgb(146 64  14); }
:root.light .text-amber-200 { color: rgb(180 83  9);  }
:root.light .text-amber-300 { color: rgb(180 83  9);  }
:root.light .text-amber-400 { color: rgb(217 119 6);  }
:root.light .hover\:text-amber-100:hover { color: rgb(146 64  14); }
:root.light .hover\:text-amber-200:hover { color: rgb(180 83  9);  }

/* ---- violet (mention / second-tier accent) ---- */
:root.light .text-violet-100 { color: rgb(91  33  182); }
:root.light .text-violet-200 { color: rgb(109 40  217); }
:root.light .text-violet-300 { color: rgb(109 40  217); }
:root.light .text-violet-400 { color: rgb(124 58  237); }
:root.light .hover\:text-violet-200:hover { color: rgb(109 40  217); }

/* ---- sky (info / assignment) ---- */
:root.light .text-sky-100 { color: rgb(7   89  133); }
:root.light .text-sky-200 { color: rgb(3   105 161); }
:root.light .text-sky-300 { color: rgb(3   105 161); }
:root.light .text-sky-400 { color: rgb(2   132 199); }
:root.light .hover\:text-sky-200:hover { color: rgb(3   105 161); }

/* ---- cyan (integration badge) ---- */
:root.light .text-cyan-100 { color: rgb(22  78  99);  }
:root.light .text-cyan-200 { color: rgb(21  94  117); }
:root.light .text-cyan-300 { color: rgb(21  94  117); }
:root.light .text-cyan-400 { color: rgb(14  116 144); }
:root.light .hover\:text-cyan-200:hover { color: rgb(21  94  117); }

/* ---- Opacity-Modifier-Varianten (text-emerald-300/80 etc.) -----------
   Die obigen Selektoren matchen nur die nackten `.text-{color}-{shade}`-
   Klassen. Bei Tailwind erzeugen Opacity-Modifier wie `/80` aber EIGENE
   Klassen (`.text-emerald-300\/80`), die NICHT auf die Override-Regel
   oben matchen — Texte mit /XY blieben in Light-Mode unsichtbar (z. B.
   die laufende Timer-Zeile mit text-emerald-100/200/300 auf bg-emerald-
   500/[0.06]). Hier setzen wir für jede tatsächlich im Repo verwendete
   Variante die Farbe explizit auf die Light-Variante mit Alpha. */

/* --- emerald (success) --- */
:root.light .text-emerald-100\/80  { color: rgb(6   95  70  / 0.80); }
:root.light .text-emerald-100\/90  { color: rgb(6   95  70  / 0.90); }
:root.light .text-emerald-200\/70  { color: rgb(4   120 87  / 0.70); }
:root.light .text-emerald-200\/80  { color: rgb(4   120 87  / 0.80); }
:root.light .text-emerald-200\/90  { color: rgb(4   120 87  / 0.90); }
:root.light .text-emerald-300\/60  { color: rgb(4   120 87  / 0.60); }
:root.light .text-emerald-300\/70  { color: rgb(4   120 87  / 0.70); }
:root.light .text-emerald-300\/80  { color: rgb(4   120 87  / 0.80); }
:root.light .text-emerald-400\/80  { color: rgb(5   150 105 / 0.80); }

/* --- rose (danger) --- */
:root.light .text-rose-200\/70     { color: rgb(190 18  60  / 0.70); }
:root.light .text-rose-300\/60     { color: rgb(190 18  60  / 0.60); }
:root.light .text-rose-300\/70     { color: rgb(190 18  60  / 0.70); }
:root.light .text-rose-300\/80     { color: rgb(190 18  60  / 0.80); }

/* --- amber (warning) --- */
:root.light .text-amber-100\/80    { color: rgb(146 64  14  / 0.80); }
:root.light .text-amber-200\/70    { color: rgb(180 83  9   / 0.70); }
:root.light .text-amber-200\/80    { color: rgb(180 83  9   / 0.80); }
:root.light .text-amber-200\/90    { color: rgb(180 83  9   / 0.90); }
:root.light .text-amber-300\/60    { color: rgb(180 83  9   / 0.60); }
:root.light .text-amber-300\/70    { color: rgb(180 83  9   / 0.70); }

/* --- sky (info) --- */
:root.light .text-sky-300\/60      { color: rgb(3   105 161 / 0.60); }
:root.light .text-sky-300\/70      { color: rgb(3   105 161 / 0.70); }
:root.light .text-sky-300\/90      { color: rgb(3   105 161 / 0.90); }
:root.light .text-sky-400\/80      { color: rgb(2   132 199 / 0.80); }

/* --- violet --- */
:root.light .text-violet-300\/60   { color: rgb(109 40  217 / 0.60); }
:root.light .text-violet-300\/70   { color: rgb(109 40  217 / 0.70); }
:root.light .text-violet-400\/80   { color: rgb(124 58  237 / 0.80); }

/* --- cyan --- */
:root.light .text-cyan-300\/70     { color: rgb(21  94  117 / 0.70); }

/* ---- Primary-Action-Button-Hover (bg-ink-50 hover:bg-white) ---------------
   Das app-weite Pattern für primäre Aktions-Buttons ist:
       bg-ink-50 hover:bg-white text-ink-950
   In Dark-Mode: ink-50 = fast weiß (250), Hover → reines Weiß (255) = subtiler
   Helligkeits-Push, text-ink-950 (= dunkel) bleibt lesbar.
   In Light-Mode aber ist ink-50 invertiert (= dunkel ~9) und text-ink-950
   = hell (~250). Der Hover ging dann von dunklem Button auf REINES WEISS
   während die Schrift hell blieb → weiß-auf-weiß, Button verschwindet.
   Fix: hover:bg-white in Light-Mode auf ink-100 mappen (ist im invertierten
   Palette nur 15 Punkte heller als ink-50 → identische subtile Aufhellung
   wie im Dark-Mode, aber der Button bleibt dunkel und die Schrift sichtbar.
   Plain `bg-white` ohne Hover bleibt unangetastet (kann beabsichtigt sein
   für echte weiße Surfaces wie Modal-Karten). */
:root.light .hover\:bg-white:hover {
    background-color: rgb(var(--ink-100));
}

/* ---- "Primary action" button gradient -------------------------------------
   The `bg-gradient-to-b from-white to-ink-200 text-ink-950` pattern is the
   app-wide pill-button style. In dark mode the gradient is a subtle white →
   light-gray (Apple-style metallic) with dark text — perfect contrast on the
   ink-950 page. In light mode we swap to the tenant's brand colour so the
   same primary button becomes a brand-coloured pill (text-ink-950 is white in
   the inverted palette — perfect contrast on the brand bg). Text-gradient
   uses have `text-transparent` so :not(.text-transparent) leaves them alone. */
:root.light .from-white:not(.text-transparent) {
    --tw-gradient-from: var(--brand-hex) var(--tw-gradient-from-position);
    --tw-gradient-to: color-mix(in srgb, var(--brand-hex) 72%, black) var(--tw-gradient-to-position);
    --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
}
/* The :hover variant on the same gradient (used in a few CTAs) */
:root.light .hover\:from-white:hover:not(.text-transparent) {
    --tw-gradient-from: color-mix(in srgb, var(--brand-hex) 90%, white) var(--tw-gradient-from-position);
    --tw-gradient-to: color-mix(in srgb, var(--brand-hex) 65%, black) var(--tw-gradient-to-position);
    --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
}

/* Native <select> overrides moved to Styles/overrides.css (design-system). */

/* The /80 / /90 variants on ink-500 used as muted text on coloured chips also
   slip below the readability threshold — anchor them at ink-300 (which our
   theme map already inverts to a much darker grey in light mode). */
:root.light .text-ink-500\/80,
:root.light [class*="text-ink-500"][class*="/80"] { color: rgb(var(--ink-300)); }

/* Avatar stack: left-on-top stacking for overlapping avatar groups. The
   default DOM-order paint puts later siblings above earlier ones, which
   covers the bottom-right online indicator on the leftmost avatar. We
   invert the order so each avatar sits on top of the next one to its
   right. Applied wherever we use `-space-x-*` to overlap avatars; the
   `+N` counter falls to the bottom of the stack as the rightmost element.
   nth-child up to 8 covers every current and reasonably foreseeable group
   (board members, assignees, channel visibility); anything past that
   falls through to z-index:1 and stacks like before. */
.avatar-stack > * { position: relative; z-index: 1; }
.avatar-stack > *:nth-child(1) { z-index: 8; }
.avatar-stack > *:nth-child(2) { z-index: 7; }
.avatar-stack > *:nth-child(3) { z-index: 6; }
.avatar-stack > *:nth-child(4) { z-index: 5; }
.avatar-stack > *:nth-child(5) { z-index: 4; }
.avatar-stack > *:nth-child(6) { z-index: 3; }
.avatar-stack > *:nth-child(7) { z-index: 2; }
