@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700&display=swap');

html {
    scroll-behavior: smooth;
    scroll-padding-top: 90px;
}

body {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

/* Improved text readability */
p {
    line-height: 1.6;
    margin-bottom: 1rem;
}

/* Better heading spacing */
h1, h2, h3, h4, h5, h6 {
    margin-top: 1.5em;
    margin-bottom: 0.5em;
    line-height: 1.3;
}

h1:first-child,
h2:first-child,
h3:first-child {
    margin-top: 0;
}

/* Link styling */
a {
    transition: all 0.2s ease;
}

/* Better list spacing */
ul, ol {
    margin-bottom: 1rem;
    padding-left: 1.5rem;
}

li {
    margin-bottom: 0.5rem;
}

/* Blockquote styling */
blockquote {
    /* Follows PRIMARY_COLOR in lib/constants.py. The template hard-coded
       teal-5, so a fork that changed its primary colour still drew every
       blockquote rule in the template's accent. */
    border-left: 4px solid var(--mantine-color-violet-5);
    padding-left: 1rem;
    margin-left: 0;
    margin-right: 0;
    font-style: italic;
    color: var(--mantine-color-dimmed);
}

input:invalid {
    outline: none !important;
}

#wrapper {
    padding: 10px;
    margin-left: 320px;
    margin-right: 320px;
}

:root[data-mantine-color-scheme="dark"] #dark-theme-icon {
    display: none;
}

:root[data-mantine-color-scheme="light"] #light-theme-icon {
    display: none;
}

.demo-container {
    display: flex;
    max-width: 100%;
    overflow: hidden;
}

.demo-preview {
    flex: 1;
    display: flex;
    flex-direction: column;
    padding: 20px;
    justify-content: center;
}

.demo-controls {
    width: 250px;
    padding: 20px;
    gap: 10px;
}

.demo-control {
    margin: 10px;
}

@media only screen and (max-width: 750px) {
    .demo-container {
        flex-direction: column;
    }

    .demo-controls {
        width: 100%;
    }
}

.dmc-bar {
    background-image: linear-gradient(to right, yellow, orange);
}

.dmc-thumb {
    border-color: orange;
    height: 20px;
    width: 20px;
    background-color: white;
}

.mantine-Table-th {
    font-size: 15px;
    font-weight: 500;
}

.dmc-indicator {
  width: 12px;
  height: 4px;
  transition: width 250ms ease;

  &[data-active] {
    width: 40px;
  }
}

.dmc-control {
  &[data-inactive] {
    opacity: 0;
    cursor: default;
  }
}

.dmc-controls {
  transition: opacity 150ms ease;
  opacity: 0;
}

.dmc-root {
  &:hover {
    .dmc-controls {
      opacity: 1;
    }
  }
}



.dmc-slider-track {
  &::before {
    background-color: light-dark(var(--mantine-color-blue-1), var(--mantine-color-dark-3));
  }
}

.dmc-slider-mark {
  width: 6px;
  height: 6px;
  border-radius: 6px;
  transform: translateX(-3px) translateY(-2px);
  border-color: light-dark(var(--mantine-color-blue-1), var(--mantine-color-dark-3));

  &[data-filled] {
    border-color: var(--mantine-color-blue-6);
  }
}

.dmc-slider-markLabel {
  font-size: var(--mantine-font-size-sm);
  color: var(--mantine-color-green-5);
  margin-bottom: 5px;
  margin-top: 0;
}

.dmc-slider-thumb {
  height: 16px;
  width: 16px;
  background-color: var(--mantine-color-green-5);
  border-width: 1px;
  box-shadow: var(--mantine-shadow-lg);
}

.navbar-link {
    padding: 0.5rem 1rem;
    border-radius: 0.25rem;
    transition: background 0.1s;
    color: inherit;
    display: inline-flex;
    gap: 0.5rem;

    &:hover {
        text-decoration: none;
        background: color-mix(in srgb, var(--mantine-color-gray-5), transparent 90%);
    }
}

/* Mobile drawer nav: full-width rows with a 44px touch target, per the
   iOS/Android minimum. The desktop navbar keeps the compact inline-flex look. */
.mobile-nav .navbar-link {
    display: flex;
    align-items: center;
    width: 100%;
    min-height: 44px;
    padding: 0.625rem 0.75rem;
    border-radius: 0.375rem;
    -webkit-tap-highlight-color: transparent;
}

.mobile-nav .navbar-link:active {
    background: color-mix(in srgb, var(--mantine-color-gray-5), transparent 80%);
}

/* ---------------------------------------------------------------------------
 * REMOVED 2026-08-21: three rules that targeted Mantine's INTERNAL hashed
 * class names (`.m_46b77525`, `.m_5caae85b`, `.m_9cdde9a`).
 *
 * Those hashes are private, version-unstable build artifacts. They are not
 * API, nothing guarantees which component a given hash names in the next
 * release, and two of these carried `!important` — so they beat the inline
 * styles Mantine writes for layout. Audited against the installed DMC 2.8
 * bundle:
 *
 *   .m_5caae85b   ZERO occurrences — the component it once styled is gone.
 *                 A dead rule that would silently spring back to life the
 *                 day Mantine reissues that hash for something else.
 *   .m_9cdde9a    the AppShell ASIDE. The rule re-declared width, transform
 *                 and z-index that Mantine already sets from its own custom
 *                 properties — and added a stray `margin-top: 15px`, which
 *                 is why the Table of Contents sat 15px lower than the
 *                 content it indexes.
 *   .m_46b77525   the header's search Select wrapper; replaced below with a
 *                 selector that says so.
 *
 * This is the lesson 2plot_leaflet recorded after a `.m_b8a05bbd` rule —
 * the Drawer content — silently overrode the network-standard drawer's
 * docking styles and left that host's mobile navigation floating. Style
 * Mantine components through their props and `styles={}`, or through the
 * stable `.mantine-<Component>-<part>` selectors the Styles API guarantees.
 * Never through an `.m_*` hash.
 * ------------------------------------------------------------------------ */

/* The header's search Select, nudged down to sit on the header's baseline.
   Scoped to the header on purpose: the mobile drawer renders its own Select
   (`#mobile-select-component`) which must NOT inherit this offset. */
header.mantine-AppShell-header .mantine-Select-root {
    margin-top: calc(0.5rem * var(--mantine-scale));
}

/* ---------------------------------------------------------------------------
 * Markdown tables scroll INSIDE their own box.
 *
 * A `<table>` is min-content sized: it refuses to shrink below the widest
 * unbreakable cell, and with `overflow: visible` it simply bursts out of its
 * container and drags the whole page wide with it. Measured on the home page
 * at a 414px viewport: the "Upstream shape / What Python sees / Why" table
 * rendered 471px wide inside a 318px column and the document scrolled 105px
 * horizontally — so every paragraph on the page could be swiped sideways.
 *
 * `display: block` makes the table an ordinary block box that can own an
 * overflow; `width: max-content` keeps the columns at their natural widths
 * instead of squashing them into unreadable slivers; `max-width: 100%` caps
 * the box at the container so it cannot push the page; `overflow-x: auto`
 * gives the table its own horizontal scroll. Above the container width the
 * four together are a no-op, so nothing changes on a desktop.
 *
 * Scoped to the markdown page bodies (`#m2d-page-*`, set by pages/markdown.py
 * and pages/home.py) and explicitly NOT to `dmc.Table`, which /file-uploads
 * renders and which has its own scroll container.
 * ------------------------------------------------------------------------ */
[id^="m2d-page"] table:not(.mantine-Table-root) {
    display: block;
    width: max-content;
    max-width: 100%;
    overflow-x: auto;
}

/* Long identifiers in control labels must be allowed to break.
 *
 * /ui-options labels a Switch `canvasActions.changeViewBackgroundColor` —
 * 309px of unbreakable text in a 250px box, because a dotted identifier
 * offers no break opportunity. It pushed 15px past a 414px viewport and made
 * the whole page swipe sideways. `anywhere` (not `break-word`) so the break
 * is allowed mid-token, which is the only thing that helps here; it applies
 * only when the text genuinely does not fit, so short labels are untouched.
 */
[id^="m2d-page"] .mantine-Switch-label,
[id^="m2d-page"] .mantine-Switch-description,
[id^="m2d-page"] .mantine-Checkbox-label {
    overflow-wrap: anywhere;
}

/* The generated prop tables (markdown2dash) pin column widths in m2d.css —
   200px + 500px of fixed columns is wider than any phone. Let them collapse
   to content below the point where they stop fitting; the rule above still
   provides the scroll if the content itself is wider. */
@media (max-width: 48em) {
    .m2d-table td:nth-child(1),
    .m2d-table td:nth-child(3),
    .m2d-block-kwargs td:nth-child(1),
    .m2d-block-kwargs td:nth-child(3) {
        width: auto;
    }
}

/* Rank the AppShell sections: the aside under the header, always.
   The Clerk avatar dropdown renders INSIDE the header, so no z-index on the
   menu itself (it ships with 10000 inline) can lift it above anything that
   outranks the header's own stacking context — and Mantine gives the aside
   calc(shell + 1), later in the DOM, so the open menu painted underneath
   the Table of Contents.

   Overriding --app-shell-aside-z-index on the shell root does NOT work:
   Mantine stamps that variable INLINE on the <aside> element itself, and an
   element's own inline declaration beats anything inherited. The inline
   style only carries the variable though — the z-index PROPERTY comes from
   the stylesheet — so overriding the property on the section wins. Static
   selector per the DMC Styles API guidance (never the hashed m_* classes).
   10 keeps the aside above page content and below every piece of chrome. */
aside.mantine-AppShell-aside {
    z-index: 10 !important;
}

:root[data-mantine-color-scheme="dark"] {
    --mantine-color-anchor: #74c0fc !important;
    --mantine-color-dark-light: rgba(63, 63, 70, 0.15);
    --mantine-color-dark-light-hover: rgba(63, 63, 70, 0.2);
    --mantine-color-dark-outline-hover: rgba(113, 113, 122, 0.05);
}

img[alt=logo] { width: 100%; }

/* Theme-aware code blocks */
:root[data-mantine-color-scheme="light"] pre,
:root[data-mantine-color-scheme="light"] code {
    background-color: #f8f9fa;
    color: #1a1b1e;
}

:root[data-mantine-color-scheme="dark"] pre,
:root[data-mantine-color-scheme="dark"] code {
    background-color: #1a1b1e;
    color: #c1c2c5;
}

/* Inline code */
:root[data-mantine-color-scheme="light"] code {
    background-color: #f1f3f5;
    padding: 2px 6px;
    border-radius: 4px;
    font-size: 0.9em;
}

:root[data-mantine-color-scheme="dark"] code {
    background-color: #25262b;
    padding: 2px 6px;
    border-radius: 4px;
    font-size: 0.9em;
}

/* Code blocks */
:root[data-mantine-color-scheme="light"] pre {
    background-color: #f8f9fa;
    border: 1px solid #dee2e6;
    border-radius: 8px;
    padding: 16px;
    overflow-x: auto;
}

:root[data-mantine-color-scheme="dark"] pre {
    background-color: #1a1b1e;
    border: 1px solid #373a40;
    border-radius: 8px;
    padding: 16px;
    overflow-x: auto;
}

/* Code inside pre blocks */
:root[data-mantine-color-scheme="light"] pre code {
    background-color: transparent;
    padding: 0;
    color: #1a1b1e;
}

:root[data-mantine-color-scheme="dark"] pre code {
    background-color: transparent;
    padding: 0;
    color: #c1c2c5;
}

/* Sun icon rotation animations - direction based on scroll */
@keyframes rotate-sun-clockwise {
    from {
        transform: rotate(0deg);
    }
    to {
        transform: rotate(360deg);
    }
}

@keyframes rotate-sun-counter-clockwise {
    from {
        transform: rotate(0deg);
    }
    to {
        transform: rotate(-360deg);
    }
}

/* Clockwise rotation (scroll down) */
#light-theme-icon.rotating-down,
#light-theme-icon.rotating-down svg,
#light-theme-icon.rotating-down iconify-icon {
    animation: rotate-sun-clockwise 1.2s ease-out infinite;
    display: inline-block;
}

/* Counter-clockwise rotation (scroll up) */
#light-theme-icon.rotating-up,
#light-theme-icon.rotating-up svg,
#light-theme-icon.rotating-up iconify-icon {
    animation: rotate-sun-counter-clockwise 1.2s ease-out infinite;
    display: inline-block;
}

/* Smooth transition when stopping */
#light-theme-icon,
#light-theme-icon svg,
#light-theme-icon iconify-icon {
    transition: transform 0.3s ease-out;
    display: inline-block;
}

/* Typewriter cursor animation for Dash Docs title */
@keyframes blink-cursor {
    0%, 49% {
        opacity: 1;
    }
    50%, 100% {
        opacity: 0;
    }
}

/* Add blinking cursor while typing */
#dash-docs-title.typing::after {
    content: '▋';
    animation: blink-cursor 1s step-end infinite;
    margin-left: 2px;
    /* Matches the brand text the caret trails — see components/header.py. */
    color: var(--mantine-color-violet-5);
}

/* AG Grid Dark Mode Support */
/* Override AG Grid theme colors for dark mode */
:root[data-mantine-color-scheme="dark"] .ag-theme-alpine {
    /* Core background colors */
    --ag-background-color: #1a1b1e;
    --ag-foreground-color: #c1c2c5;
    --ag-border-color: #373a40;
    --ag-secondary-border-color: #2c2e33;

    /* Header colors */
    --ag-header-background-color: #25262b;
    --ag-header-foreground-color: #c1c2c5;

    /* Row colors */
    --ag-odd-row-background-color: #1a1b1e;
    --ag-row-hover-color: #25262b;
    --ag-selected-row-background-color: #373a40;

    /* Control panel (filters, pagination) */
    --ag-control-panel-background-color: #25262b;

    /* Input colors */
    --ag-input-border-color: #373a40;
    --ag-input-disabled-border-color: #2c2e33;
    --ag-input-disabled-background-color: #25262b;

    /* Pagination and widgets */
    --ag-disabled-foreground-color: #5c5f66;
    --ag-chip-background-color: #373a40;

    /* Hover and focus states */
    --ag-row-border-color: #2c2e33;
    --ag-cell-horizontal-border: solid #2c2e33;

    /* Filter colors */
    --ag-input-focus-border-color: #5c5f66;

    /* Icons */
    color-scheme: dark;
}

/* Light mode adjustments (ensure proper contrast) */
:root[data-mantine-color-scheme="light"] .ag-theme-alpine {
    --ag-background-color: #ffffff;
    --ag-foreground-color: #1a1b1e;
    --ag-border-color: #dee2e6;
    --ag-header-background-color: #f8f9fa;
    --ag-row-hover-color: #f1f3f5;
}

/* Custom AG Grid Cell Styling - Light Mode */
:root[data-mantine-color-scheme="light"] .ag-theme-alpine .timestamp-cell {
    font-family: monospace;
    font-size: 14px;
}

:root[data-mantine-color-scheme="light"] .ag-theme-alpine .bot-type-cell {
    font-weight: 500;
    padding: 4px 8px;
    border-radius: 4px;
}

:root[data-mantine-color-scheme="light"] .ag-theme-alpine .bot-training {
    background-color: #ffe0e0;
    color: #c92a2a;
}

:root[data-mantine-color-scheme="light"] .ag-theme-alpine .bot-search {
    background-color: #d0ebff;
    color: #1971c2;
}

:root[data-mantine-color-scheme="light"] .ag-theme-alpine .bot-traditional {
    background-color: #d3f9d8;
    color: #2f9e44;
}

:root[data-mantine-color-scheme="light"] .ag-theme-alpine .bot-unknown {
    background-color: #f1f3f5;
    color: #868e96;
    font-weight: 400;
}

:root[data-mantine-color-scheme="light"] .ag-theme-alpine .page-cell {
    font-family: monospace;
    font-size: 12px;
    background-color: #f8f9fa;
    padding: 4px 6px;
    border-radius: 4px;
}

:root[data-mantine-color-scheme="light"] .ag-theme-alpine .user-agent-cell {
    font-size: 12px;
    color: #868e96;
}

/* Custom AG Grid Cell Styling - Dark Mode */
:root[data-mantine-color-scheme="dark"] .ag-theme-alpine .timestamp-cell {
    font-family: monospace;
    font-size: 14px;
}

:root[data-mantine-color-scheme="dark"] .ag-theme-alpine .bot-type-cell {
    font-weight: 500;
    padding: 4px 8px;
    border-radius: 4px;
}

:root[data-mantine-color-scheme="dark"] .ag-theme-alpine .bot-training {
    background-color: #5c1414;
    color: #ffa8a8;
}

:root[data-mantine-color-scheme="dark"] .ag-theme-alpine .bot-search {
    background-color: #1c3d5a;
    color: #74c0fc;
}

:root[data-mantine-color-scheme="dark"] .ag-theme-alpine .bot-traditional {
    background-color: #1b4332;
    color: #8ce99a;
}

:root[data-mantine-color-scheme="dark"] .ag-theme-alpine .bot-unknown {
    background-color: #373a40;
    color: #909296;
    font-weight: 400;
}

:root[data-mantine-color-scheme="dark"] .ag-theme-alpine .page-cell {
    font-family: monospace;
    font-size: 12px;
    background-color: #25262b;
    padding: 4px 6px;
    border-radius: 4px;
}

:root[data-mantine-color-scheme="dark"] .ag-theme-alpine .user-agent-cell {
    font-size: 12px;
    color: #909296;
}

/* ---------------------------------------------------------------------------
 * MOBILE FIT (sync item 16 / template 1.6.39) — ported, not copied.
 *
 * This fork's own table rule above is scoped to the markdown page bodies and
 * was measured here (105px of drag at 414px); it already covers the kwargs
 * prop table by element, so the template's `table.m2d-table,
 * table.m2d-block-kwargs` pair is reduced to the one class the fork's
 * selector cannot reach on its own. Everything below is the template's
 * verbatim: the containers a code block can sit in, which refuse to shrink
 * below the code's intrinsic width and drag the whole document wide.
 *
 * Public Mantine class names only — never the hashed .m_* internals, for the
 * reason written out at length further down this file.
 * ------------------------------------------------------------------------ */

/* `.. kwargs::` prop tables carry m2d-block-kwargs, not m2d-table — the one
   table class a page-scoped element selector still wants named explicitly;
   measured on the template's /examples/directives at 391px: a 457px table
   in a 488px document. */
table.m2d-block-kwargs,
/* (1.6.42) `.. props::`-style directive tables render nested inside a
   wrapper rather than carrying a table class of their own, so the rule is
   reached through the block. Same recipe, third selector. */
.m2d-block-props table {
    display: block;
    width: max-content;
    max-width: 100%;
    overflow-x: auto;
}

/* Code blocks scroll inside their own box, wherever they sit (1.6.39;
   owner-observed on /backend-comparison at phone width). CodeHighlight's
   <pre> already scrolls, but a flex parent with the default min-width:auto
   — Mantine's List item wrapper, a Blockquote, a Stack — refuses to shrink
   below the code's intrinsic width and drags the whole document wide
   (measured: a 959px document in a 200px viewport, widest element the
   List itemWrapper around the "Replace @server.before_request" block).
   Public Mantine class names only — never the hashed .m_* internals. */
.mantine-List-itemWrapper,
.mantine-List-itemLabel,
.mantine-List-item,
.mantine-Blockquote-root,
.mantine-Timeline-itemBody,
.mantine-CodeHighlight-root,
.mantine-CodeHighlightTabs-root {
    min-width: 0;
    max-width: 100%;
}
/* The wrapper is inline-flex and the label a block child: without
   min-width:0 on the LABEL too, it grows to the code's width (measured
   887px inside a 287px wrapper on /backend-comparison at 391px). */
.mantine-List-itemWrapper {
    width: 100%;
}
.mantine-List-itemLabel {
    flex: 1 1 auto;
}
/* Timeline bullets (/changelog): a Text in a no-wrap Group grows to its
   longest unbreakable token — a 60-character test name in a code span —
   and leaves its card (a 549px document at 391px). Same rule as the
   component sets inline; here so the stylesheet alone holds the line. */
.mantine-Timeline-root .mantine-Text-root,
.mantine-Timeline-root .mantine-Code-root {
    min-width: 0;
    overflow-wrap: anywhere;
}
/* Inline code in prose: a long unbreakable token (`app.server.before_request`
   chains, dotted module paths) is the last thing that can push a page past
   the viewport once blocks and tables scroll in their own boxes — measured:
   a 353px codespan, a 425px document at 391px on /backend-comparison.
   Block code (CodeHighlight) keeps pre formatting; this is inline only. */
code.m2d-codespan,
.mantine-Code-root:not(.mantine-CodeHighlight-code) {
    overflow-wrap: anywhere;
    white-space: normal;
}
.mantine-CodeHighlight-root pre,
.mantine-CodeHighlightTabs-root pre,
.mantine-AppShell-main pre {
    overflow-x: auto;
    max-width: 100%;
}

/* Skip link (1.6.41, adopted from muischeduler): the first tab stop, off-
   screen until keyboard focus, then pinned top-left above the header. */
.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 9999;
    background: var(--mantine-primary-color-filled);
    color: var(--mantine-color-white);
    padding: 8px 14px;
    border-radius: 0 0 8px 0;
    font-weight: 600;
    text-decoration: none;
}
.skip-link:focus {
    left: 0;
}
