* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

:root {
  /* Color Palette - Liquid Glass Apple Design */
  --bg-primary: linear-gradient(180deg, #F5F5F7 0%, #FAFAFC 100%);
  --bg-secondary: rgba(255, 255, 255, 0.7);
  --bg-card: rgba(255, 255, 255, 0.6);
  --border-color: rgba(0, 0, 0, 0.08);
  --border-color-hover: rgba(0, 0, 0, 0.15);
  --text-primary: #1D1D1F;
  --text-secondary: #48484A;
  --accent-gray: #8E8E93;
  --accent-gray-light: #AEAEB2;
  --success-green: #34C759;
  --danger-red: #FF3B30;
  
  /* Typography */
  --font-ui: 'Outfit', sans-serif;
  --font-mono: 'JetBrains Mono', monospace;
  
  /* Transitions */
  --transition-speed: 0.15s;
  
  font-synthesis: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  margin: 0;
  padding: 0;
  width: 100vw;
  /* See .chart-container: 100vh is iOS Safari's tallest viewport, so it runs the layout
     underneath the browser's own bottom toolbar. dvh tracks what is actually visible. */
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  /* War #131722 - ein blaugrauer TradingView-Rest (Farbton 224 Grad) unter der
     gesamten App, der beim Laden und beim Overscroll durchblitzte. Als Hex und
     nicht als Token, weil .dark-mode auf .chart-container sitzt und den body
     nie erreicht. */
  background: #000000;
  color: #F7F7F7;
  font-family: var(--font-ui);
}

::selection {
  background: rgba(142, 142, 147, 0.2);
  color: #1D1D1F;
}

/* Auf schwarzem Grund ergab die helle Auswahl Kontrast 1,01:1 - markierter Text
   verschwand beim Doppelklick auf einen Preis oder Symbolnamen vollstaendig. */
.dark-mode ::selection {
  background: rgba(255, 255, 255, 0.22);
  color: #F7F7F7;
}

#root {
  width: 100%;
  height: 100%;
}

button {
  font-family: var(--font-ui);
  cursor: pointer;
  transition: all var(--transition-speed) ease;
  border: none;
  outline: none;
}

button:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}

input, select {
  font-family: var(--font-ui);
  transition: all var(--transition-speed) ease;
}

/* Die beiden !important hier haben 49 der 54 Fokus-Regeln der Komponenten tot
   gemacht: kein Eingabefeld konnte seinen eigenen Ring zeigen, jeder Klick
   erzeugte stattdessen denselben breiten hellgrauen Halo aus dem Glas-Stand.
   Ohne !important greifen die spezifischeren Komponentenregeln wieder, und was
   keine eigene hat, faellt auf diesen neutralen Standard zurueck. */
input:focus, select:focus {
  outline: none;
  border-color: var(--bk-border-strong);
  box-shadow: 0 0 0 3px var(--bk-divider);
}

/* Custom Scrollbar */
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

::-webkit-scrollbar-track {
  background: rgba(0, 0, 0, 0.03);
}

::-webkit-scrollbar-thumb {
  background: rgba(0, 0, 0, 0.2);
  border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
  background: rgba(0, 0, 0, 0.3);
}


/* ══════════════════════════════════════════════════════════════════════
   SCHWARZ — neutrales Flächensystem

   Eine durchgehende schwarze Leinwand. Benachbarte Flächen unterscheiden
   sich nur um wenige Helligkeitsstufen; Hierarchie entsteht über Schrift
   und Abstand, nicht über Kästen.

   Alle Neutraltöne sind bewusst unbunt - kein Blau-, Violett- oder
   Grünstich. Farbe trägt hier ausschließlich Bedeutung: Gewinn, Verlust,
   Warnung. Sonst nichts.

   Rahmen werden weiterhin als 1px-Ring über inset box-shadow gezeichnet,
   wo vorher keiner war. Ein echter border addierte Breite und verschöbe
   Bedienelemente; der Ring sieht gleich aus und kostet keine Geometrie.
   ══════════════════════════════════════════════════════════════════════ */
:root{
  /* helle Ebene: neutral, ohne Farbstich - dieselbe Disziplin wie dunkel */
  --bk-app: #FFFFFF;
  --bk-chart: #FFFFFF;
  --bk-shell: #FAFAFA;
  --bk-panel: #FFFFFF;
  --bk-elevated: #FFFFFF;
  /* Karte auf einer Flaeche, und der Hover dazu.

     Das Journal legte seine Karten vorher auf --bk-shell - die Ebene UNTER dem Panel, auf
     dem sie liegen. Im Dunkelmodus wurden sie dadurch dunkler als ihr eigener Grund und
     lasen sich als Loecher in der Flaeche statt als Karten darauf. --bk-elevated schied
     als Ersatz aus: das ist im Hellmodus reines Weiss und damit dieselbe Farbe wie das
     Panel, derselbe Fall, an dem schon .profile-picture haengengeblieben ist.

     Der Abstand zum Grund ist mit Absicht groesser als eine einzelne Stufe: die Paneele,
     auf denen diese Karten liegen, tragen inzwischen selbst --bk-elevated (dunkel
     #101010), die Karte muss also an diesem Wert vorbei und nicht am dunkleren
     --bk-panel, gegen den sie urspruenglich gerechnet war.

     Drei Ebenen, weil das Journal drei hat: --bk-card liegt auf dem Panel (die Kacheln
     der Kennzahlen, die vier Abschnitte), --bk-card-2 liegt auf einer solchen Karte (die
     Zeilen und Zellen INNERHALB der Abschnitte). Ohne die zweite Ebene faellt beides auf
     denselben Wert und die Zeilen verschwinden in ihrem eigenen Abschnitt.

     Die Hover-Farbe ist deckend, und das ist der Punkt: ein durchscheinender Wert wie
     --bk-divider mischt sich mit der Flaeche UNTER der Karte, nicht mit der Karte selbst,
     und ergab auf einer #202020-Karte zwei Helligkeitsstufen Unterschied - einen Hover,
     den niemand sieht. */
  /* Die Scheibe hinter einem Firmenzeichen. Bewusst in BEIDEN Themes hell und
     hier derselbe Wert: ein Firmenzeichen ist in seinen eigenen Farben gezeichnet
     und fuer hellen Grund gemacht - ASMLs Blau und Metas Blau stehen auf Schwarz
     kaum noch, und ein Zeichen, das ausschliesslich aus dunkler Tinte besteht,
     verschwaende ganz. Die Scheibe gibt dem Zeichen den Grund, fuer den es
     entworfen wurde, statt das Zeichen an das Theme anzupassen - was hiesse, eine
     geschuetzte Marke umzufaerben. Es ist auch, was TradingView tut; dort sitzt
     die Scheibe in der SVG-Datei selbst, weshalb deren Kachel keinen eigenen
     Hintergrund braucht. Krypto- und Flaggensymbole bekommen sie nicht: die sind
     bereits als randlose Scheibe gezeichnet. */
  --bk-mark-disc: #F2F2F2;
  --bk-card: #F4F4F4;
  --bk-card-2: #EAEAEA;
  --bk-card-2-hover: #E0E0E0;
  --bk-input: #F4F4F4;
  --bk-hover: rgba(0,0,0,.05);
  --bk-active: rgba(0,0,0,.09);
  --bk-border: #E4E4E4;
  --bk-border-strong: #CFCFCF;
  --bk-divider: rgba(0,0,0,.075);
  --bk-text: #0B0B0B;
  --bk-text-2: #5E5E5E;
  --bk-text-3: #8A8A8A;
  --bk-text-off: #B4B4B4;
  --bk-on-primary: #FFFFFF;
  --bk-primary: #0B0B0B;
  --bk-lift: 0 8px 24px rgba(0,0,0,.10);

  --bk-r-panel: 16px;
  --bk-r-control: 12px;
  --bk-r-icon: 10px;

  --bk-pos: #1E9E5F;
  --bk-neg: #D93A44;
  --bk-warn: #B8860B;

  /* Chartify's own accent, taken from public/logo.svg, as distinct from the system blue
     that ordinary controls use. The features that carry the brand - the assistant, the
     chart scanner - draw from here, so recolouring the logo moves all of them at once.
     Not repeated in .dark-mode below: the brand does not change with the theme.
     --brand is the logo gradient's midpoint, --brand-hover its dark stop, and the rgb
     triple exists because a hex cannot be given an alpha inside rgba(). */
  --brand: #4C29E9;
  --brand-hover: #3D20DC;
  --brand-rgb: 76, 41, 233;
}

.dark-mode{
  --bk-app: #000000;
  --bk-chart: #000000;
  --bk-shell: #050505;
  --bk-panel: #080808;
  /* Die Farbe der Leisten: Navbar, Werkzeugschiene, Strip. Panels und Menues stehen jetzt
     auf derselben Flaeche wie der Rahmen um sie herum, statt eine Stufe darunter.

     Warum hier und nicht an fuenfzehn Selektoren: die Gruppen "schwebende Paneele" und
     "Menues und Popover" am Dateiende von CandlestickChart.css lesen beide diesen Token,
     ebenso .chart-scanner-modal.dark-mode. Neun der zehn genannten Oberflaechen haengen
     also an dieser einen Zeile - Markt, Timeframe, Indikatoren, Replay, AI Painter, Chart
     Scan, Journal, Rechtsklickmenue und Profil. Nur .tool-flyout hatte seine Farbe selbst
     hartcodiert und wird drueben nachgezogen.

     --bk-shell bleibt bei #050505: der traegt Journal- und Panelflaechen, die tiefer
     stehen sollen. Die beiden sind nicht dasselbe, auch wenn sie sich hier nahekommen. */
  --bk-elevated: #151619;
  /* Nicht invertiert - siehe die Begruendung oben. */
  --bk-mark-disc: #F2F2F2;
  /* Dieselbe Flaeche, auf der die Starter im Assistenten stehen. Das Journal legt
     seine Kacheln und Abschnitte per Inline-Style auf diesen Token, also liegen sie
     jetzt auf genau der Karte, die "Check the risk" traegt.

     --bk-card-2 bleibt bei #2A2A2A und wird bewusst NICHT mitgezogen: das sind die
     Zeilen INNERHALB der Abschnitte, und die haben keinen Rahmen - ihre Flaeche ist
     das einzige, was sie definiert. Auf denselben Wert gesetzt wie ihr Abschnitt
     waeren die Trade-Zeilen unsichtbar. */
  --bk-card: #202124;
  --bk-card-2: #2A2A2A;
  --bk-card-2-hover: #343434;
  --bk-input: #141414;
  --bk-hover: #191919;
  --bk-active: #202020;
  --bk-border: #242424;
  --bk-border-strong: #303030;
  --bk-divider: rgba(255,255,255,.075);
  --bk-text: #F7F7F7;
  --bk-text-2: #949494;
  --bk-text-3: #666666;
  --bk-text-off: #464646;
  --bk-on-primary: #000000;
  --bk-primary: #FFFFFF;
  /* nur so viel Schatten, dass eine schwebende Fläche sich vom Grund löst */
  --bk-lift: 0 10px 28px rgba(0,0,0,.55);

  /* Auf die Kerzenfarben des Charts gesetzt (CandlestickChart.jsx), damit eine
     Gewinnzahl im Panel exakt dasselbe Gruen zeigt wie die Kerze daneben.
     Vorher liefen fuenf Gruentoene fuer dieselbe Rolle nebeneinander. */
  --bk-pos: #34C759;
  --bk-neg: #FF3B30;
  --bk-warn: #F5B942;
}

@media (prefers-contrast: more){
  .dark-mode{ --bk-border: #3A3A3A; --bk-divider: rgba(255,255,255,.18); --bk-text-2: #B4B4B4 }
  :root{ --bk-border: #BDBDBD; --bk-divider: rgba(0,0,0,.20); --bk-text-2: #3A3A3A }
}
/* Mobile-First Responsive Styles */

/* Withholds pinch-zoom and double-tap-zoom from the browser: listing only the pan values
   is what blocks them. This is the lock that actually holds on iOS Safari, which has
   ignored user-scalable=no since iOS 10. (The old comment here claimed it still allowed
   pinch-zoom - it never did, and .chart-container was separately adding pinch-zoom back
   with !important, which is how the whole app stayed zoomable.) */
* {
  touch-action: pan-x pan-y;
}

/* Mobile viewport adjustments */
@media (max-width: 768px), (max-height: 500px) and (orientation: landscape) {
  body {
    overflow: hidden;
    position: fixed;
    width: 100%;
    height: 100%;
  }

  /* dvh, and deliberately not position: fixed with inset: 0. That looks like the more
     robust way to fill the screen, and on iOS it is the opposite: Safari resolves fixed
     positioning against the LARGE viewport - the height the page would have with the
     toolbars hidden - so inset: 0 overshoots whatever is actually on screen and posts the
     bottom of the app underneath the toolbar. dvh is the unit that tracks the visible
     height as that chrome comes and goes, which is the whole reason it exists.
     vh stays ahead of it for browsers without dvh. */
  .App {
    width: 100vw;
    height: 100vh;
    height: 100dvh;
    /* --app-height is visualViewport.height, written from main.jsx - the measured visible
       area, which is the only figure that has been right in a tab and in a standalone
       window at the same time. The units above remain the fallback if the script has not
       run yet. */
    height: var(--app-height, 100dvh);
    /* Side insets live here rather than on body: they keep the app's background running to
       the edges while holding its contents out of the notch, which matters in landscape. */
    padding-left: env(safe-area-inset-left);
    padding-right: env(safe-area-inset-right);
    box-sizing: border-box;
    overflow: hidden;
  }

  /* Optimize chart container for mobile */
  .chart-container {
    /* pinch-zoom removed: it handed the pinch to the browser, which zoomed the whole page.
       Withholding it leaves the gesture to the chart's own touch handlers, so pinching
       scales the candles - what the gesture should have done here all along - instead of
       magnifying the interface. */
    touch-action: pan-x pan-y !important;
    -webkit-overflow-scrolling: touch;
  }

  /* Make toolbars scrollable on small screens */
  .toolbar {
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none; /* Firefox */
  }

  .toolbar::-webkit-scrollbar {
    display: none; /* Chrome, Safari */
  }

  /* Optimize buttons for touch */
  button, .btn, .tool-btn {
    min-height: 44px; /* iOS recommended touch target size */
    min-width: 44px;
    padding: 8px 12px;
  }

  /* Make modal dialogs mobile-friendly */
  .modal-content, .alert-modal, .backtest-modal {
    max-width: 95vw;
    max-height: 90vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* Symbol selector - make scrollable */
  .symbol-selector {
    max-height: 60vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* Settings panel - adjust for mobile */
  .settings-panel {
    max-height: 80vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* Input fields - easier to tap */
  input[type="text"],
  input[type="number"],
  input[type="email"],
  input[type="password"],
  select,
  textarea {
    font-size: 16px; /* Prevent zoom on iOS */
    min-height: 44px;
  }

  /* Optimize dropdown menus */
  select {
    -webkit-appearance: none;
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23999' d='M6 9L1 4h10z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
    padding-right: 30px;
  }

  /* Hide desktop-only elements on mobile */
  .desktop-only {
    display: none !important;
  }

  /* Optimize color picker for mobile */
  .custom-color-adder {
    max-width: 90vw;
  }

  /* Make chart legend responsive */
  .legend {
    font-size: 12px;
    flex-wrap: wrap;
  }

  /* Optimize navbar for mobile: scroll horizontally instead of wrapping/overlapping */
  .navbar {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    padding: 0 8px;
  }

  .navbar::-webkit-scrollbar {
    display: none;
  }

  /* Stack elements vertically on small screens */
  .flex-row-mobile-column {
    flex-direction: column !important;
  }
}

/* Tablet adjustments */
@media (min-width: 769px) and (max-width: 1024px) {
  .chart-container {
    touch-action: pan-x pan-y pinch-zoom !important;
  }

  button, .btn {
    min-height: 40px;
    min-width: 40px;
  }
}

/* Landscape mobile */
@media (max-width: 896px) and (orientation: landscape) {
  .modal-content {
    max-height: 85vh;
    overflow-y: auto;
  }

  .toolbar {
    padding: 4px;
  }

  button {
    min-height: 36px;
    min-width: 36px;
    padding: 6px 10px;
  }
}

/* Notched devices are handled where the elements that meet the system UI are defined, not
   here on body: the navbar pads by the top inset, the bottom strip by the bottom inset, and
   .App by the side insets. Padding body instead held the whole app off the screen edges,
   which installed to the home screen read as bands of page background top and bottom.
   .App is also position: fixed on a phone, so it would not inherit body's padding anyway. */

/* PWA display mode detection */
@media (display-mode: standalone) {
  /* When installed as PWA */
  .install-prompt {
    display: none !important;
  }
}

/* Touch feedback */
/* Stand ausserhalb jeder Media-Query und traf damit JEDEN Knopf auf JEDEM Geraet:
   auf dem Desktop verblasste beim Klicken alles auf 70 Prozent. Gehoert nur auf
   Touch, wo es kein Hover gibt. */
@media (hover: none) {
  button:active,
.btn:active,
.tool-btn:active {
  opacity: 0.7;
  ;
}
}

/* Prevent text selection on UI elements during touch */
.toolbar,
.navbar,
.control-panel,
.sidebar {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* Allow text selection in inputs and content areas */
input,
textarea,
.content-area {
  -webkit-user-select: text;
  user-select: text;
}
.App {
  width: 100vw;
  height: 100vh;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background: transparent;
  display: flex;
  flex-direction: column;
}

/* Price Alert Notification Animation */
@keyframes slideDown {
  from {
    transform: translate(-50%, -100%);
    opacity: 0;
  }
  to {
    transform: translate(-50%, 0);
    opacity: 1;
  }
}
.alert-modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 600px;
  max-height: 80vh;
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(60px) saturate(180%);
  -webkit-backdrop-filter: blur(60px) saturate(180%);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 20px;
  z-index: 1501;
  display: flex;
  flex-direction: column;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15), 0 0 1px rgba(0, 0, 0, 0.05);
  overflow: hidden;
}

/* The shared .modal-content rule carries no horizontal padding, because the symbol
   modal's own rows inset themselves. This modal's sections do not, so their content sat
   flush against the edges while the header above was inset 24px. Scoped to .alert-modal
   rather than fixing the shared rule, which every other modal already lays out around. */
.alert-modal .modal-content {
  padding: 8px 24px 24px;
}

.alert-error {
  padding: 12px 16px;
  margin-bottom: 20px;
  background-color: rgba(255, 59, 48, 0.1);
  border: 1px solid rgba(255, 59, 48, 0.3);
  border-radius: 10px;
  color: #FF3B30;
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
}

.alert-section {
  margin-bottom: 28px;
}

.alert-section:last-child {
  margin-bottom: 0;
}

.alert-section h4 {
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 11px;
  color: var(--bk-text-3);
  margin: 0 0 16px 0;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.alert-info-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
  margin-bottom: 20px;
}

.alert-info-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 14px;
  background: rgba(255, 255, 255, 0.6);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 10px;
}

.alert-label {
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  color: var(--bk-text-3);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.alert-value {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  color: #1D1D1F;
}

.alert-toggle-btn {
  width: 100%;
  padding: 14px;
  border: none;
  border-radius: 12px;
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 14px;
  cursor: pointer;
  transition: all 0.15s ease;
}

.alert-toggle-btn.enable {
  background: linear-gradient(135deg, #34C759, #30B554);
  color: white;
  box-shadow: 0 4px 15px rgba(52, 199, 89, 0.3);
}

.alert-toggle-btn.enable:hover {
  ;
  box-shadow: 0 6px 25px rgba(52, 199, 89, 0.4);
}

.alert-toggle-btn.disable {
  background: linear-gradient(135deg, #FF3B30, #E82E24);
  color: white;
  box-shadow: 0 4px 15px rgba(255, 59, 48, 0.3);
}

.alert-toggle-btn.disable:hover {
  ;
  box-shadow: 0 6px 25px rgba(255, 59, 48, 0.4);
}

.alert-toggle-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Shown when an alert exists for this symbol/timeframe but was frozen on different
   settings than the chart currently has. Amber rather than red: nothing is broken, the
   alert is doing exactly what it was told to. */
.alert-stale-notice {
  padding: 12px 14px;
  margin-bottom: 12px;
  border-radius: 12px;
  background: rgba(255, 149, 0, 0.10);
  border: 1px solid rgba(255, 149, 0, 0.35);
  font-family: var(--font-ui);
  font-size: 13px;
  line-height: 1.45;
  color: #8A5200;
}

.alert-stale-notice .alert-toggle-btn {
  margin-top: 10px;
  padding: 10px;
  font-size: 13px;
}

.dark-mode .alert-stale-notice {
  background: rgba(255, 159, 10, 0.12);
  border: 1px solid rgba(255, 159, 10, 0.35);
  color: #FFB84D;
}

.alert-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.alert-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 16px;
  background: rgba(255, 255, 255, 0.6);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 12px;
  transition: all 0.15s ease;
}

.alert-item:hover {
  border-color: rgba(0, 0, 0, 0.12);
  background: rgba(255, 255, 255, 0.8);
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
  ;
}

.alert-item-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.alert-item-main {
  display: flex;
  align-items: center;
  gap: 12px;
}

.alert-item-symbol {
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 700;
  color: #1D1D1F;
}

.alert-item-timeframe {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  padding: 2px 8px;
  background: rgba(142, 142, 147, 0.1);
  border: 1px solid rgba(142, 142, 147, 0.2);
  border-radius: 6px;
  color: #8E8E93;
}

.alert-item-details {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  color: var(--text-secondary);
  letter-spacing: 0.3px;
}

.alert-delete-btn {
  width: 32px;
  height: 32px;
  background-color: rgba(255, 59, 48, 0.1);
  border: 1px solid rgba(255, 59, 48, 0.2);
  border-radius: 8px;
  color: #FF3B30;
  font-size: 20px;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.2s ease;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

.alert-delete-btn:hover {
  background-color: #FF3B30;
  border-color: #FF3B30;
  color: white;
  box-shadow: 0 4px 20px rgba(255, 59, 48, 0.4);
  ;
}

/* Dark Mode Styles */
.alert-modal.dark-mode {
  background: rgba(26, 26, 26, 0.95);
  border: 1px solid #242424;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}

.dark-mode .modal-header {
  border-bottom: 1px solid #242424;
}

.dark-mode .alert-error {
  background-color: rgba(255, 59, 48, 0.15);
  border: 1px solid rgba(255, 59, 48, 0.4);
  color: #FF6B6B;
}

.dark-mode .alert-section h4 {
  color: var(--bk-text-2);
}

.dark-mode .alert-info-item {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid #242424;
}

.dark-mode .alert-label {
  color: var(--bk-text-2);
}

.dark-mode .alert-value {
  color: #F7F7F7;
}

.dark-mode .alert-item {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid #242424;
}

.dark-mode .alert-item:hover {
  border-color: #303030;
  background: rgba(255, 255, 255, 0.05);
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
}

.dark-mode .alert-item-symbol {
  color: #F7F7F7;
}

.dark-mode .alert-item-timeframe {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid #242424;
  color: var(--bk-text-2);
}

.dark-mode .alert-item-details {
  color: var(--bk-text-2);
}

.dark-mode .alert-delete-btn {
  background-color: rgba(255, 59, 48, 0.15);
  border: 1px solid rgba(255, 59, 48, 0.3);
  color: #FF6B6B;
}

.dark-mode .alert-delete-btn:hover {
  background-color: #FF3B30;
  border-color: #FF3B30;
  color: white;
}
/* Alert Trigger Status */
.alert-recent-badge {
  font-size: 10px;
  font-weight: 600;
  padding: 3px 8px;
  background: linear-gradient(135deg, #34C759, #30B554);
  color: white;
  border-radius: 6px;
  animation: pulse 2s ease-in-out infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.7; }
}

.alert-item-trigger {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
}

.alert-trigger-label {
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 600;
  color: #8E8E93;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.alert-trigger-time {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
}

.alert-trigger-time.triggered {
  color: #34C759;
}

.alert-trigger-time.never {
  color: #8E8E93;
  font-style: italic;
}

/* Webhooks - an additional destination alerts are copied to */
.webhook-hint {
  font-family: var(--font-ui);
  font-size: 12px;
  line-height: 1.5;
  color: var(--bk-text-3);
  margin-bottom: 14px;
}

/* An alert with its webhooks: the alert's own row on top, its webhooks underneath. */
.alert-item.alert-item-with-webhooks {
  flex-direction: column;
  align-items: stretch;
  gap: 12px;
}

.alert-item-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}

.alert-webhooks {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: 12px;
  border-top: 1px solid rgba(0, 0, 0, 0.06);
}

/* Wraps its buttons under the name on a narrow phone rather than squeezing the name. */
.alert-webhook {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  background: rgba(0, 0, 0, 0.025);
  border: 1px solid rgba(0, 0, 0, 0.06);
  border-radius: 10px;
}

/* A real basis, not the 0 that flex: 1 gives it: with 0 the name squeezed down to one
   letter per line on a narrow phone before the buttons ever wrapped under it. */
.alert-webhook .alert-item-info {
  flex: 1 1 150px;
  min-width: 0;
}

.alert-webhook-name {
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 600;
  color: #1D1D1F;
  overflow-wrap: anywhere;
}

.alert-webhook .alert-delete-btn {
  width: 28px;
  height: 28px;
  font-size: 18px;
}

.alert-webhooks .alert-error {
  margin-bottom: 0;
}

.alert-webhooks .webhook-add-btn {
  padding: 9px;
  font-size: 12px;
  border-radius: 10px;
}

.alert-webhook-teaser {
  margin: 10px 0 0;
}

.webhook-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}

.webhook-action-btn {
  padding: 7px 12px;
  background: rgba(255, 255, 255, 0.7);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 8px;
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  color: #1D1D1F;
  cursor: pointer;
  transition: all 0.15s ease;
  white-space: nowrap;
}

.webhook-action-btn:hover:not(:disabled) {
  background: rgba(0, 0, 0, 0.05);
  border-color: rgba(0, 0, 0, 0.18);
  ;
}

.webhook-action-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.webhook-action-btn.primary {
  background: linear-gradient(135deg, #34C759, #30B554);
  border-color: transparent;
  color: white;
  box-shadow: 0 4px 15px rgba(52, 199, 89, 0.25);
}

.webhook-badge {
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 6px;
}

.webhook-badge.off {
  background: rgba(142, 142, 147, 0.15);
  border: 1px solid rgba(142, 142, 147, 0.3);
  color: #8E8E93;
}

.webhook-badge.signed {
  background: rgba(52, 152, 219, 0.12);
  border: 1px solid rgba(52, 152, 219, 0.3);
  color: #2980B9;
}

.webhook-form {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  background: rgba(255, 255, 255, 0.6);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 12px;
}

.webhook-form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.webhook-input {
  width: 100%;
  padding: 10px 12px;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid rgba(0, 0, 0, 0.12);
  border-radius: 10px;
  font-family: var(--font-ui);
  font-size: 13px;
  color: #1D1D1F;
  outline: none;
  box-sizing: border-box;
  transition: border-color 0.15s ease;
}

.webhook-input:focus {
  border-color: #34C759;
}

.webhook-input::placeholder {
  color: #A1A1A6;
}

.webhook-select {
  cursor: pointer;
}

/* The options inherit the select's text colour, but the popup is painted on the
   platform's own background, so they went white-on-white in dark mode. Both
   halves are pinned here. */
.webhook-select option {
  background: #FFFFFF;
  color: #1D1D1F;
}

/* PineConnector's extra fields, grouped so it reads as one block that belongs to the
   format above it rather than four more inputs on the general form. */
.webhook-pc-fields {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-top: 10px;
  border-top: 1px solid rgba(0, 0, 0, 0.08);
}

.webhook-pc-note {
  font-family: var(--font-ui);
  font-size: 12px;
  line-height: 1.5;
  color: var(--bk-text-3);
  margin: 0;
}

.webhook-form-actions {
  display: flex;
  gap: 8px;
}

.webhook-add-btn {
  width: 100%;
  padding: 12px;
  background: rgba(255, 255, 255, 0.6);
  border: 1px dashed rgba(0, 0, 0, 0.2);
  border-radius: 12px;
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 600;
  color: var(--bk-text-3);
  cursor: pointer;
  transition: all 0.15s ease;
}

.webhook-add-btn:hover {
  border-color: #34C759;
  color: #34C759;
  background: rgba(52, 199, 89, 0.05);
}

/* Webhooks - dark mode */
.dark-mode .webhook-hint {
  color: var(--bk-text-2);
}

.dark-mode .alert-webhooks {
  border-top-color: #242424;
}

.dark-mode .alert-webhook {
  background: rgba(255, 255, 255, 0.03);
  border-color: #242424;
}

.dark-mode .alert-webhook-name {
  color: #F7F7F7;
}

.dark-mode .webhook-action-btn {
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid #242424;
  color: var(--bk-text-2);
}

.dark-mode .webhook-action-btn:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.12);
  border-color: #303030;
}

.dark-mode .webhook-action-btn.primary {
  background: linear-gradient(135deg, #34C759, #30B554);
  border-color: transparent;
  color: white;
}

.dark-mode .webhook-badge.signed {
  background: rgba(52, 152, 219, 0.18);
  border: 1px solid rgba(52, 152, 219, 0.4);
  color: #5DADE2;
}

.dark-mode .webhook-form {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid #242424;
}

.dark-mode .webhook-input {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid #242424;
  color: #F7F7F7;
}

.dark-mode .webhook-select option {
  background: #101010;
  color: #F7F7F7;
}

.dark-mode .webhook-input::placeholder {
  color: var(--bk-text-3);
}

.dark-mode .webhook-input:focus {
  border-color: #30D158;
}

.dark-mode .webhook-pc-fields {
  border-top-color: var(--bk-border);
}

.dark-mode .webhook-pc-note {
  color: var(--bk-text-2);
}

.dark-mode .webhook-add-btn {
  background: rgba(255, 255, 255, 0.03);
  border: 1px dashed #303030;
  color: var(--bk-text-2);
}

.dark-mode .webhook-add-btn:hover {
  border-color: #30D158;
  color: #30D158;
  background: rgba(48, 209, 88, 0.08);
}

/* Dark Mode for Trigger Status */
.dark-mode .alert-trigger-label {
  color: var(--bk-text-2);
}

.dark-mode .alert-trigger-time.triggered {
  color: #30D158;
}

.dark-mode .alert-trigger-time.never {
  color: var(--bk-text-3);
}

/* ══════════════════════════════════════════════════════════════════════
   A webhook's own message
   ══════════════════════════════════════════════════════════════════════
   The row in the add form that says what the webhook will send, and the
   Edit message view behind it. The view is laid out after TradingView's -
   back arrow, Alert name, Message, Add placeholder, reset, help, then
   Cancel / Apply - and drawn in the platform's tokens, so it follows the
   theme like the panels around it. */

.webhook-badge.message {
  background: rgba(175, 82, 222, 0.12);
  border: 1px solid rgba(175, 82, 222, 0.3);
  color: #9B51E0;
}

.webhook-message-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--bk-input);
  box-shadow: inset 0 0 0 1px var(--bk-border);
}

.webhook-message-summary {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.webhook-message-title {
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  color: var(--bk-text-2);
}

.webhook-message-preview {
  font-family: var(--font-ui);
  font-size: 12.5px;
  color: var(--bk-text-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.webhook-message-preview.custom {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--bk-text);
}

.webhook-pc-note code {
  font-family: var(--font-mono);
  font-size: 11.5px;
  padding: 1px 4px;
  border-radius: 4px;
  background: var(--bk-input);
}

.webhook-message-editor {
  display: flex;
  flex-direction: column;
  min-height: 0;
  max-height: 80vh;
  font-family: var(--font-ui);
  color: var(--bk-text);
}

.wme-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 14px 14px 12px;
  border-bottom: 1px solid var(--bk-border);
}

.wme-title {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.wme-title h3 {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: var(--bk-text);
}

.wme-subtitle {
  font-size: 11.5px;
  color: var(--bk-text-3);
}

.wme-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: none;
  border-radius: 10px;
  background: transparent;
  color: var(--bk-text-2);
  cursor: pointer;
}

.wme-icon-btn:hover {
  background: var(--bk-hover);
  color: var(--bk-text);
}

.wme-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  padding: 16px 20px 18px;
}

.wme-label {
  display: block;
  font-size: 13px;
  color: var(--bk-text-2);
  margin-bottom: 7px;
}

/* Entry / Take profit / Stop loss: which of the webhook's messages the box below edits. */
.wme-tabs {
  display: flex;
  gap: 4px;
  margin-top: 16px;
  padding: 3px;
  border-radius: 11px;
  background: var(--bk-input);
  box-shadow: inset 0 0 0 1px var(--bk-border);
}

.wme-tab {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 7px 8px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--bk-text-2);
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
}

.wme-tab:hover {
  color: var(--bk-text);
}

.wme-tab.active {
  background: var(--bk-hover);
  color: var(--bk-text);
  font-weight: 600;
}

.wme-tab-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--brand, #4C29E9);
}

.wme-label-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 16px;
  margin-bottom: 7px;
}

.wme-label-row .wme-label {
  margin-bottom: 0;
}

.wme-warning {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #FF9500;
  color: #FFFFFF;
  font-size: 11px;
  font-weight: 800;
  cursor: help;
}

.wme-warning-text {
  margin-top: 6px;
  font-size: 12px;
  color: #D97706;
}

.wme-input {
  width: 100%;
  box-sizing: border-box;
  padding: 10px 12px;
  border: none;
  border-radius: 10px;
  background: var(--bk-input);
  box-shadow: inset 0 0 0 1px var(--bk-border);
  color: var(--bk-text);
  font-family: var(--font-ui);
  font-size: 14px;
  outline: none;
}

.wme-input:focus {
  box-shadow: inset 0 0 0 1px var(--bk-text-3);
}

.wme-input::placeholder {
  color: var(--bk-text-3);
}

.wme-textarea {
  min-height: 220px;
  resize: vertical;
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.5;
}

/* Anchors the placeholder menu, which opens upwards over the text box the way
   TradingView's does - there is never room below, the footer is there. */
.wme-tools {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
}

.wme-btn {
  padding: 8px 14px;
  border: none;
  border-radius: 10px;
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--bk-border-strong, var(--bk-border));
  color: var(--bk-text);
  font-family: var(--font-ui);
  font-size: 13.5px;
  font-weight: 500;
  cursor: pointer;
}

.wme-btn:hover:not(:disabled),
.wme-btn.active {
  background: var(--bk-hover);
}

.wme-btn:disabled {
  opacity: 0.6;
  cursor: progress;
}

.wme-square {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
}

.wme-help {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--bk-text-3);
  color: var(--bk-elevated);
  font-size: 12px;
  font-weight: 700;
  cursor: help;
  outline: none;
}

.wme-menu {
  position: absolute;
  left: 0;
  bottom: calc(100% + 6px);
  z-index: 5;
  width: min(420px, 100%);
  /* Opens inside the scrolling body, above the text box: kept to what the name field
     and the text box leave above it, or its top would be cut off. */
  max-height: 300px;
  overflow-y: auto;
  padding: 6px 0;
  border-radius: 12px;
  background: var(--bk-elevated);
  box-shadow: inset 0 0 0 1px var(--bk-border), var(--bk-lift);
}

.wme-menu-group + .wme-menu-group {
  border-top: 1px solid var(--bk-border);
  margin-top: 4px;
  padding-top: 4px;
}

.wme-menu-heading {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 8px 16px 6px;
  border: none;
  background: transparent;
  color: var(--bk-text-3);
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
}

.wme-menu-heading svg {
  transition: transform 0.15s ease;
}

.wme-menu-heading svg.collapsed {
  transform: rotate(180deg);
}

.wme-menu-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
  padding: 9px 16px;
  border: none;
  background: transparent;
  color: var(--bk-text);
  font-family: var(--font-ui);
  font-size: 14px;
  text-align: left;
  cursor: pointer;
}

.wme-menu-item:hover {
  background: var(--bk-hover);
}

.wme-menu-label {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.wme-menu-code {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--bk-text-3);
}

.wme-error {
  margin-top: 12px;
}

.wme-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding: 14px 16px;
  border-top: 1px solid var(--bk-border);
}

.wme-cancel {
  padding: 10px 18px;
}

.wme-apply {
  padding: 10px 22px;
  box-shadow: none;
  background: var(--bk-text);
  color: var(--bk-elevated);
  font-weight: 600;
}

.wme-apply:hover:not(:disabled) {
  background: var(--bk-text);
  opacity: 0.88;
}

/* 16px on a phone so iOS does not zoom the page when a field takes focus, as
   mobile.css does for every other field there. */
@media (max-width: 768px) {
  .wme-input,
  .wme-textarea {
    font-size: 16px;
  }
  .wme-textarea {
    min-height: 160px;
  }
  .wme-menu-code {
    font-size: 11px;
  }
  .wme-menu {
    max-height: 240px;
  }
}
/* iPhone / iPad in a browser tab only: notifications need the Home Screen app, explained
   over the alert window's own content (AlertModal.jsx, needsHomeScreenForAlerts). */
.home-screen-help {
  position: absolute;
  inset: 0;
  z-index: 20;
  display: grid;
  place-items: center;
  padding: 18px;
  background: rgba(0, 0, 0, 0.45);
}

.home-screen-help-card {
  width: min(420px, 100%);
  max-height: 100%;
  overflow-y: auto;
  box-sizing: border-box;
  padding: 22px 20px 18px;
  border-radius: 16px;
  background: #FFFFFF;
  color: #0B0B0B;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.3);
  text-align: left;
}

.alert-modal.dark-mode .home-screen-help-card {
  background: #1C1C1E;
  color: #F7F7F7;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.08);
}

.home-screen-help-icon {
  font-size: 30px;
  line-height: 1;
  margin-bottom: 10px;
}

.home-screen-help-card h4 {
  margin: 0 0 8px;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.3;
}

.home-screen-help-card p {
  margin: 0 0 12px;
  font-size: 14px;
  line-height: 1.45;
  opacity: 0.8;
}

.home-screen-help-steps {
  margin: 0 0 16px;
  padding-left: 20px;
  font-size: 14px;
  line-height: 1.5;
}

.home-screen-help-steps li {
  margin-bottom: 6px;
}

.home-screen-help-share {
  width: 17px;
  height: 17px;
  margin: 0 4px;
  vertical-align: -3px;
  color: #0A84FF;
}

.home-screen-help-btn {
  width: 100%;
  min-height: 44px;
  border: none;
  border-radius: 12px;
  background: var(--brand, #4C29E9);
  color: #FFFFFF;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}

.home-screen-help-btn:hover {
  background: var(--brand-hover, #3D20DC);
}
/* The one list of every alert. Built on the price alerts panel's own classes
   (.price-alerts-modal, .alert-row, .alerts-btn), so it follows the same theme tokens;
   only what that panel has no use for is here. */

.alerts-manager {
  max-width: 720px;
}

.am-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  margin: -12px 0 14px;
  font-size: 12px;
  color: var(--bk-text-3);
}

.am-summary strong {
  color: var(--bk-text);
}

.am-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 10px;
}

.am-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid var(--bk-border);
  background: transparent;
  color: var(--bk-text-2);
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}

.am-chip:hover {
  color: var(--bk-text);
}

.am-chip--on {
  background: var(--bk-hover);
  border-color: var(--bk-text-2);
  color: var(--bk-text);
}

.am-chip-count {
  opacity: 0.6;
  font-weight: 500;
}

.am-toolbar {
  display: flex;
  gap: 8px;
  margin-bottom: 10px;
}

/* Scoped under .alerts-manager: .alerts-input sets width: 100% and loads after this file. */
.alerts-manager .am-search {
  flex: 1 1 auto;
  width: auto;
  min-width: 0;
}

.alerts-manager .am-status {
  flex: 0 0 auto;
  width: auto;
}

.am-bulk {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-height: 32px;
  margin-bottom: 8px;
}

.am-check {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--bk-text-2);
  cursor: pointer;
}

.am-bulk-actions {
  display: flex;
  gap: 6px;
}

.am-row {
  align-items: flex-start;
  gap: 10px;
}

.am-row-check {
  margin-top: 3px;
  flex-shrink: 0;
}

.am-row-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.am-row--paused .am-row-main,
.am-row--triggered .am-row-main {
  opacity: 0.7;
}

.am-symbol {
  font-weight: 700;
  font-size: 14px;
  color: var(--bk-text);
}

.am-title {
  font-size: 13px;
  color: var(--bk-text);
  overflow-wrap: anywhere;
}

.am-type {
  padding: 2px 8px;
  border-radius: 5px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

.am-type--swift { background: rgba(99, 102, 241, 0.15); color: #6366f1; }
.am-type--price { background: rgba(16, 185, 129, 0.15); color: var(--bk-pos); }
.am-type--drawing { background: rgba(245, 158, 11, 0.15); color: #d97706; }
.am-type--indicator { background: rgba(59, 130, 246, 0.15); color: #3b82f6; }

.am-status-tag {
  margin-left: auto;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bk-text-3);
}

.am-status-tag--active { color: var(--bk-pos); }
.am-status-tag--triggered { color: #d97706; }

.am-row-actions {
  flex-wrap: wrap;
  justify-content: flex-end;
  max-width: 45%;
}

.am-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--bk-border);
}

/* A phone: the actions go under the alert instead of squeezing it. */
@media (max-width: 560px) {
  .alerts-manager {
    width: calc(100% - 32px);
    padding: 16px;
  }

  .am-row {
    flex-wrap: wrap;
  }

  .am-row-main {
    flex-basis: calc(100% - 30px);
  }

  .am-row-actions {
    max-width: none;
    width: 100%;
    justify-content: flex-start;
    padding-left: 24px;
  }

  .am-toolbar {
    flex-direction: column;
  }

  .alerts-manager .am-status {
    width: 100%;
  }
}
/* Voice input in the Chartify AI composer. The bar lies over the whole composer while
   recording, so the text box and its buttons are out of the way until it is done. */

.ai-composer {
  position: relative;
}

/* Scoped under .chatbot-input: the panel styles every button in there as its round
   purple send button (".chatbot-input button"), and these are not that. */
.chatbot-input .ai-mic-btn {
  width: 30px;
  height: 30px;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: #6E6E73;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.chatbot-input .ai-mic-btn:hover:not(:disabled) {
  background: rgba(0, 0, 0, 0.06);
  color: #1D1D1F;
}

.chatbot-input .ai-mic-btn:disabled {
  opacity: 0.4;
  cursor: default;
}

.chatbot-modal.dark-mode .chatbot-input .ai-mic-btn { background: transparent; color: #A1A1A6; }
.chatbot-modal.dark-mode .chatbot-input .ai-mic-btn:hover:not(:disabled) { background: rgba(255, 255, 255, 0.08); color: #F5F5F7; }

.ai-voice-bar {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 8px;
  border-radius: inherit;
  background: #fff;
  color: var(--ai-accent, #6366f1);
  animation: ai-voice-in 0.16s ease-out;
}

.chatbot-modal.dark-mode .ai-voice-bar {
  background: #1c1c1e;
}

@keyframes ai-voice-in {
  from { opacity: 0; transform: scale(0.98); }
  to { opacity: 1; transform: none; }
}

.chatbot-input .ai-voice-btn {
  width: 30px;
  height: 30px;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.06);
  color: #3A3A3C;
  cursor: pointer;
}

.chatbot-input .ai-voice-btn:hover:not(:disabled) { background: rgba(0, 0, 0, 0.1); }

.chatbot-modal.dark-mode .chatbot-input .ai-voice-btn { background: rgba(255, 255, 255, 0.1); color: #E5E5EA; }
.chatbot-modal.dark-mode .chatbot-input .ai-voice-btn:hover:not(:disabled) { background: rgba(255, 255, 255, 0.16); }

.chatbot-input .ai-voice-btn.ai-voice-btn--done,
.chatbot-modal.dark-mode .chatbot-input .ai-voice-btn.ai-voice-btn--done {
  background: var(--ai-accent, #6366f1);
  color: #fff;
}

.chatbot-input .ai-voice-btn.ai-voice-btn--done:hover:not(:disabled),
.chatbot-modal.dark-mode .chatbot-input .ai-voice-btn.ai-voice-btn--done:hover:not(:disabled) {
  background: var(--ai-accent-hover, #4f46e5);
}

.chatbot-input .ai-voice-btn:disabled {
  opacity: 0.4;
  cursor: default;
}

.ai-voice-dot {
  width: 8px;
  height: 8px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: #EF4444;
  animation: ai-voice-pulse 1.2s ease-in-out infinite;
}

@keyframes ai-voice-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.3; }
}

.ai-voice-wave {
  flex: 1 1 auto;
  min-width: 0;
  height: 26px;
}

.ai-voice-time {
  flex: 0 0 auto;
  font-family: var(--font-ui);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: #6E6E73;
}

.chatbot-modal.dark-mode .ai-voice-time { color: #A1A1A6; }

.ai-voice-status {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: var(--font-ui);
  font-size: 13px;
  color: #6E6E73;
}

.chatbot-modal.dark-mode .ai-voice-status { color: #A1A1A6; }

.ai-voice-spinner {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-top-color: transparent;
  animation: ai-voice-spin 0.7s linear infinite;
}

@keyframes ai-voice-spin {
  to { transform: rotate(360deg); }
}

.ai-voice-error {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(100% + 6px);
  padding: 7px 10px;
  border-radius: 8px;
  background: rgba(239, 68, 68, 0.1);
  border: 1px solid rgba(239, 68, 68, 0.3);
  color: #DC2626;
  font-family: var(--font-ui);
  font-size: 12px;
}

@media (prefers-reduced-motion: reduce) {
  .ai-voice-bar, .ai-voice-dot, .ai-voice-spinner { animation: none; }
}
/* Backtest Results Modal Overlay */
.backtest-modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: transparent;
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 10000;
}

/* Modal Content */
.backtest-modal-content {
  background: #1c1c1e;
  border-radius: 16px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
  width: 90%;
  max-width: 500px;
  max-height: 90vh;
  overflow: hidden;
  animation: slideUp 0.3s ease-out;
}

.backtest-modal-overlay.light .backtest-modal-content {
  background: #ffffff;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
}

@keyframes slideUp {
  from {
    opacity: 0;
    transform: translateY(30px) scale(0.95);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

/* Header */
.backtest-modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 28px 32px 20px 32px;
  border-bottom: none;
}

.backtest-modal-overlay.light .backtest-modal-header {
  border-bottom: none;
}

.backtest-modal-title {
  margin: 0;
  font-size: 20px;
  font-weight: 700;
  color: #ffffff;
  letter-spacing: 0.5px;
}

.backtest-modal-overlay.light .backtest-modal-title {
  color: #000000;
}

.backtest-modal-close {
  background: transparent;
  border: none;
  color: #666;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  font-size: 20px;
  cursor: pointer;
  transition: all 0.2s;
  display: flex;
  align-items: center;
  justify-content: center;
}

.backtest-modal-overlay.light .backtest-modal-close {
  color: #888;
}

.backtest-modal-close:hover {
  background: rgba(255, 255, 255, 0.1);
  color: #999;
}

.backtest-modal-overlay.light .backtest-modal-close:hover {
  background: rgba(0, 0, 0, 0.05);
  color: #444;
}

/* Body */
.backtest-modal-body {
  padding: 0 32px 20px 32px;
}

.backtest-stats-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
  margin-bottom: 20px;
}

.backtest-stat-card {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  padding: 20px;
  text-align: center;
  transition: all 0.2s ease;
}

.backtest-modal-overlay.light .backtest-stat-card {
  background: #f8f9fa;
  border: 1px solid #e5e5e5;
}

.backtest-stat-card.highlight {
  background: rgba(16, 185, 129, 0.1);
  border: 1px solid rgba(16, 185, 129, 0.3);
}

.backtest-modal-overlay.light .backtest-stat-card.highlight {
  background: rgba(16, 185, 129, 0.05);
  border: 1px solid rgba(16, 185, 129, 0.2);
}

.backtest-stat-card:hover {
  border-color: rgba(255, 255, 255, 0.2);
  ;
}

.backtest-modal-overlay.light .backtest-stat-card:hover {
  border-color: #d0d0d0;
  ;
}

.backtest-stat-label {
  font-size: 12px;
  font-weight: 600;
  color: #d0d0d0;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 8px;
  display: block;
}

.backtest-modal-overlay.light .backtest-stat-label {
  color: #666;
}

/* The monospace face these figures have always had. It used to reach them from
   CandlestickChart.css, which defines the same class name for the on-chart dashboard and
   happened to load after this file; scoping that stylesheet's rules to the dashboard took
   the font away with them. Declared here now, in the stylesheet that owns the modal, so it
   no longer depends on which file the bundler emits last.

   tabular-nums too: four figures in a 2x2 grid, and proportional digits shift the columns
   about as the values change. */
.backtest-stat-value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 28px;
  font-weight: 700;
  color: #d0d0d0;
  display: block;
}

.backtest-modal-overlay.light .backtest-stat-value {
  color: #000000;
}

.backtest-stat-value.best {
  color: #10B981;
}

.backtest-modal-overlay.light .backtest-stat-value.best {
  color: #059669;
}

/* The sample size the best result was measured over, under the run summary. Quieter than
   that line, since it qualifies the percentages rather than describing the run. */
.backtest-time-info,
.backtest-trades-info {
  text-align: center;
  padding: 12px;
  background: transparent;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 500;
  color: #c0c0c0;
}

.backtest-modal-overlay.light .backtest-time-info,
.backtest-modal-overlay.light .backtest-trades-info {
  color: #666;
}

/* Footer */
.backtest-modal-footer {
  display: flex;
  gap: 12px;
  padding: 0 32px 28px 32px;
  border-top: none;
  background: transparent;
}

.backtest-modal-overlay.light .backtest-modal-footer {
  border-top: none;
  background: transparent;
}

.backtest-modal-btn {
  flex: 1;
  padding: 14px 24px;
  font-size: 14px;
  font-weight: 600;
  border-radius: 10px;
  cursor: pointer;
  transition: all 0.2s ease;
  border: none;
  letter-spacing: 0.3px;
}

/* Close Button - Red */
.backtest-modal-btn.cancel {
  background: rgba(239, 68, 68, 0.15);
  color: #EF4444;
  border: 1px solid rgba(239, 68, 68, 0.3);
}

.backtest-modal-overlay.light .backtest-modal-btn.cancel {
  background: rgba(239, 68, 68, 0.1);
  color: #DC2626;
  border: 1px solid rgba(239, 68, 68, 0.2);
}

.backtest-modal-btn.cancel:hover {
  background: rgba(239, 68, 68, 0.25);
  border-color: rgba(239, 68, 68, 0.4);
  ;
  box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
}

.backtest-modal-overlay.light .backtest-modal-btn.cancel:hover {
  background: rgba(239, 68, 68, 0.15);
  border-color: rgba(239, 68, 68, 0.3);
  box-shadow: 0 4px 12px rgba(239, 68, 68, 0.15);
}

.backtest-modal-btn.cancel:active {
  transform: translateY(0);
}

/* Apply Button - Green */
.backtest-modal-btn.apply {
  background: rgba(16, 185, 129, 0.2);
  color: #10B981;
  border: 1px solid rgba(16, 185, 129, 0.4);
}

.backtest-modal-overlay.light .backtest-modal-btn.apply {
  background: rgba(16, 185, 129, 0.15);
  color: #059669;
  border: 1px solid rgba(16, 185, 129, 0.3);
}

.backtest-modal-btn.apply:hover {
  background: rgba(16, 185, 129, 0.3);
  border-color: rgba(16, 185, 129, 0.5);
  ;
  box-shadow: 0 4px 12px rgba(16, 185, 129, 0.4);
}

.backtest-modal-overlay.light .backtest-modal-btn.apply:hover {
  background: rgba(16, 185, 129, 0.2);
  border-color: rgba(16, 185, 129, 0.4);
  box-shadow: 0 4px 12px rgba(16, 185, 129, 0.15);
}

.backtest-modal-btn.apply:active {
  transform: translateY(0);
}

/* Responsive */
@media (max-width: 640px) {
  .backtest-stats-grid {
    grid-template-columns: 1fr;
  }
  
  .backtest-modal-content {
    width: 95%;
    margin: 20px;
  }
  
  .backtest-modal-header,
  .backtest-modal-body,
  .backtest-modal-footer {
    padding-left: 24px;
    padding-right: 24px;
  }
}
/* Backtest Results Modal Overlay */
.backtest-modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: transparent;
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 10000;
}

/* Modal Content */
/*
 * The body scrolls, the header and footer do not.
 *
 * max-height with overflow:hidden and nothing scrollable inside means anything taller than
 * 90vh is cut off with no way to reach it. Expanding the advanced list adds ~435px, which on
 * a 375x812 phone put the content at 1137px against a 731px cap: 406px gone, including the
 * whole footer, so Close and Apply Best Settings sat outside the viewport entirely and
 * elementFromPoint on them returned nothing - the only ways out were Escape or a tap on the
 * overlay. Making the body the scroll container keeps both buttons pinned and reachable at
 * any height.
 */
.backtest-modal-content {
  background: #1c1c1e;
  border-radius: 16px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
  width: 90%;
  max-width: 500px;
  max-height: 90vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  animation: slideUp 0.3s ease-out;
}

.backtest-modal-header,
.backtest-modal-footer {
  flex: 0 0 auto;
}

/* min-height:0 because a flex item's default min-height:auto refuses to shrink below its
 * content, which would hand the overflow straight back to the modal. */
.backtest-modal-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  /* Headroom for the hover lift.
   *
   * overflow-y: auto makes this a clipping box, and overflow-x resolves to auto with it, so
   * anything drawn above the content edge is cut. The top stat cards sat flush against that
   * edge, so their translateY(-2px) took the top two pixels of both boxes off. Four pixels
   * here is room for the lift with a little to spare, taken back out of the header's bottom
   * padding so nothing moves. */
  padding-top: 4px;
}

.backtest-modal-overlay.light .backtest-modal-content {
  background: #ffffff;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
}

@keyframes slideUp {
  from {
    opacity: 0;
    transform: translateY(30px) scale(0.95);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

/* Header */
.backtest-modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  /* 4px less at the bottom than it looks: that gap has moved into the body's top padding,
     where it can absorb the stat cards' hover lift. The distance on screen is unchanged. */
  padding: 28px 32px 24px 32px;
  border-bottom: none;
}

.backtest-modal-overlay.light .backtest-modal-header {
  border-bottom: none;
}

.backtest-modal-title {
  margin: 0;
  font-size: 20px;
  font-weight: 700;
  color: #ffffff;
  letter-spacing: 0.5px;
}

.backtest-modal-overlay.light .backtest-modal-title {
  color: #000000;
}

.backtest-modal-close {
  background: transparent;
  border: 1px solid #555;
  color: #888;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  font-size: 20px;
  cursor: pointer;
  transition: all 0.2s;
  display: flex;
  align-items: center;
  justify-content: center;
}

.backtest-modal-overlay.light .backtest-modal-close {
  color: #888;
}

.backtest-modal-close:hover {
  background: rgba(255, 255, 255, 0.1);
  color: #999;
}

.backtest-stats-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
  margin-bottom: 20px;
}

.backtest-stat-card {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  padding: 20px;
  text-align: center;
  transition: all 0.2s ease;
}

.backtest-modal-overlay.light .backtest-stat-card {
  background: #f8f9fa;
  border: 1px solid #e5e5e5;
}

.backtest-stat-card.highlight {
  background: rgba(16, 185, 129, 0.1);
  border: 1px solid rgba(16, 185, 129, 0.3);
}

.backtest-modal-overlay.light .backtest-stat-card.highlight {
  background: rgba(16, 185, 129, 0.05);
  border: 1px solid rgba(16, 185, 129, 0.2);
}

.backtest-stat-card:hover {
  border-color: rgba(255, 255, 255, 0.2);
  ;
}

.backtest-modal-overlay.light .backtest-stat-card:hover {
  border-color: #d0d0d0;
}

.backtest-stat-label {
  font-size: 12px;
  font-weight: 600;
  color: #888;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 8px;
  display: block;
}

.backtest-modal-overlay.light .backtest-stat-label {
  color: #666;
}

/* The monospace face these figures have always had. It used to reach them from
   CandlestickChart.css, which defines the same class name for the on-chart dashboard and
   happened to load after this file; scoping that stylesheet's rules to the dashboard took
   the font away with them. Declared here now, in the stylesheet that owns the modal, so it
   no longer depends on which file the bundler emits last.

   tabular-nums too: four figures in a 2x2 grid, and proportional digits shift the columns
   about as the values change. */
.backtest-stat-value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 28px;
  font-weight: 700;
  color: #d0d0d0;
  display: block;
}

.backtest-modal-overlay.light .backtest-stat-value {
  color: #000000;
}

.backtest-stat-value.best {
  color: #10B981;
}

.backtest-modal-overlay.light .backtest-stat-value.best {
  color: #059669;
}

.backtest-time-info,
.backtest-trades-info {
  text-align: center;
  padding: 12px;
  background: transparent;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 500;
  color: #666;
}

.backtest-modal-overlay.light .backtest-time-info,
.backtest-modal-overlay.light .backtest-trades-info {
  color: #888;
}

/* The trades line sits directly beneath the time line, so it drops the top padding
   that would otherwise double the gap between the two. */
.backtest-trades-info {
  padding-top: 0;
}

/* Footer */
.backtest-modal-footer {
  display: flex;
  gap: 10px;
  padding: 24px 32px;
  border-top: none;
  background: transparent;
}

.backtest-modal-overlay.light .backtest-modal-footer {
  border-top: none;
  background: transparent;
}

.backtest-modal-btn {
  flex: 1;
  padding: 14px 24px;
  font-size: 14px;
  font-weight: 600;
  border-radius: 10px;
  cursor: pointer;
  transition: all 0.2s ease;
  border: none;
  letter-spacing: 0.3px;
}

.backtest-modal-btn.cancel {
  background: rgba(239, 68, 68, 0.15);
  color: #EF4444;
  border: 1px solid rgba(239, 68, 68, 0.3);
}

.backtest-modal-overlay.light .backtest-modal-btn.cancel {
  background: rgba(239, 68, 68, 0.1);
  color: #DC2626;
  border: 1px solid rgba(239, 68, 68, 0.2);
}

.backtest-modal-btn.cancel:hover {
  background: rgba(239, 68, 68, 0.25);
  border-color: rgba(239, 68, 68, 0.4);
  ;
  box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
}

.backtest-modal-overlay.light .backtest-modal-btn.cancel:hover {
  background: rgba(239, 68, 68, 0.15);
  border-color: rgba(239, 68, 68, 0.3);
}

.backtest-modal-btn.cancel:active {
  transform: translateY(0);
}

.backtest-modal-btn.apply {
  background: rgba(16, 185, 129, 0.2);
  color: #10B981;
  border: 1px solid rgba(16, 185, 129, 0.4);
}

.backtest-modal-overlay.light .backtest-modal-btn.apply {
  background: rgba(16, 185, 129, 0.15);
  color: #059669;
  border: 1px solid rgba(16, 185, 129, 0.3);
}

.backtest-modal-btn.apply:hover {
  background: rgba(16, 185, 129, 0.3);
  border-color: rgba(16, 185, 129, 0.5);
  ;
  box-shadow: 0 4px 12px rgba(16, 185, 129, 0.4);
}

.backtest-modal-overlay.light .backtest-modal-btn.apply:hover {
  background: rgba(16, 185, 129, 0.2);
}

.backtest-modal-btn.apply:active {
  transform: translateY(0);
}

/* Responsive */
@media (max-width: 640px) {
  .backtest-stats-grid {
    grid-template-columns: 1fr;
  }
  
  .backtest-modal-content {
    width: 95%;
    margin: 20px;
  }
}

/* ── Advanced: every tested setting ───────────────────────────────────────────
   Appended at the end on purpose. The rules above exist twice over in this file
   and the later copy wins, so anything declared earlier would be overridden.

   Everything here borrows the modal's own vocabulary rather than inventing one:
   the panel is a .backtest-stat-card surface, the headings are .backtest-stat-label,
   and Apply is .backtest-modal-btn.apply at row scale. An earlier version used its
   own greys, radii and green and read as a component from a different product. */

/* Its own line under the two summary lines. */
.backtest-advanced-row {
  display: flex;
  justify-content: center;
  margin-top: 10px;
}

.backtest-advanced-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  /* Named now, but still quiet: no fill until it is hovered or open, and the same muted
     label treatment as the stat cards above, so it does not compete with Apply. */
  color: #888;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: all 0.2s ease;
}

.backtest-advanced-caret {
  font-size: 11px;
  line-height: 1;
  transition: transform 0.2s ease;
}

.backtest-advanced-toggle.open .backtest-advanced-caret {
  transform: rotate(180deg);
}

.backtest-advanced-toggle:hover,
.backtest-advanced-toggle:focus-visible {
  color: #d0d0d0;
  background: rgba(255, 255, 255, 0.05);
  border-color: rgba(255, 255, 255, 0.1);
}

.backtest-advanced-toggle.open {
  color: #10B981;
  background: rgba(16, 185, 129, 0.1);
  border-color: rgba(16, 185, 129, 0.3);
}

/* The card. Same surface, radius and padding as .backtest-stat-card, and no side
   margin - the modal body already insets by 32px, so a margin here would indent it
   past the stat cards it sits under. */
.backtest-advanced-card {
  margin-top: 4px;
  padding: 20px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
}

.backtest-advanced-label {
  display: block;
  margin-bottom: 12px;
  font-size: 12px;
  font-weight: 600;
  color: #888;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

/* The modal itself does not scroll, so an expanded list has to bound its own height
   or it pushes the footer buttons out of the content box. */
.backtest-advanced-scroll {
  max-height: 260px;
  overflow-y: auto;
  overflow-x: auto;
  margin: 0 -4px;
  padding: 0 4px;
}

.backtest-advanced-table {
  width: 100%;
  /* NOT border-collapse: collapse. A collapsed border belongs to the table rather
     than to the cell, so the sticky header's bottom border stays behind while the
     header itself travels - the row separator detaches and scrolls away. Separate
     borders keep it on the cell where it sticks with it. Spacing is zeroed, so the
     layout is identical either way. */
  border-collapse: separate;
  border-spacing: 0;
  font-size: 12.5px;
}

/* Without this the short columns collapse to their content and W sits flush against
   L - "185 25" reads as one number. The last column drops it again so Apply stays
   flush with the card's padding. */
.backtest-advanced-table th,
.backtest-advanced-table td {
  padding-right: 8px;
}

/* The Apply column is pinned to the right edge. On a phone the modal is ~337px wide
   and the table needs ~374px, so without this the only actionable control in the row
   sits off-screen and has to be scrolled to. Everything else scrolls under it. The
   background has to be opaque for that to work, and matches what the card's
   rgba(255,255,255,0.05) composites to. */
.backtest-advanced-table th:last-child,
.backtest-advanced-table td:last-child {
  position: sticky;
  right: 0;
  padding-right: 0;
  padding-left: 8px;
  text-align: right;
  background: #272729;
}

/* Three layers, and all of them need saying. Both the header row and the pinned
   column are position: sticky, so both paint above the ordinary cells, and between
   two positioned elements at the same z-index the later one in the document wins -
   which would put a scrolling Apply button over the header. The corner cell belongs
   to both and has to sit above each. */
.backtest-advanced-table td:last-child {
  z-index: 1;
}

.backtest-advanced-table th:last-child {
  z-index: 3;
}

/* The row hover tint is translucent and cannot show through an opaque cell, so the
   pinned one gets the composited equivalent instead. */
.backtest-advanced-table tbody tr:hover td:last-child {
  background: #2c2c2e;
}

.backtest-advanced-table th {
  position: sticky;
  top: 0;
  /* Above the pinned last column (1), below the corner cell (3). */
  z-index: 2;
  padding: 0 8px 8px 0;
  text-align: left;
  /* Opaque, not the card's translucent fill: rows scrolling underneath a semi
     transparent header show through it. #272729 is what the card's rgba(255,255,255,0.05)
     actually composites to over the modal's #1c1c1e, so it matches rather than banding. */
  background: #272729;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.backtest-advanced-table td {
  padding: 7px 8px 7px 0;
  color: #d0d0d0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
  white-space: nowrap;
}

.backtest-advanced-table tbody tr:last-child td {
  border-bottom: none;
}

.backtest-advanced-table tbody tr {
  transition: background 0.15s ease;
}

.backtest-advanced-table tbody tr:hover td {
  background: rgba(255, 255, 255, 0.03);
}

.backtest-advanced-table .rank {
  width: 1.8em;
  color: #666;
}

.backtest-advanced-table td.win {
  color: var(--bk-pos);
  font-weight: 700;
}

.backtest-advanced-table td.muted {
  color: #888;
  font-variant-numeric: tabular-nums;
}

/* Header cells are buttons so the whole label is the sort target. */
.backtest-advanced-sort {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 2px 3px;
  margin-left: -3px;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: #888;
  font-family: inherit;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.backtest-advanced-sort:hover {
  color: #d0d0d0;
  background: rgba(255, 255, 255, 0.05);
}

.backtest-advanced-sort.active {
  color: var(--bk-text);
}

/* The inactive ↕ is dimmed rather than hidden, so the column reads as sortable
   before it is hovered without competing with the arrow that is actually set. */
.backtest-advanced-sort .arrow {
  font-size: 8px;
  opacity: 0.45;
}

.backtest-advanced-sort.active .arrow {
  opacity: 1;
}

/* .backtest-modal-btn.apply at row scale. */
.backtest-advanced-apply {
  padding: 4px 10px;
  background: rgba(16, 185, 129, 0.2);
  color: #10B981;
  border: 1px solid rgba(16, 185, 129, 0.4);
  border-radius: 8px;
  font-family: inherit;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.3px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.backtest-advanced-apply:hover {
  background: rgba(16, 185, 129, 0.3);
  border-color: rgba(16, 185, 129, 0.5);
  ;
  box-shadow: 0 2px 8px rgba(16, 185, 129, 0.3);
}

.backtest-advanced-apply:active {
  transform: translateY(0);
}

.backtest-advanced-note {
  margin-top: 12px;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.5;
  color: #666;
}

/* Light theme. .backtest-modal-content turns white while its inherited colour stays
   the dark-theme grey, so every one of these has to be restated rather than left to
   cascade - the same reason each rule above this file's light block does it. */
.backtest-modal-overlay.light .backtest-advanced-toggle {
  color: #888;
}

.backtest-modal-overlay.light .backtest-advanced-toggle:hover,
.backtest-modal-overlay.light .backtest-advanced-toggle:focus-visible {
  color: #000;
  background: #f0f1f2;
  border-color: #e5e5e5;
}

.backtest-modal-overlay.light .backtest-advanced-toggle.open {
  color: #059669;
  background: rgba(16, 185, 129, 0.08);
  border-color: rgba(16, 185, 129, 0.25);
}

.backtest-modal-overlay.light .backtest-advanced-card {
  background: #f8f9fa;
  border: 1px solid #e5e5e5;
}

.backtest-modal-overlay.light .backtest-advanced-label,
.backtest-modal-overlay.light .backtest-advanced-sort,
.backtest-modal-overlay.light .backtest-advanced-table td.muted {
  color: #666;
}

.backtest-modal-overlay.light .backtest-advanced-table th,
.backtest-modal-overlay.light .backtest-advanced-table td:last-child {
  background: #f8f9fa;
}

.backtest-modal-overlay.light .backtest-advanced-table th {
  border-bottom-color: #e5e5e5;
}

.backtest-modal-overlay.light .backtest-advanced-table tbody tr:hover td:last-child {
  background: #f2f3f4;
}

.backtest-modal-overlay.light .backtest-advanced-table td {
  color: #000;
  border-bottom-color: rgba(0, 0, 0, 0.05);
}

.backtest-modal-overlay.light .backtest-advanced-table tbody tr:hover td {
  background: rgba(0, 0, 0, 0.02);
}

.backtest-modal-overlay.light .backtest-advanced-table .rank {
  color: #999;
}

/* #10B981 is too pale on white - the stat cards drop to #059669 here for the same
   reason. */
.backtest-modal-overlay.light .backtest-advanced-table td.win,
.backtest-modal-overlay.light .backtest-advanced-sort.active {
  color: var(--bk-pos);
}

.backtest-modal-overlay.light .backtest-advanced-sort:hover {
  color: #000;
  background: #f0f1f2;
}

.backtest-modal-overlay.light .backtest-advanced-apply {
  background: rgba(16, 185, 129, 0.15);
  color: #059669;
  border: 1px solid rgba(16, 185, 129, 0.3);
}

.backtest-modal-overlay.light .backtest-advanced-apply:hover {
  background: rgba(16, 185, 129, 0.2);
}

.backtest-modal-overlay.light .backtest-advanced-note {
  color: #888;
}
/* Reports section of the trade journal - see JournalReports.jsx.
 *
 * Every colour is a --bk-* token, the same ones the rest of the journal uses, so this
 * block follows the theme without a dark-mode rule of its own. The one exception is the
 * bar fills, which carry their own alpha over --bk-pos / --bk-neg.
 *
 * Selectors are all jr-* and none of them reach outside this component. The one class
 * borrowed from elsewhere is .journal-stat-info, the little "i" tooltip, which is styled
 * in CandlestickChart.css and reused here on purpose so the hints look identical.
 */

.jr-root {
  margin-top: 30px;
  font-family: var(--font-ui);
  color: var(--bk-text);
}

.jr-section-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}

.jr-section-title {
  margin: 0;
  font-size: 18px;
  font-weight: 700;
  color: var(--bk-text);
}

.jr-section-note {
  font-size: 12px;
  color: var(--bk-text-3);
}

/* ── stat cards ──────────────────────────────────────────────────────────── */

.jr-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(170px, 100%), 1fr));
  gap: 16px;
  margin-bottom: 24px;
}

.jr-card {
  padding: 18px;
  background: var(--bk-card);
  border-radius: 14px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  min-width: 0;
}

.jr-card-label {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
  font-size: 12px;
  font-weight: 500;
  color: var(--bk-text-2);
}

.jr-card-value {
  font-size: 24px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  /* Six-figure P&L in a 170px card would otherwise push the grid wider than the modal. */
  overflow-wrap: anywhere;
}

.jr-value-pos { color: var(--bk-pos); }
.jr-value-neg { color: var(--bk-neg); }

/* ── panels ──────────────────────────────────────────────────────────────── */

.jr-panel {
  padding: 18px;
  background: var(--bk-card);
  border-radius: 14px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  margin-bottom: 20px;
  min-width: 0;
}

.jr-panel-title {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 14px;
  font-size: 13px;
  font-weight: 600;
  color: var(--bk-text-2);
}

.jr-panel-note {
  font-size: 11px;
  font-weight: 400;
  color: var(--bk-text-3);
}

.jr-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: 20px;
}

.jr-empty {
  padding: 24px 4px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--bk-text-3);
  text-align: center;
}

.jr-empty-standalone {
  margin-top: 30px;
}

/* ── bar charts ──────────────────────────────────────────────────────────── */

.jr-chart {
  min-width: 0;
}

.jr-bars {
  position: relative;
  display: flex;
  align-items: stretch;
  gap: 2px;
  height: 140px;
}

/* Breakeven. Sits at whatever height the data puts zero, which is the whole point of
   drawing it - a chart with no line here would not show which bars are losses. */
.jr-zero-line {
  position: absolute;
  left: 0;
  right: 0;
  top: var(--jr-zero-top, 100%);
  height: 1px;
  background: var(--bk-border);
  pointer-events: none;
}

.jr-bar-col {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
}

.jr-bar {
  position: absolute;
  left: 0;
  right: 0;
  border-radius: 2px;
  transition: opacity 0.15s ease;
}

.jr-bar-col:hover .jr-bar { opacity: 0.75; }

.jr-bar-pos { background: var(--bk-pos); }
.jr-bar-neg { background: var(--bk-neg); }

.jr-bar-labels {
  display: flex;
  gap: 2px;
  margin-top: 6px;
}

.jr-bar-label {
  flex: 1 1 0;
  min-width: 0;
  font-size: 9px;
  line-height: 1.2;
  color: var(--bk-text-3);
  text-align: center;
  /* Each label box is only as wide as its own bar - a 24th of the row on the hour chart -
     which is narrower than "00:00". The component thins those labels to every third, so
     the two boxes on either side are empty strings and a centred label can spill into
     them without hitting anything. Clipping here instead cost the last character and
     rendered the axis as 00:0, 03:0, 06:0. */
  overflow: visible;
  white-space: nowrap;
}

/* ── equity curve ────────────────────────────────────────────────────────── */

.jr-curve-wrap { min-width: 0; }

.jr-curve-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}

.jr-curve-value {
  font-size: 22px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--bk-text);
}

.jr-curve-dd { text-align: right; }

.jr-curve-dd-value {
  font-size: 16px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--bk-neg);
}

.jr-curve-sub {
  font-size: 11px;
  color: var(--bk-text-3);
}

.jr-curve {
  display: block;
  width: 100%;
  height: 180px;
  overflow: visible;
}

/* The path is stretched by preserveAspectRatio="none", so the stroke has to opt out of
   that scaling or it thickens horizontally and thins vertically.
   Red because this is the underwater plot: every point on it is a loss against the
   account's own high-water mark, including the flat stretches at zero. */
.jr-curve-line {
  fill: none;
  stroke: var(--bk-neg);
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.jr-curve-area {
  fill: var(--bk-neg);
  opacity: 0.12;
  stroke: none;
}

.jr-curve-axis {
  display: flex;
  justify-content: space-between;
  margin-top: 6px;
  font-size: 10px;
  color: var(--bk-text-3);
}

/* ── phone ───────────────────────────────────────────────────────────────── */

@media (max-width: 640px) {
  .jr-root { margin-top: 20px; }
  .jr-cards { grid-template-columns: repeat(auto-fit, minmax(min(132px, 100%), 1fr)); gap: 12px; }
  .jr-card { padding: 14px; }
  .jr-card-value { font-size: 19px; }
  .jr-panel { padding: 14px; }
  .jr-bars { height: 110px; }
  .jr-curve { height: 140px; }
  .jr-grid { gap: 16px; }
}
/* The preview card beside the Indicators window. Portalled to <body> and fixed, so the
   window's own overflow cannot clip it; above the window, which sits at z-index 100.
   It never takes the pointer - it is something to look at, and a card the mouse could
   land on would steal the hover from the row it belongs to. */
.indicator-hover-preview {
  position: fixed;
  z-index: 1200;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid rgba(0, 0, 0, 0.1);
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.18);
  pointer-events: none;
  animation: indicator-hover-preview-in 140ms ease-out;
}

.indicator-hover-preview.dark {
  border-color: #2A2A2A;
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.55);
}

.indicator-hover-preview-drawing {
  display: block;
  width: 100%;
  height: 100%;
}

@keyframes indicator-hover-preview-in {
  from {
    opacity: 0;
    transform: scale(0.97);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

@media (prefers-reduced-motion: reduce) {
  .indicator-hover-preview {
    animation: none;
  }
}
/* Support - the user's tickets. Built from the same tokens as the other floating panels,
   so it follows the light and dark theme with them. */

.support-center-overlay { z-index: 10040; }

.support-center {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 10050;
  width: 520px;
  max-width: calc(100vw - 24px);
  max-height: min(720px, calc(var(--app-height, 100vh) - 32px));
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  background: var(--bk-elevated);
  box-shadow: inset 0 0 0 1px var(--bk-border), var(--bk-lift, 0 20px 50px rgba(0, 0, 0, 0.25));
  border-radius: var(--bk-r-panel, 16px);
  color: var(--bk-text);
  font-family: var(--font-ui);
  animation: supportCenterIn 0.18s cubic-bezier(0.33, 1, 0.68, 1);
  overflow: hidden;
}

@keyframes supportCenterIn {
  from { opacity: 0; transform: translate(-50%, -48%); }
  to { opacity: 1; transform: translate(-50%, -50%); }
}

.support-center-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 16px 18px 12px;
  border-bottom: 1px solid var(--bk-border);
}
.support-center-head h3 {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  font-size: 16px;
  font-weight: 650;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.support-center-back {
  border: none;
  background: transparent;
  color: var(--bk-text-2);
  font-size: 24px;
  line-height: 1;
  padding: 0 6px 2px 0;
  cursor: pointer;
}
.support-center-back:hover { color: var(--bk-text); }

.support-center-body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px 18px 18px;
  overflow-y: auto;
  min-height: 0;
}

.support-center-text, .support-center-hint {
  margin: 0;
  color: var(--bk-text-2);
  font-size: 13px;
  line-height: 1.5;
}
.support-center-hint { font-size: 12px; }

.support-center-error {
  margin: 12px 18px 0;
  padding: 8px 12px;
  border-radius: var(--bk-r-control, 8px);
  background: rgba(239, 68, 68, 0.1);
  color: #DC2626;
  font-size: 12.5px;
  font-weight: 500;
}
.dark-mode .support-center-error { color: #FF6B6B; }

.support-center-primary, .support-center-secondary {
  height: 38px;
  border: none;
  border-radius: var(--bk-r-control, 8px);
  font-family: var(--font-ui);
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.15s ease;
}
.support-center-primary { background: var(--bk-primary, #6366f1); color: var(--bk-on-primary, #fff); }
.support-center-secondary { background: var(--bk-input); color: var(--bk-text); box-shadow: inset 0 0 0 1px var(--bk-border); }
.support-center-primary:hover:not(:disabled), .support-center-secondary:hover { opacity: 0.88; }
.support-center-primary:disabled { opacity: 0.45; cursor: default; }

.support-center-list { display: flex; flex-direction: column; gap: 6px; }
.support-center-empty { color: var(--bk-text-3); text-align: center; padding: 16px 0; font-size: 13px; }
.support-center-item {
  display: flex;
  flex-direction: column;
  gap: 6px;
  text-align: left;
  padding: 10px 12px;
  border: none;
  border-radius: var(--bk-r-control, 8px);
  background: var(--bk-input);
  box-shadow: inset 0 0 0 1px var(--bk-border);
  color: var(--bk-text);
  font-family: var(--font-ui);
  cursor: pointer;
}
.support-center-item:hover { box-shadow: inset 0 0 0 1px var(--bk-text-3); }
.support-center-item.unread { box-shadow: inset 0 0 0 1.5px var(--bk-primary, #6366f1); }
.support-center-item-top { display: flex; align-items: center; gap: 8px; }
.support-center-item-subject { flex: 1 1 auto; min-width: 0; font-size: 13.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.support-center-new { flex: 0 0 auto; font-size: 11px; font-weight: 700; color: var(--bk-primary, #6366f1); }
.support-center-item-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: 11.5px; color: var(--bk-text-3); }

.support-center-chip { padding: 1px 7px; border-radius: 999px; font-size: 11px; font-weight: 600; background: var(--bk-hover, rgba(0, 0, 0, 0.06)); color: var(--bk-text-2); }
.support-center-chip.kind-bug { background: rgba(239, 68, 68, 0.12); color: #E5342A; }
.support-center-chip.kind-feature { background: rgba(99, 102, 241, 0.13); color: #6366F1; }
.support-center-chip.status-answered { background: rgba(52, 199, 89, 0.14); color: #1E9E4A; }
.support-center-chip.status-open { background: rgba(255, 149, 0, 0.14); color: #D97706; }

.support-center-label { display: flex; flex-direction: column; gap: 5px; font-size: 12px; font-weight: 600; color: var(--bk-text-2); }
.support-center-input {
  width: 100%;
  box-sizing: border-box;
  padding: 9px 12px;
  border: none;
  border-radius: var(--bk-r-control, 8px);
  background: var(--bk-input);
  box-shadow: inset 0 0 0 1px var(--bk-border);
  color: var(--bk-text);
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 400;
  outline: none;
}
.support-center-input:focus { box-shadow: inset 0 0 0 1px var(--bk-text-3); }
.support-center-input::placeholder { color: var(--bk-text-3); }
.support-center-textarea { resize: vertical; line-height: 1.45; min-height: 72px; }

.support-center-sent { align-items: stretch; text-align: center; }
.support-center-sent h4 { margin: 0; font-size: 16px; }
.support-center-check {
  width: 48px; height: 48px; margin: 6px auto 0; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(52, 199, 89, 0.14); color: #1E9E4A; font-size: 24px; font-weight: 700;
}

.support-center-thread-wrap { gap: 10px; }
.support-center-thread { display: flex; flex-direction: column; gap: 10px; }
.support-center-msg { max-width: 88%; padding: 9px 12px; border-radius: 12px; font-size: 13px; line-height: 1.5; }
.support-center-msg.you { align-self: flex-end; background: var(--bk-primary, #6366f1); color: var(--bk-on-primary, #fff); border-bottom-right-radius: 4px; }
.support-center-msg.team { align-self: flex-start; background: var(--bk-input); box-shadow: inset 0 0 0 1px var(--bk-border); border-bottom-left-radius: 4px; }
.support-center-msg-who { font-size: 11px; font-weight: 600; opacity: 0.75; margin-bottom: 3px; }
.support-center-msg-body { white-space: pre-wrap; word-break: break-word; }
.support-center-waiting { align-self: center; font-size: 12px; color: var(--bk-text-3); text-align: center; padding: 4px 8px; }
.support-center-reply { display: flex; flex-direction: column; gap: 8px; padding-top: 6px; border-top: 1px solid var(--bk-border); }

/* The unread count on Support in the navbar menu, and the dot on the menu button. */
.navbar-menu-badge {
  margin-left: auto;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  box-sizing: border-box;
  border-radius: 9px;
  background: #EF4444;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
}
.icon-btn.has-unread { position: relative; }
.icon-btn.has-unread::after {
  content: '';
  position: absolute;
  top: 5px;
  right: 5px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #EF4444;
}

/* The screenshot and trail note in the bug report panel. */
.bug-report-attach {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--bk-r-control, 8px);
  background: var(--bk-input);
  box-shadow: inset 0 0 0 1px var(--bk-border);
  font-family: var(--font-ui);
  font-size: 12px;
  color: var(--bk-text-2);
}
.bug-report-attach img { width: 64px; height: 40px; object-fit: cover; border-radius: 4px; flex: 0 0 auto; box-shadow: inset 0 0 0 1px var(--bk-border); }
.bug-report-attach-ph { width: 64px; height: 40px; border-radius: 4px; flex: 0 0 auto; background: var(--bk-hover, rgba(0, 0, 0, 0.06)); }
.bug-report-status { margin: 0; font-family: var(--font-ui); font-size: 12.5px; line-height: 1.45; }
.bug-report-status.error { color: #DC2626; }
.dark-mode .bug-report-status.error { color: #FF6B6B; }
.bug-report-status.ok { color: var(--bk-text-2); }
.bug-report-send {
  height: 38px;
  border: none;
  border-radius: var(--bk-r-control, 8px);
  background: var(--bk-primary, #6366f1);
  color: var(--bk-on-primary, #fff);
  font-family: var(--font-ui);
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
}
.bug-report-send:disabled { opacity: 0.45; cursor: default; }

@media (max-width: 768px) {
  .support-center { width: calc(100vw - 16px); max-height: calc(var(--app-height, 100vh) - 16px); }
  .support-center-input { font-size: 16px; }
}

@media (prefers-reduced-motion: reduce) {
  .support-center { animation: none; }
}

/* Reply emails on or off, under the ticket list. */
.support-center-mail {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding-top: 12px;
  border-top: 1px solid var(--bk-border);
  color: var(--bk-text);
  font-size: 13px;
  line-height: 1.4;
  cursor: pointer;
}
.support-center-mail input { margin: 2px 0 0; flex-shrink: 0; cursor: pointer; }
.support-center-mail-to {
  display: block;
  color: var(--bk-text-2);
  font-size: 12px;
  word-break: break-all;
}
.setup-guide-root {
  position: fixed;
  inset: 0;
  z-index: 3000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  animation: setup-guide-in 0.22s ease-out both;
}
.setup-guide-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.setup-guide-card {
  position: relative;
  width: min(880px, 100%);
  max-height: calc(var(--app-height, 100vh) - 48px);
  overflow-y: auto;
  padding: 18px 20px 20px;
  border-radius: var(--bk-r-panel, 16px);
  background: var(--bk-elevated, #1c1d21);
  color: var(--bk-text, #f5f5f7);
  font-family: var(--font-ui);
  box-shadow: inset 0 0 0 1px var(--bk-border, rgba(255, 255, 255, 0.08)), 0 24px 60px rgba(0, 0, 0, 0.45);
}
.setup-guide-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 14px;
}
.setup-guide-title {
  margin: 0 0 4px;
  font-size: 17px;
  font-weight: 650;
}
.setup-guide-text {
  margin: 0;
  font-size: 13px;
  line-height: 1.45;
  color: var(--bk-text-2, rgba(245, 245, 247, 0.7));
}
.setup-guide-close {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--bk-text-2, rgba(245, 245, 247, 0.7));
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}
.setup-guide-close:hover { background: var(--bk-hover, rgba(255, 255, 255, 0.08)); color: var(--bk-text, #fff); }
.setup-guide-video {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: 12px;
  overflow: hidden;
  background: #000;
}
.setup-guide-video iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

@media (max-width: 768px) {
  .setup-guide-root { padding: 12px; }
  .setup-guide-card { padding: 14px 14px 16px; }
}

@keyframes setup-guide-in { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .setup-guide-root { animation: none; } }
/* Chartify Script: the editor panel, the script settings window and the bits of the badge
   only scripts have. Everything is prefixed cse- / script- so nothing here can reach a rule
   anywhere else in the app. Colours come from the same tokens as the other panels; the
   purple is Chartify's own (--brand), used only for the AI. */

.cse-panel {
  --cse-accent: var(--brand, #4C29E9);
  --cse-accent-rgb: var(--brand-rgb, 76, 41, 233);
  --cse-accent-text: var(--brand, #4C29E9);
  --cse-code-bg: #FCFCFC;
  --cse-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  position: fixed;
  top: 60px;
  right: 10px;
  bottom: 46px;
  width: min(620px, 50vw);
  min-width: 380px;
  z-index: 9000;
  display: flex;
  flex-direction: column;
  background: var(--bk-elevated);
  color: var(--bk-text);
  border-radius: var(--bk-r-panel, 16px);
  box-shadow: inset 0 0 0 1px var(--bk-border), var(--bk-lift, 0 20px 50px rgba(0, 0, 0, 0.25));
  font-family: var(--font-ui);
  overflow: hidden;
  text-align: left;
  container: cse / inline-size;
}
.dark-mode .cse-panel, .cse-panel.dark-mode {
  --cse-accent-text: #A897FF;
  --cse-code-bg: #0F1012;
}
.cse-panel *, .cse-panel *::before, .cse-panel *::after { box-sizing: border-box; }
.cse-panel button { font-family: inherit; }
.cse-panel * { scrollbar-width: thin; scrollbar-color: var(--bk-border-strong) transparent; }
.cse-panel ::-webkit-scrollbar { width: 10px; height: 10px; }
.cse-panel ::-webkit-scrollbar-thumb { border-radius: 10px; border: 3px solid transparent; background: var(--bk-border-strong) padding-box; }
.cse-panel ::-webkit-scrollbar-track, .cse-panel ::-webkit-scrollbar-corner { background: transparent; }
.cse-panel kbd {
  margin-left: 6px; padding: 1px 5px; border-radius: 5px; font: inherit; font-size: 10.5px; font-weight: 600;
  color: var(--bk-text-3); box-shadow: inset 0 0 0 1px var(--bk-border);
}

/* ---------- head: where you are, and the tools ---------- */
.cse-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 50px;
  padding: 8px 8px 8px 10px;
  border-bottom: 1px solid var(--bk-border);
}
.cse-crumbs { display: flex; align-items: center; gap: 2px; min-width: 0; flex: 1 1 auto; }
.cse-crumb {
  display: inline-flex; align-items: center; gap: 7px; min-width: 0; height: 32px; padding: 0 9px;
  border: none; border-radius: 9px; background: transparent; color: var(--bk-text-2);
  font-size: 13px; font-weight: 550; cursor: pointer; white-space: nowrap;
}
.cse-crumb:hover, .cse-crumb.active { background: var(--bk-hover); color: var(--bk-text); }
.cse-crumb.current { color: var(--bk-text); font-weight: 650; font-size: 14px; flex: 0 1 auto; }
.cse-crumb-sep { flex: 0 0 auto; color: var(--bk-text-3); }
.cse-name { overflow: hidden; text-overflow: ellipsis; }
.cse-dirty { flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%; background: var(--bk-warn); }

.cse-tools { display: flex; align-items: center; gap: 2px; flex: 0 0 auto; }
.cse-tool {
  display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 10px;
  border: none; border-radius: 9px; background: transparent; color: var(--bk-text-2);
  font-size: 12.5px; font-weight: 600; cursor: pointer; white-space: nowrap;
  transition: background 0.12s ease, color 0.12s ease;
}
.cse-tool:hover { background: var(--bk-hover); color: var(--bk-text); }
.cse-tool.active { background: var(--bk-active); color: var(--bk-text); }
.cse-tool.ai { color: var(--cse-accent-text); }
.cse-tool.ai:hover { background: rgba(var(--cse-accent-rgb), 0.08); }
.cse-tool.ai.active { background: rgba(var(--cse-accent-rgb), 0.16); color: var(--cse-accent-text); }
.cse-tools-sep { width: 1px; height: 18px; margin: 0 4px; background: var(--bk-border); }
.cse-icon-btn {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 32px; height: 32px; border: none; border-radius: 9px; background: transparent;
  color: var(--bk-text-2); cursor: pointer;
}
.cse-icon-btn:hover { background: var(--bk-hover); color: var(--bk-text); }
.cse-icon-btn.small { width: 26px; height: 26px; border-radius: 7px; }
@container cse (max-width: 470px) {
  .cse-tool-label, .cse-crumb-text { display: none; }
  .cse-tool { padding: 0 9px; }
}

/* ---------- buttons ---------- */
.cse-primary, .cse-ghost, .cse-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 32px; padding: 0 13px; border: none; border-radius: 9px;
  font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer; white-space: nowrap;
  transition: background 0.12s ease, opacity 0.12s ease, color 0.12s ease;
}
.cse-primary { background: var(--bk-primary); color: var(--bk-on-primary); }
.cse-primary:hover:not(:disabled) { opacity: 0.88; }
.cse-primary.done { background: var(--bk-card); color: var(--bk-text); box-shadow: inset 0 0 0 1px var(--bk-border); }
.cse-ghost, .cse-btn { background: transparent; color: var(--bk-text-2); box-shadow: inset 0 0 0 1px var(--bk-border); }
.cse-ghost:hover:not(:disabled), .cse-ghost.active, .cse-btn:hover:not(:disabled), .cse-btn.active { color: var(--bk-text); background: var(--bk-hover); }
.cse-ghost.accent { color: var(--cse-accent-text); box-shadow: inset 0 0 0 1px rgba(var(--cse-accent-rgb), 0.35); }
.cse-ghost.accent:hover:not(:disabled) { background: rgba(var(--cse-accent-rgb), 0.1); color: var(--cse-accent-text); }
.cse-primary.small, .cse-ghost.small { height: 28px; padding: 0 11px; font-size: 12px; border-radius: 8px; }
.cse-primary:disabled, .cse-ghost:disabled, .cse-btn:disabled { opacity: 0.45; cursor: default; }
.cse-text-btn {
  display: inline-flex; align-items: center; gap: 5px; height: 26px; padding: 0 8px; border: none; border-radius: 7px;
  background: transparent; color: var(--bk-text-2); font-size: 12px; font-weight: 600; cursor: pointer;
}
.cse-text-btn:hover { background: var(--bk-hover); color: var(--bk-text); }
.cse-link { border: none; background: transparent; padding: 0 0 0 6px; font: inherit; font-weight: 650; color: var(--cse-accent-text); cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
.cse-pill {
  display: inline-flex; align-items: center; gap: 4px; flex: 0 0 auto; height: 21px; padding: 0 8px; border-radius: 999px;
  font-size: 11px; font-weight: 650; color: var(--bk-text-2); background: var(--bk-card);
}
.cse-pill.good { color: var(--bk-pos); background: color-mix(in srgb, var(--bk-pos) 12%, transparent); }
.cse-pill.bad { color: var(--bk-neg); background: color-mix(in srgb, var(--bk-neg) 12%, transparent); }

.cse-plan {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 14px; font-size: 12.5px; color: var(--bk-text-2);
  background: var(--bk-card); border-bottom: 1px solid var(--bk-border);
}

/* ---------- body: the code, and a tool panel beside it (wide) or under it ---------- */
.cse-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.cse-main { flex: 1 1 auto; min-height: 0; min-width: 0; display: flex; }
.cse-body.has-side .cse-main { flex: 1 1 40%; min-height: 120px; }
.cse-side {
  flex: 1 1 60%;
  min-height: 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--bk-elevated);
  border-top: 1px solid var(--bk-border);
  font-size: 13px;
}
@container cse (min-width: 860px) {
  .cse-body { flex-direction: row; }
  .cse-body.has-side .cse-main { flex: 1 1 auto; min-height: 0; }
  .cse-side { flex: 0 0 380px; border-top: none; border-left: 1px solid var(--bk-border); }
}
.cse-side-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 42px; padding: 6px 8px 6px 14px; border-bottom: 1px solid var(--bk-border); }
.cse-side-title { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 650; color: var(--bk-text); }
.cse-side-title svg { color: var(--bk-text-2); }
.cse-side-title.accent svg { color: var(--cse-accent-text); }
.cse-side-tools { display: inline-flex; align-items: center; gap: 2px; }
.cse-side-text { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--bk-text-2); }
.cse-side-foot { padding: 8px 14px 10px; font-size: 11px; line-height: 1.4; color: var(--bk-text-3); border-top: 1px solid var(--bk-border); }
.cse-notice { padding: 9px 12px; border-radius: 10px; font-size: 12.5px; line-height: 1.45; background: var(--bk-card); }
.cse-notice.bad { color: var(--bk-neg); }

/* What testing the AI's code on the chart found, under its code card: green when it passed,
   amber when it could not be confirmed. */
.cse-test {
  margin-top: 8px; padding: 9px 12px; border-radius: 10px; font-size: 12.5px; line-height: 1.45;
  background: color-mix(in srgb, var(--bk-warn) 9%, var(--bk-card));
  border: 1px solid color-mix(in srgb, var(--bk-warn) 28%, transparent);
}
.cse-test.pass {
  background: color-mix(in srgb, var(--bk-pos) 9%, var(--bk-card));
  border-color: color-mix(in srgb, var(--bk-pos) 28%, transparent);
}
.cse-test-head { display: flex; align-items: center; gap: 7px; font-weight: 600; color: var(--bk-text); }
.cse-test-mark {
  display: inline-flex; align-items: center; justify-content: center; width: 17px; height: 17px;
  border-radius: 50%; font-size: 11px; font-weight: 800; color: #fff; background: var(--bk-warn); flex: 0 0 auto;
}
.cse-test.pass .cse-test-mark { background: var(--bk-pos); }
.cse-test-goal { margin-top: 4px; color: var(--bk-text-2); }
.cse-test-steps { margin: 4px 0 0; padding-left: 18px; color: var(--bk-text-2); }
.cse-test-steps li { margin-top: 2px; }
.cse-test-steps li.pass { color: var(--bk-text); }

/* The mistake under the code, in full, with a way to the line and to a fix. */
.cse-main { flex-direction: column; }
.cse-problem {
  display: flex; align-items: center; gap: 8px; flex: 0 0 auto; padding: 7px 8px 7px 12px;
  border-top: 1px solid color-mix(in srgb, var(--bk-neg) 30%, var(--bk-border));
  background: color-mix(in srgb, var(--bk-neg) 8%, var(--bk-elevated)); color: var(--bk-neg);
}
.cse-problem > svg { flex: 0 0 auto; }
.cse-problem-text {
  flex: 1 1 auto; min-width: 0; padding: 2px 0; border: none; background: transparent; color: inherit; text-align: left;
  font-size: 12.5px; line-height: 1.4; cursor: pointer; overflow-wrap: anywhere;
}
.cse-problem-text:hover { text-decoration: underline; text-underline-offset: 2px; }
.cse-problem .cse-ghost { flex: 0 0 auto; }

/* ---------- the code editor ---------- */
.cse-editor {
  --cse-size: 13px;
  --cse-line: 21px;
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  display: flex;
  background: var(--cse-code-bg);
  font-family: var(--cse-mono);
  font-size: var(--cse-size);
  line-height: var(--cse-line);
}
.cse-gutter {
  flex: 0 0 auto;
  min-width: 46px;
  padding: 12px 0;
  text-align: right;
  color: var(--bk-text-3);
  opacity: 0.75;
  user-select: none;
  overflow: hidden;
}
.cse-num-line { height: var(--cse-line); padding: 0 12px 0 8px; font-size: 11.5px; }
.cse-num-line.current { color: var(--bk-text); }
.cse-num-line.error { color: var(--bk-neg); font-weight: 700; }
.cse-gutter-pad { height: 48px; }
.cse-code { position: relative; flex: 1 1 auto; min-width: 0; overflow: hidden; }
.cse-layer, .cse-area {
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 12px 14px 12px 4px;
  font: inherit;
  line-height: inherit;
  letter-spacing: 0;
  tab-size: 4;
  white-space: pre;
  overflow: auto;
  border: none;
}
.cse-layer { pointer-events: none; color: var(--bk-text); overflow: hidden; }
.cse-line { min-height: var(--cse-line); margin: 0 -14px 0 -4px; padding: 0 14px 0 4px; border-radius: 0; }
.cse-line.current { background: var(--bk-hover); }
.cse-line.error { background: color-mix(in srgb, var(--bk-neg) 13%, transparent); box-shadow: inset 2px 0 0 var(--bk-neg); }
.cse-area {
  resize: none;
  outline: none;
  background: transparent;
  color: transparent;
  caret-color: var(--bk-text);
  -webkit-text-fill-color: transparent;
}
.cse-area::selection { background: rgba(var(--brand-rgb, 76, 41, 233), 0.3); -webkit-text-fill-color: transparent; }
.cse-cm { color: var(--bk-text-3); font-style: italic; }
.cse-str { color: #16A34A; }
.cse-num { color: #D97706; }
.cse-hex { color: #D97706; }
.cse-hex::before { content: ''; display: inline-block; width: 9px; height: 9px; margin-right: 3px; border-radius: 2px; background: var(--cse-swatch); box-shadow: 0 0 0 1px var(--bk-border); vertical-align: 0; }
.cse-kw { color: #C026D3; font-weight: 600; }
.cse-out { color: #2563EB; font-weight: 600; }
.cse-fn { color: #0891B2; }
.cse-var { color: #EA580C; }
.cse-col { color: #65A30D; }
.dark-mode .cse-str { color: #4ADE80; }
.dark-mode .cse-num, .dark-mode .cse-hex { color: #FBBF24; }
.dark-mode .cse-kw { color: #E879F9; }
.dark-mode .cse-out { color: #60A5FA; }
.dark-mode .cse-fn { color: #22D3EE; }
.dark-mode .cse-var { color: #FB923C; }
.dark-mode .cse-col { color: #A3E635; }

/* ---------- a card of code (AI answers, converted scripts) ---------- */
.cse-card { border-radius: 12px; overflow: hidden; background: var(--cse-code-bg); box-shadow: inset 0 0 0 1px var(--bk-border); }
.cse-card-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 5px 6px 5px 12px; border-bottom: 1px solid var(--bk-border); }
.cse-card-label { font-size: 11.5px; font-weight: 650; color: var(--bk-text-2); white-space: nowrap; }
.cse-card-meta { font-weight: 500; color: var(--bk-text-3); }
.cse-card-tools { display: inline-flex; align-items: center; gap: 6px; }
.cse-card-code { margin: 0; padding: 8px 0; overflow: auto; font-family: var(--cse-mono); font-size: 11.5px; line-height: 1.6; color: var(--bk-text); }
.cse-card-line { display: flex; white-space: pre; padding-right: 12px; }
.cse-card-line.error { background: color-mix(in srgb, var(--bk-neg) 13%, transparent); }
.cse-card-num { flex: 0 0 34px; padding-right: 10px; text-align: right; color: var(--bk-text-3); user-select: none; opacity: 0.75; }
.cse-card-error { padding: 7px 12px; font-size: 12px; color: var(--bk-neg); border-top: 1px solid var(--bk-border); }
.cse-card-actions { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px; border-top: 1px solid var(--bk-border); background: var(--bk-elevated); }

/* ---------- Docs ---------- */
.cse-search {
  display: flex; align-items: center; gap: 8px; margin: 10px 12px 4px; padding: 0 10px; height: 34px;
  border-radius: 10px; background: var(--bk-input); box-shadow: inset 0 0 0 1px var(--bk-border); color: var(--bk-text-3);
}
.cse-search:focus-within { box-shadow: inset 0 0 0 1px rgba(var(--cse-accent-rgb), 0.55), 0 0 0 3px rgba(var(--cse-accent-rgb), 0.12); }
.cse-search input, .cse-search input:focus { flex: 1 1 auto; min-width: 0; height: 100%; padding: 0; border: none; outline: none; box-shadow: none; background: transparent; color: var(--bk-text); font: inherit; font-size: 13px; }
.cse-ref-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 4px 14px 20px; font-size: 12px; }
.cse-ref-title { margin: 14px 0 8px; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--bk-text-3); }
.cse-ref-item { display: flex; flex-direction: column; gap: 3px; padding: 7px 0; border-bottom: 1px solid var(--bk-divider); }
.cse-ref-item:last-child { border-bottom: none; }
.cse-ref-item code { font-family: var(--cse-mono); font-size: 11.5px; color: var(--bk-text-2); word-break: break-word; }
.cse-ref-item code b { color: var(--bk-text); font-weight: 650; }
.cse-ref-item span { color: var(--bk-text-2); line-height: 1.45; }
.cse-ref-none { padding: 20px 0; color: var(--bk-text-3); text-align: center; }

/* ---------- my scripts ---------- */
.cse-list { flex: 1 1 auto; overflow-y: auto; padding: 14px 12px 20px; }
.cse-list-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 0 4px 12px; }
.cse-list-title { font-size: 15px; font-weight: 650; }
.cse-list-sub { margin-top: 2px; font-size: 12px; color: var(--bk-text-3); }
.cse-empty { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 40px 16px; text-align: center; }
.cse-empty-icon { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 12px; background: var(--bk-card); color: var(--bk-text-2); margin-bottom: 4px; }
.cse-empty-title { font-size: 14px; font-weight: 650; }
.cse-empty-text { font-size: 12.5px; color: var(--bk-text-2); }
.cse-row { display: flex; align-items: center; gap: 2px; padding-right: 4px; border-radius: 12px; }
.cse-row + .cse-row { margin-top: 2px; }
.cse-row:hover, .cse-row.active { background: var(--bk-hover); }
.cse-row-main { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 11px; padding: 9px 10px; border: none; background: transparent; text-align: left; font: inherit; color: var(--bk-text); cursor: pointer; }
.cse-row-icon { display: grid; place-items: center; flex: 0 0 auto; width: 32px; height: 32px; border-radius: 9px; background: var(--bk-card); color: var(--bk-text-2); }
.cse-row.active .cse-row-icon { color: var(--cse-accent-text); background: rgba(var(--cse-accent-rgb), 0.14); }
.cse-row-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.cse-row-name { font-size: 13.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cse-row-meta { font-size: 11.5px; color: var(--bk-text-3); }
.cse-row-delete { display: grid; place-items: center; flex: 0 0 auto; width: 32px; height: 32px; border: none; background: transparent; cursor: pointer; color: var(--bk-text-3); border-radius: 8px; opacity: 0; }
.cse-row:hover .cse-row-delete, .cse-row-delete:focus-visible { opacity: 1; }
.cse-row-delete:hover { color: var(--bk-neg); background: var(--bk-active); }
@media (hover: none) { .cse-row-delete { opacity: 1; } }

/* ---------- foot: the state of the script, and what to do with it ---------- */
.cse-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 50px;
  padding: 8px 10px 8px 12px;
  border-top: 1px solid var(--bk-border);
}
.cse-state {
  display: flex; align-items: center; gap: 7px; min-width: 0; flex: 1 1 auto; height: 30px; padding: 0 9px;
  border: none; border-radius: 8px; background: transparent; font: inherit; font-size: 12.5px; text-align: left; color: var(--bk-text-2);
}
.cse-state span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cse-state svg { flex: 0 0 auto; }
.cse-state.good svg { color: var(--bk-pos); }
.cse-state.info { color: var(--bk-text); }
.cse-state.info svg { color: var(--bk-pos); }
.cse-state.bad { color: var(--bk-neg); background: color-mix(in srgb, var(--bk-neg) 9%, transparent); }
button.cse-state { cursor: pointer; }
button.cse-state:hover { background: color-mix(in srgb, var(--bk-neg) 14%, transparent); }
.cse-foot-actions { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
@container cse (max-width: 520px) {
  .cse-foot kbd { display: none; }
}

/* ---------- script settings ---------- */
.script-settings-overlay { z-index: 10040; }
.script-settings {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 10050;
  width: 380px;
  max-width: calc(100vw - 24px);
  max-height: calc(var(--app-height, 100vh) - 40px);
  display: flex;
  flex-direction: column;
  background: var(--bk-elevated);
  color: var(--bk-text);
  border-radius: var(--bk-r-panel, 16px);
  box-shadow: inset 0 0 0 1px var(--bk-border), var(--bk-lift, 0 20px 50px rgba(0, 0, 0, 0.25));
  font-family: var(--font-ui);
  text-align: left;
}
.script-settings-head { display: flex; align-items: center; justify-content: space-between; padding: 14px 16px 10px; border-bottom: 1px solid var(--bk-border); }
.script-settings-head h3 { margin: 0; font-size: 15px; font-weight: 650; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.script-settings-body { padding: 10px 16px; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; }
.script-settings-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: 13px; }
.script-settings-row span { color: var(--bk-text-2); }
.script-settings-row input[type="number"], .script-settings-row input[type="text"], .script-settings-row select {
  width: 150px; height: 32px; padding: 0 10px; border: none; border-radius: 9px;
  background: var(--bk-input); color: var(--bk-text); box-shadow: inset 0 0 0 1px var(--bk-border); font: inherit; font-size: 13px;
}
.script-settings-row input[type="color"] { width: 44px; height: 30px; border: none; background: transparent; padding: 0; cursor: pointer; }
.script-settings-row input[type="checkbox"] { width: 18px; height: 18px; }
.script-settings-foot { display: flex; justify-content: flex-end; gap: 8px; padding: 10px 16px 14px; border-top: 1px solid var(--bk-border); }

/* ---------- badges ---------- */
.script-badge-tag { margin-left: 6px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--bk-warn); }
.script-badge-error { color: var(--bk-neg) !important; }

/* ---------- phone ---------- */
@media (max-width: 768px), (max-height: 500px) and (orientation: landscape) {
  .cse-panel {
    top: 0; left: 0; right: 0; bottom: 0;
    width: 100vw; min-width: 0;
    height: var(--app-height, 100vh);
    border-radius: 0;
    z-index: 10030;
    padding-top: env(safe-area-inset-top);
  }
  /* A tool takes the whole body on a phone: the code is one tap away (close the tool). */
  .cse-body.has-side .cse-main { display: none; }
  .cse-side { flex: 1 1 auto; border-top: none; }
  .cse-editor { --cse-size: 14px; }
  .cse-area, .cse-layer, .cse-gutter { font-size: 16px; } /* below 16px iOS zooms the page on focus */
  .cse-composer textarea, .cse-paste-input, .cse-search input { font-size: 16px; }
  .cse-foot { padding-bottom: calc(8px + env(safe-area-inset-bottom)); }
  .cse-foot .cse-ghost:not(.accent) { padding: 0 10px; }
}

/* ---------- the Scripts tab of the Indicators window ---------- */
.scripts-tab-intro {
  margin: 2px 16px 12px;
  padding: 14px 16px;
  border-radius: 12px;
  background: var(--bk-card);
}
.scripts-tab-title { font-size: 13.5px; font-weight: 650; color: var(--bk-text); margin-bottom: 4px; }
.scripts-tab-text { font-size: 12.5px; line-height: 1.5; color: var(--bk-text-2); margin-bottom: 10px; }
.scripts-tab-new {
  height: 32px; padding: 0 12px; border: none; border-radius: 9px; cursor: pointer;
  background: var(--bk-primary); color: var(--bk-on-primary); font: inherit; font-size: 12.5px; font-weight: 600;
}
.scripts-tab-new:hover { opacity: 0.88; }
.scripts-tab-open { border: none; background: transparent; padding: 0; text-align: left; font: inherit; color: inherit; cursor: pointer; min-width: 0; }
.scripts-tab-empty { padding: 10px 24px; font-size: 12.5px; color: var(--bk-text-3); }
.scripts-tab-error { padding: 8px 24px; font-size: 12.5px; color: var(--bk-neg); }
.scripts-tab-open .indicator-item-name, .scripts-tab-open .indicator-item-desc { display: block; }

/* ---------- docked beside the chart (computer) ---------- */
.cse-dock {
  position: relative;
  flex: 0 0 auto;
  min-width: 360px;
  max-width: calc(100% - 320px);
  height: 100%;
  display: flex;
  background: var(--bk-shell);
  box-shadow: inset 1px 0 0 var(--bk-border);
}
.cse-dock.dark-mode { background: #151619; }
.cse-dock .cse-panel {
  position: relative;
  inset: auto;
  width: 100%;
  min-width: 0;
  height: 100%;
  z-index: auto;
  border-radius: 0;
  box-shadow: none;
}

/* The grab strip on the dock's left edge, like the assistant's. */
.cse-resizer {
  position: absolute;
  left: -6px;
  top: 0;
  bottom: 0;
  width: 12px;
  cursor: col-resize;
  z-index: 3;
  touch-action: none;
}
.cse-resizer::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 3px;
  height: 44px;
  border-radius: 2px;
  background: rgba(var(--brand-rgb, 76, 41, 233), 0.45);
  transition: background 0.15s ease, height 0.15s ease;
}
.cse-resizer:hover::after, .cse-resizer.dragging::after { background: var(--brand, #4C29E9); height: 72px; }
/* While dragging, the chart and the editor must not grab the pointer or select text. */
.cse-dock.resizing, .cse-dock.resizing * { user-select: none; }

.script-settings-group { margin: 8px 0 2px; font-size: 11px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--bk-text-3); }
.script-settings-tip { color: var(--bk-text-3); cursor: help; }

/* ---------- Script AI ---------- */
.cse-ai-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 14px; }
.cse-ai-welcome { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 8px 0 4px; }
.cse-ai-hero { display: grid; place-items: center; width: 42px; height: 42px; border-radius: 12px; color: #FFFFFF; background: var(--cse-accent); box-shadow: 0 6px 18px rgba(var(--cse-accent-rgb), 0.35); }
.cse-ai-hero-title { margin-top: 12px; font-size: 15px; font-weight: 650; letter-spacing: -0.01em; }
.cse-ai-hero-text { max-width: 300px; margin-top: 4px; font-size: 12.5px; line-height: 1.5; color: var(--bk-text-2); }
.cse-starters { display: flex; flex-direction: column; gap: 7px; width: 100%; margin-top: 16px; }
.cse-starter {
  display: flex; align-items: center; gap: 11px; width: 100%; padding: 9px 11px;
  border-radius: 12px; border: 1px solid var(--bk-border); background: var(--bk-panel); color: var(--bk-text);
  text-align: left; cursor: pointer; transition: border-color 0.15s ease, background 0.15s ease;
}
.dark-mode .cse-starter { background: #1C1D20; border-color: #2A2C31; }
.cse-starter-icon { display: grid; place-items: center; flex: 0 0 auto; width: 32px; height: 32px; border-radius: 10px; background: rgba(var(--cse-accent-rgb), 0.1); color: var(--cse-accent-text); }
.dark-mode .cse-starter-icon { background: rgba(var(--cse-accent-rgb), 0.38); color: #FFFFFF; }
.cse-starter-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.cse-starter-label { font-size: 13px; font-weight: 600; }
.cse-starter-hint { font-size: 11.5px; line-height: 1.35; color: var(--bk-text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cse-starter-go { flex: 0 0 auto; color: var(--bk-text-3); opacity: 0; transform: translateX(-3px); transition: opacity 0.15s ease, transform 0.15s ease; }
.cse-starter:hover:not(:disabled) { border-color: rgba(var(--cse-accent-rgb), 0.5); background: rgba(var(--cse-accent-rgb), 0.06); }
.cse-starter:hover:not(:disabled) .cse-starter-go { opacity: 1; transform: none; color: var(--cse-accent-text); }
.cse-starter:disabled { opacity: 0.5; cursor: default; }
@media (hover: none) { .cse-starter-go { opacity: 1; transform: none; } }

.cse-msg { display: flex; flex-direction: column; gap: 10px; }
.cse-msg.user { align-items: flex-end; }
.cse-bubble {
  max-width: 88%; padding: 8px 12px; border-radius: 14px 14px 4px 14px;
  background: var(--cse-accent); color: #FFFFFF; font-size: 13px; line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere;
}
.cse-rich { font-size: 13px; line-height: 1.6; color: var(--bk-text); overflow-wrap: anywhere; }
.cse-rich p { margin: 0 0 8px; }
.cse-rich p:last-child { margin-bottom: 0; }
.cse-rich .cse-rich-h { font-weight: 650; margin-top: 4px; }
.cse-rich ul, .cse-rich ol { margin: 0 0 8px; padding-left: 20px; }
.cse-rich li { margin: 2px 0; }
.cse-rich strong { font-weight: 650; }
.cse-rich code { font-family: var(--cse-mono); font-size: 11.5px; padding: 1px 5px; border-radius: 5px; background: var(--bk-card); }
.cse-thinking { display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--bk-text-3); }
.cse-thinking-mark { display: inline-grid; place-items: center; color: var(--cse-accent-text); animation: cse-pulse 1.4s ease-in-out infinite; }
@keyframes cse-pulse { 0%, 100% { opacity: 0.35; transform: scale(0.9); } 50% { opacity: 1; transform: scale(1.05); } }
@media (prefers-reduced-motion: reduce) { .cse-thinking-mark { animation: none; } }

.cse-composer-wrap { padding: 8px 12px 10px; border-top: 1px solid var(--bk-border); }
.cse-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.cse-chip {
  display: inline-flex; align-items: center; gap: 5px; height: 26px; padding: 0 10px; border: none; border-radius: 999px;
  background: rgba(var(--cse-accent-rgb), 0.1); color: var(--cse-accent-text); font-size: 12px; font-weight: 600; cursor: pointer;
}
.cse-chip:hover { background: rgba(var(--cse-accent-rgb), 0.18); }
.cse-composer {
  display: flex; align-items: flex-end; gap: 6px; padding: 6px 6px 6px 12px; border-radius: 14px;
  border: 1px solid var(--bk-border); background: var(--bk-input);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.cse-composer:focus-within { border-color: rgba(var(--cse-accent-rgb), 0.55); box-shadow: 0 0 0 3px rgba(var(--cse-accent-rgb), 0.12); }
.cse-composer textarea, .cse-composer textarea:focus {
  box-shadow: none;
  flex: 1 1 auto; min-width: 0; max-height: 150px; padding: 6px 0; border: none; outline: none; resize: none;
  background: transparent; color: var(--bk-text); font: inherit; font-size: 13px; line-height: 1.5;
}
.cse-composer textarea::placeholder { color: var(--bk-text-3); }
.cse-composer-tools { display: flex; align-items: center; gap: 4px; flex: 0 0 auto; }
.cse-send {
  display: grid; place-items: center; width: 30px; height: 30px; border: none; border-radius: 9px;
  background: var(--cse-accent); color: #FFFFFF; cursor: pointer; transition: opacity 0.12s ease;
}
.cse-send:hover:not(:disabled) { background: var(--brand-hover, #3D20DC); }
.cse-send:disabled { opacity: 0.35; cursor: default; }
.cse-composer-foot { display: flex; justify-content: space-between; gap: 10px; margin-top: 6px; padding: 0 4px; font-size: 10.5px; color: var(--bk-text-3); }
.cse-composer-foot span:last-child { text-align: right; }
@container cse (max-width: 520px) { .cse-composer-foot span:last-child { display: none; } }

.cse-mode { position: relative; }
.cse-mode-btn {
  display: inline-flex; align-items: center; gap: 5px; height: 30px; padding: 0 8px; border: none; border-radius: 8px;
  background: transparent; color: var(--bk-text-2); font-size: 12px; font-weight: 600; cursor: pointer;
}
.cse-mode-btn:hover:not(:disabled), .cse-mode-btn.open { background: var(--bk-hover); color: var(--bk-text); }
.cse-mode-btn:disabled { opacity: 0.5; cursor: default; }
.cse-mode-menu {
  position: absolute; right: 0; bottom: calc(100% + 8px); z-index: 5; width: 220px; padding: 5px;
  border-radius: 12px; background: var(--bk-elevated); box-shadow: inset 0 0 0 1px var(--bk-border), var(--bk-lift, 0 10px 28px rgba(0, 0, 0, 0.3));
}
.cse-mode-option { display: flex; flex-direction: column; gap: 1px; width: 100%; padding: 7px 9px; border: none; border-radius: 8px; background: transparent; color: var(--bk-text); text-align: left; cursor: pointer; }
.cse-mode-option:hover { background: var(--bk-hover); }
.cse-mode-option.selected { background: rgba(var(--cse-accent-rgb), 0.12); }
.cse-mode-option.locked { opacity: 0.6; }
.cse-mode-label { display: flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; }
.cse-mode-blurb { font-size: 11px; color: var(--bk-text-3); }
.cse-lock { font-size: 10px; font-weight: 700; color: var(--bk-warn); }

/* ---------- Convert from Pine ---------- */
.cse-pine-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 12px; }
.cse-paste { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 220px; border-radius: 12px; overflow: hidden; background: var(--cse-code-bg); box-shadow: inset 0 0 0 1px var(--bk-border); }
.cse-paste:focus-within { box-shadow: inset 0 0 0 1px rgba(var(--cse-accent-rgb), 0.55), 0 0 0 3px rgba(var(--cse-accent-rgb), 0.12); }
.cse-paste-input, .cse-paste-input:focus {
  box-shadow: none;
  flex: 1 1 auto; min-height: 180px; padding: 10px 12px; border: none; outline: none; resize: none; background: transparent; color: var(--bk-text);
  font-family: var(--cse-mono); font-size: 11.5px; line-height: 1.6; white-space: pre; overflow: auto;
}
.cse-paste-input::placeholder { color: var(--bk-text-3); }
.cse-paste-bar { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 7px 7px 7px 12px; border-top: 1px solid var(--bk-border); background: var(--bk-elevated); font-size: 11.5px; color: var(--bk-text-3); }
.cse-result { display: flex; align-items: flex-start; gap: 10px; padding: 11px 12px; border-radius: 12px; background: var(--bk-card); }
.cse-result-icon { display: grid; place-items: center; flex: 0 0 auto; width: 28px; height: 28px; border-radius: 8px; }
.cse-result.good .cse-result-icon { color: var(--bk-pos); background: color-mix(in srgb, var(--bk-pos) 15%, transparent); }
.cse-result.warn .cse-result-icon { color: var(--bk-warn); background: color-mix(in srgb, var(--bk-warn) 15%, transparent); }
.cse-result.bad .cse-result-icon { color: var(--bk-neg); background: color-mix(in srgb, var(--bk-neg) 15%, transparent); }
.cse-result-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cse-result-title { font-size: 13px; font-weight: 650; }
.cse-result-sub { font-size: 12px; line-height: 1.45; color: var(--bk-text-2); overflow-wrap: anywhere; }
.cse-notes { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; border-radius: 12px; box-shadow: inset 0 0 0 1px var(--bk-border); overflow: hidden; }
.cse-notes li { display: flex; align-items: baseline; gap: 10px; padding: 7px 12px; font-size: 12px; line-height: 1.45; color: var(--bk-text-2); }
.cse-notes li + li { border-top: 1px solid var(--bk-divider); }
.cse-note-line { flex: 0 0 auto; min-width: 34px; font-family: var(--cse-mono); font-size: 11px; font-weight: 600; color: var(--bk-text-3); }

/* ---------- publishing (editor side panel) ---------- */
.cse-publish-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 10px; }
.cse-publish-text { font-size: 12.5px; line-height: 1.5; color: var(--bk-text-2); }
.cse-publish-state { padding: 10px 12px; border-radius: 10px; background: var(--bk-card); font-size: 12.5px; line-height: 1.5; color: var(--bk-text); box-shadow: inset 3px 0 0 var(--bk-border); }
.cse-publish-state.good { box-shadow: inset 3px 0 0 var(--bk-pos); }
.cse-publish-state.bad { box-shadow: inset 3px 0 0 var(--bk-neg); }
.cse-publish-sub { margin-top: 3px; color: var(--bk-text-2); white-space: pre-wrap; overflow-wrap: anywhere; }
.cse-publish-state .cse-link { margin-top: 4px; padding: 0; }
.cse-publish-form { display: flex; flex-direction: column; gap: 10px; }
.cse-publish-form label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; font-weight: 600; color: var(--bk-text-2); }
.cse-publish-form input:not([type="checkbox"]), .cse-publish-form textarea {
  padding: 8px 10px; border: none; border-radius: 9px; resize: vertical;
  background: var(--bk-input); color: var(--bk-text); box-shadow: inset 0 0 0 1px var(--bk-border);
  font: inherit; font-size: 13px; font-weight: 400;
}
.cse-publish-count { align-self: flex-end; font-weight: 400; color: var(--bk-text-3); }
.cse-publish-form .cse-publish-agree { flex-direction: row; align-items: flex-start; gap: 8px; font-weight: 400; line-height: 1.45; color: var(--bk-text-2); }
.cse-publish-agree input { margin-top: 2px; flex-shrink: 0; }
.cse-publish-buttons { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; }
.cse-publish-warn { padding: 8px 10px; border-radius: 9px; font-size: 12px; line-height: 1.45; color: var(--bk-neg); background: var(--bk-card); }
.cse-publish-done { padding: 8px 10px; border-radius: 9px; font-size: 12px; line-height: 1.45; color: var(--bk-pos); background: var(--bk-card); }
@media (max-width: 768px) {
  .cse-publish-form input:not([type="checkbox"]), .cse-publish-form textarea { font-size: 16px; }
}

/* ---------- the Community tab of the Indicators window ---------- */
.community-tools { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.community-search {
  flex: 1 1 180px; min-width: 0; height: 32px; padding: 0 10px; border: none; border-radius: 9px;
  background: var(--bk-input); color: var(--bk-text); box-shadow: inset 0 0 0 1px var(--bk-border); font: inherit; font-size: 12.5px;
}
.community-sort { display: inline-flex; padding: 2px; border-radius: 9px; background: var(--bk-input); box-shadow: inset 0 0 0 1px var(--bk-border); }
.community-sort button { height: 28px; padding: 0 10px; border: none; border-radius: 7px; background: transparent; color: var(--bk-text-2); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; }
.community-sort button.active { background: var(--bk-hover); color: var(--bk-text); }
.community-detail { margin: 0 16px 10px; padding: 12px 14px; border-radius: 12px; background: var(--bk-card); }
.community-description { font-size: 12.5px; line-height: 1.55; color: var(--bk-text); white-space: pre-wrap; overflow-wrap: anywhere; }
.community-meta { margin-top: 8px; font-size: 11.5px; color: var(--bk-text-3); }
.community-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.community-secondary {
  height: 32px; padding: 0 12px; border: none; border-radius: 9px; cursor: pointer; font: inherit; font-size: 12.5px; font-weight: 600;
  background: transparent; color: var(--bk-text); box-shadow: inset 0 0 0 1px var(--bk-border);
}
.community-secondary:hover { background: var(--bk-hover); }
.community-more { display: block; margin: 6px auto 12px; height: 30px; padding: 0 14px; border: none; border-radius: 9px; cursor: pointer; background: transparent; color: var(--bk-text-2); box-shadow: inset 0 0 0 1px var(--bk-border); font: inherit; font-size: 12.5px; }
@media (max-width: 768px) {
  .community-search { font-size: 16px; }
}

/* ---------- alerts on a script (ScriptAlertDialog) ---------- */
.script-alert-dialog { width: min(460px, calc(100vw - 32px)); }
.sad-form { display: flex; flex-direction: column; gap: 10px; padding-bottom: 6px; border-bottom: 1px solid var(--bk-border); }
.sad-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: 13px; }
.sad-row > span { color: var(--bk-text-2); }
.sad-row select, .sad-field input {
  height: 32px; padding: 0 10px; border: none; border-radius: 9px; min-width: 0;
  background: var(--bk-input); color: var(--bk-text); box-shadow: inset 0 0 0 1px var(--bk-border); font: inherit; font-size: 13px;
}
.sad-field { display: flex; flex-direction: column; gap: 4px; font-size: 12px; font-weight: 600; color: var(--bk-text-2); }
.sad-choice { display: inline-flex; padding: 2px; border-radius: 9px; background: var(--bk-input); box-shadow: inset 0 0 0 1px var(--bk-border); }
.sad-choice button { height: 28px; padding: 0 10px; border: none; border-radius: 7px; background: transparent; color: var(--bk-text-2); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; }
.sad-choice button.active { background: var(--bk-hover); color: var(--bk-text); }
.sad-buttons { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.sad-muted { color: var(--bk-text-3); font-weight: 400; }
.sad-small { font-size: 11.5px; line-height: 1.45; }
.sad-note { font-size: 12.5px; line-height: 1.5; color: var(--bk-text-2); padding: 10px 12px; border-radius: 10px; background: var(--bk-card); }
.sad-note code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px; }
.sad-error { font-size: 12.5px; color: var(--bk-neg); }
.sad-done { font-size: 12.5px; color: var(--bk-pos); }
.sad-list-head { margin-top: 4px; font-size: 11px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--bk-text-3); }
.sad-item { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 10px; background: var(--bk-card); }
.sad-item.off { opacity: 0.7; }
.sad-item-main { flex: 1 1 auto; min-width: 0; }
.sad-item-title { font-size: 13px; font-weight: 600; color: var(--bk-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sad-item-actions { display: flex; gap: 4px; flex-shrink: 0; }
.sad-item-actions .cse-btn { height: 28px; padding: 0 8px; font-size: 12px; }
@media (max-width: 768px) {
  .sad-row select, .sad-field input { font-size: 16px; }
  .sad-item { flex-wrap: wrap; }
}
.scripts-tab-buttons { display: flex; flex-wrap: wrap; gap: 8px; }
/* ========================================
   WIDGET SIDEBAR
   ========================================
   A flex child of .chart-layout like the AI dock, so its width comes out of the chart
   rather than lying over it. Colours are the theme's tokens, so light and dark follow. */
.wsb {
  position: relative;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  min-width: 0;
  max-width: calc(100% - 320px);
  height: 100%;
  box-sizing: border-box;
  background: var(--bk-shell);
  border-left: 1px solid var(--bk-border);
  color: var(--bk-text);
  font-family: var(--font-ui);
}

/* Dark mode: the surface of the app's panels (#151619, as the Chartify AI panel and the
   menus), not the near-black shell; what sits inside a card - tiles, figures - is on the
   card colour one step up (#202124), as the assistant's starters are. Also outranks the
   plain `.dark-mode { background: #000 }` the class would otherwise pull in. */
.wsb.dark-mode {
  background: var(--bk-elevated);
}

.wsb.dark-mode .wsb-card {
  background: var(--bk-elevated);
  border-color: var(--bk-border-strong);
}

.wsb.dark-mode .wsb-card-head {
  border-bottom-color: var(--bk-border-strong);
}

.wsb.dark-mode .wsb-add-menu {
  border-color: var(--bk-border-strong);
}

.wsb.resizing {
  user-select: none;
}

.wsb.drag-target {
  box-shadow: inset 0 0 0 2px rgba(var(--brand-rgb), 0.45);
}

.wsb-resizer {
  position: absolute;
  left: -6px;
  top: 0;
  bottom: 0;
  width: 12px;
  cursor: col-resize;
  z-index: 3;
}

.wsb-resizer::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 3px;
  height: 44px;
  border-radius: 2px;
  background: transparent;
  transition: background 0.15s ease, height 0.15s ease;
}

.wsb-resizer:hover::after,
.wsb-resizer.dragging::after {
  background: var(--brand);
  height: 72px;
}

.wsb-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex: 0 0 auto;
  height: 40px;
  padding: 0 8px 0 14px;
  border-bottom: 1px solid var(--bk-border);
}

.wsb-title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.01em;
}

.wsb-head-actions {
  display: flex;
  align-items: center;
  gap: 2px;
}

.wsb-icon-btn,
.wsb-card-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  min-width: 0;
  min-height: 0;
  padding: 0;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--bk-text-2);
  cursor: pointer;
}

.wsb-card-btn {
  width: 24px;
  height: 24px;
  border-radius: 6px;
}

.wsb-icon-btn:hover:not(:disabled),
.wsb-icon-btn.active,
.wsb-card-btn:hover {
  background: var(--bk-hover);
  color: var(--bk-text);
}

.wsb-icon-btn:disabled {
  opacity: 0.4;
  cursor: default;
}

.wsb-add-wrap {
  position: relative;
}

.wsb-add-backdrop {
  position: fixed;
  inset: 0;
  z-index: 20;
}

.wsb-add-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 21;
  display: flex;
  flex-direction: column;
  min-width: 210px;
  padding: 4px;
  background: var(--bk-elevated);
  border: 1px solid var(--bk-border);
  border-radius: 10px;
  box-shadow: var(--bk-lift);
}

.wsb-add-item {
  display: flex;
  align-items: center;
  gap: 9px;
  height: 34px;
  min-height: 0;
  padding: 0 10px;
  border: none;
  border-radius: 7px;
  background: transparent;
  color: var(--bk-text);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
}

.wsb-add-item:hover {
  background: var(--bk-hover);
}

.wsb-add-icon,
.wsb-card-icon {
  display: inline-flex;
  color: var(--bk-text-2);
}

.wsb-add-icon svg,
.wsb-card-icon svg {
  width: 14px;
  height: 14px;
}

/* The stack. Scrolls as a whole; a card that fills (Chartify AI) takes what is left. */
.wsb-list {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 8px;
  overflow-y: auto;
  scrollbar-width: thin;
}

.wsb-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  margin: 8px 0;
  padding: 28px 18px;
  border: 1.5px dashed var(--bk-border-strong);
  border-radius: 12px;
  color: var(--bk-text-3);
  text-align: center;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.wsb-empty.armed {
  border-color: var(--brand);
  background: rgba(var(--brand-rgb), 0.06);
  color: var(--brand);
}

.wsb-empty-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--bk-text);
}

.wsb-empty-hint {
  font-size: 12px;
  line-height: 1.45;
}

.wsb-drop-marker {
  flex: 0 0 auto;
  height: 3px;
  margin: -5.5px 6px;
  border-radius: 2px;
  background: var(--brand);
}

.wsb-card {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--bk-panel);
  border: 1px solid var(--bk-border);
  border-radius: 12px;
  overflow: hidden;
  transition: box-shadow 0.25s ease;
}

.wsb-card.fill {
  flex: 1 0 460px;
}

.wsb-card.flash {
  box-shadow: 0 0 0 2px var(--brand);
}

.wsb-card-head {
  display: flex;
  align-items: center;
  gap: 7px;
  flex: 0 0 auto;
  height: 36px;
  padding: 0 6px 0 8px;
  border-bottom: 1px solid var(--bk-border);
  cursor: grab;
  user-select: none;
}

.wsb-card.folded .wsb-card-head {
  border-bottom: none;
}

.wsb-card-head:active {
  cursor: grabbing;
}

.wsb-grip {
  display: inline-flex;
  color: var(--bk-text-3);
}

.wsb-card-title {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12.5px;
  font-weight: 600;
}

.wsb-card-body {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  max-height: 520px;
  overflow-y: auto;
  scrollbar-width: thin;
}

.wsb-card.fill .wsb-card-body {
  max-height: none;
  overflow: hidden;
}

/* --- Chartify AI inside a card ---------------------------------------------------
   The panel is the docked one; the card's own header names it and carries the remove
   button, so the panel's close button is left out (see renderAiPanel). */
.wsb-card .chatbot-modal.ai-side-panel {
  flex: 1 1 auto;
  height: auto;
  min-height: 0;
  border: none;
  border-radius: 0;
  box-shadow: none;
}

/* The card header already says Chartify AI: the panel keeps the market and timeframe line,
   the credits and the history button, and drops its logo and title. */
.wsb-card .chatbot-header .ai-avatar,
.wsb-card .ai-title-text h3 {
  display: none;
}

/* --- The drawers' contents inside a card ----------------------------------------- */
.wsb-card .drawer-content {
  padding: 12px;
  overflow: visible;
}

.wsb-card .wsb-watchlist .drawer-content {
  padding: 0 0 8px;
}

.wsb-card .wsb-watchlist .wl-create {
  padding-top: 10px;
}

/* ========================================
   HEAT MAP
   ======================================== */
.hm {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px;
}

.hm-tabs {
  display: flex;
  gap: 4px;
  overflow-x: auto;
  scrollbar-width: none;
}

.hm-tabs::-webkit-scrollbar {
  display: none;
}

.hm-tab {
  flex: 0 0 auto;
  height: 26px;
  min-height: 0;
  padding: 0 10px;
  border: 1px solid var(--bk-border);
  border-radius: 13px;
  background: transparent;
  color: var(--bk-text-2);
  font-family: inherit;
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
}

.hm-tab.active {
  background: var(--bk-primary);
  border-color: var(--bk-primary);
  color: var(--bk-on-primary);
}

.hm-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
  gap: 4px;
}

.hm-tile {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: space-between;
  gap: 4px;
  height: 52px;
  min-height: 0;
  min-width: 0;
  padding: 7px 8px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: var(--bk-card);
  color: var(--bk-text);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: transform 0.1s ease, filter 0.15s ease;
}

.hm-tile:hover {
  filter: brightness(1.08);
}

.hm-tile:active {
  transform: scale(0.97);
}

.hm-tile.up {
  background: color-mix(in srgb, var(--bk-pos) var(--hm-strength), var(--bk-card));
}

.hm-tile.down {
  background: color-mix(in srgb, var(--bk-neg) var(--hm-strength), var(--bk-card));
}

.hm-tile.stale {
  opacity: 0.6;
}

.hm-tile.current {
  border-color: var(--bk-text);
}

.hm-tile-name {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 11.5px;
  font-weight: 700;
}

.hm-tile-change {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  opacity: 0.9;
}

.hm-foot {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  font-size: 11px;
  color: var(--bk-text-3);
}

.hm-empty {
  padding: 16px;
  font-size: 12px;
  color: var(--bk-text-3);
}

/* ========================================
   JOURNAL WIDGET
   ======================================== */
.jw {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 12px;
}

.jw-figures {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
}

.jw-figure {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  padding: 8px 9px;
  border-radius: 9px;
  background: var(--bk-card);
}

.jw-figure--wide {
  grid-column: 1 / -1;
}

.jw-label {
  font-size: 10.5px;
  font-weight: 600;
  color: var(--bk-text-3);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.jw-value {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: 13.5px;
  font-weight: 700;
}

.jw-figure--wide .jw-value {
  font-size: 20px;
}

.jw-value.pos,
.jw-pnl.pos {
  color: var(--bk-pos);
}

.jw-value.neg,
.jw-pnl.neg {
  color: var(--bk-neg);
}

.jw-recent {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.jw-section {
  margin-bottom: 4px;
  font-size: 11px;
  font-weight: 700;
  color: var(--bk-text-2);
}

.jw-none {
  font-size: 12px;
  line-height: 1.45;
  color: var(--bk-text-3);
}

.jw-trade {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 8px;
  height: 30px;
  font-size: 12px;
}

.jw-dir {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 5px;
  font-size: 10.5px;
  font-weight: 700;
  color: #fff;
  background: var(--bk-pos);
}

.jw-dir.short {
  background: var(--bk-neg);
}

.jw-sym {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}

.jw-date {
  color: var(--bk-text-3);
  font-size: 11.5px;
}

.jw-pnl {
  font-family: var(--font-mono);
  font-weight: 600;
}

.jw-actions {
  display: flex;
  gap: 6px;
}

.jw-btn {
  flex: 1 1 0;
  height: 32px;
  min-height: 0;
  padding: 0 10px;
  border: 1px solid var(--bk-border);
  border-radius: 9px;
  background: transparent;
  color: var(--bk-text);
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}

.jw-btn:hover {
  background: var(--bk-hover);
}

.jw-btn.primary {
  background: var(--bk-primary);
  border-color: var(--bk-primary);
  color: var(--bk-on-primary);
}
/* The Account section of the profile panel, in the panel's own type and colours. */

.acct-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 0;
}
.acct-row + .acct-row { border-top: 1px solid var(--bk-divider); }
.acct-row-main {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
.acct-label {
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: #86868B;
}
.acct-value {
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 600;
  color: var(--bk-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.acct-link {
  flex: 0 0 auto;
  padding: 6px 12px;
  border: none;
  border-radius: 8px;
  background: var(--bk-hover);
  color: var(--bk-text);
  font-family: var(--font-ui);
  font-size: 12.5px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}
.acct-link:hover { background: var(--bk-active); }
.acct-hint {
  margin: 2px 0 8px;
  font-family: var(--font-ui);
  font-size: 12px;
  line-height: 1.45;
  color: var(--bk-text-2);
}

.acct-change {
  margin: 4px 0 8px;
  padding: 12px;
  border-radius: 12px;
  background: var(--bk-hover);
}
.acct-input {
  width: 100%;
  box-sizing: border-box;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid var(--bk-border-strong);
  background: var(--bk-elevated);
  color: var(--bk-text);
  font-family: var(--font-ui);
  font-size: 14px;
  outline: none;
}
.acct-input:focus { border-color: var(--bk-text-2); }
.acct-code {
  text-align: center;
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 8px;
}
.acct-error {
  margin-top: 8px;
  font-family: var(--font-ui);
  font-size: 12.5px;
  color: var(--bk-neg);
}
.acct-buttons {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 12px;
}
.acct-btn {
  padding: 8px 14px;
  border: none;
  border-radius: 9px;
  background: var(--bk-hover);
  color: var(--bk-text);
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.acct-btn:hover:not(:disabled) { background: var(--bk-active); }
.acct-btn:disabled { opacity: 0.5; cursor: default; }
.acct-btn-primary { background: var(--bk-primary); color: var(--bk-on-primary); }
.acct-btn-primary:hover:not(:disabled) { background: var(--bk-primary); filter: brightness(1.1); }
.acct-btn-danger { background: var(--bk-neg); color: #FFFFFF; }
.acct-btn-danger:hover:not(:disabled) { background: var(--bk-neg); filter: brightness(1.1); }

.acct-delete-link {
  margin-top: 10px;
  padding: 0;
  border: none;
  background: none;
  font-family: var(--font-ui);
  font-size: 12.5px;
  font-weight: 500;
  color: var(--bk-text-2);
  cursor: pointer;
}
.acct-delete-link:hover { color: var(--bk-neg); text-decoration: underline; }

.acct-overlay {
  position: fixed;
  inset: 0;
  z-index: 3000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(0, 0, 0, 0.55);
}
.acct-modal {
  width: min(420px, 100%);
  padding: 24px;
  border-radius: 16px;
  background: #FFFFFF;
  color: #0B0B0B;
  font-family: var(--font-ui);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
}
.acct-modal.dark {
  background: #1C1D21;
  color: #F5F5F7;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08), 0 20px 60px rgba(0, 0, 0, 0.6);
}
.acct-modal h3 { margin: 0 0 10px; font-size: 18px; font-weight: 700; }
.acct-modal p { margin: 0 0 12px; font-size: 13.5px; line-height: 1.55; opacity: 0.85; }
.acct-modal .acct-warn { color: #B45309; opacity: 1; }
.acct-modal.dark .acct-warn { color: #FBBF24; }
.acct-modal .acct-label { display: block; margin: 6px 0 6px; }
.acct-modal .acct-input { background: transparent; color: inherit; }

.acct-reasons {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 6px 0 14px;
}
.acct-reason {
  padding: 6px 11px;
  border: none;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.05);
  color: inherit;
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
}
.acct-modal.dark .acct-reason { background: rgba(255, 255, 255, 0.07); }
.acct-reason.on {
  background: var(--bk-primary);
  color: var(--bk-on-primary);
}
.acct-modal.dark .acct-reason.on { background: #F5F5F7; color: #0B0B0B; }

/* "This does NOT cancel your subscription" - only for an account with one running. */
.acct-sub-warning {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 2px 0 14px;
  padding: 12px 14px;
  border-radius: 12px;
  background: rgba(255, 159, 10, 0.12);
  box-shadow: inset 0 0 0 1px rgba(255, 159, 10, 0.45);
  font-size: 13px;
  line-height: 1.5;
}
.acct-sub-warning strong { font-size: 14px; color: #B45309; }
.acct-modal.dark .acct-sub-warning strong { color: #FBBF24; }
.acct-sub-warning a { font-weight: 650; color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.acct-sub-ack {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-top: 4px;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}
.acct-sub-ack input { margin-top: 2px; }
/* Orderflow menu and order book. Built on the app's panel tokens (--bk-*), so they follow
   the theme with the rest of the chart. */

.of-menu {
  position: fixed;
  z-index: 1300;
  width: 320px;
  max-width: calc(100vw - 16px);
  padding: 12px;
  border-radius: var(--bk-r-panel, 16px);
  background: var(--bk-elevated);
  box-shadow: inset 0 0 0 1px var(--bk-border), var(--bk-lift, 0 10px 30px rgba(0, 0, 0, 0.18));
  color: var(--bk-text);
  font-family: var(--font-ui);
  animation: ofIn 0.14s ease-out;
}
@keyframes ofIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.of-menu-head { padding: 2px 4px 10px; border-bottom: 1px solid var(--bk-border); margin-bottom: 6px; }
.of-menu-title { font-size: 14px; font-weight: 700; }
.of-menu-sub { font-size: 11.5px; color: var(--bk-text-2); margin-top: 2px; }
.of-menu-row { display: flex; align-items: center; gap: 12px; padding: 8px 4px; border-radius: 10px; cursor: pointer; }
.of-menu-row:hover { background: var(--bk-hover, rgba(0, 0, 0, 0.04)); }
.of-menu-row > div { flex: 1 1 auto; min-width: 0; }
.of-menu-label { font-size: 13px; font-weight: 600; }
.of-menu-hint { font-size: 11.5px; color: var(--bk-text-2); line-height: 1.35; margin-top: 1px; }
.of-menu-foot { margin-top: 6px; padding: 8px 4px 2px; border-top: 1px solid var(--bk-border); font-size: 11.5px; color: var(--bk-text-3, var(--bk-text-2)); line-height: 1.4; }
.of-menu-error { color: #E5342A; }
/* The derivatives, folded into a dropdown at the bottom; the menu scrolls if the window is
   short with it open. */
.of-menu { max-height: calc(100vh - 80px); overflow-y: auto; scrollbar-width: none; }
.of-menu::-webkit-scrollbar { display: none; }
.of-drop { margin-top: 8px; border-top: 1px solid var(--bk-border); padding-top: 6px; }
.of-drop-head {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 4px; border: none; border-radius: 10px;
  background: transparent; color: inherit; font-family: inherit; text-align: left; cursor: pointer;
}
.of-drop-head:hover { background: var(--bk-hover, rgba(0, 0, 0, 0.04)); }
.of-drop-head > span:first-child { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.of-drop-count {
  flex: 0 0 auto; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px;
  background: #34C759; color: #fff; font-size: 11px; font-weight: 700; line-height: 18px; text-align: center;
}
.of-drop-chevron { flex: 0 0 auto; color: var(--bk-text-2); transition: transform 0.15s; }
.of-drop-head.open .of-drop-chevron { transform: rotate(180deg); }
.of-drop-body { padding-top: 2px; }
.of-menu-sources { display: flex; flex-wrap: wrap; gap: 4px; padding: 4px 4px 2px; }
.of-source {
  border: none; border-radius: 7px; padding: 4px 9px; cursor: pointer;
  background: var(--bk-input, rgba(0, 0, 0, 0.06)); color: var(--bk-text-2);
  font-family: inherit; font-size: 11.5px; font-weight: 600;
}
.of-source.on { background: var(--bk-text); color: var(--bk-elevated); }
.of-menu-note { margin-top: 6px; padding: 0 4px 2px; font-size: 11.5px; color: var(--bk-text-3, var(--bk-text-2)); line-height: 1.4; }
.of-menu-paused { color: var(--bk-text); font-weight: 600; margin-bottom: 4px; }

.of-switch {
  appearance: none; -webkit-appearance: none; flex: 0 0 auto;
  width: 36px; height: 21px; border-radius: 11px; background: var(--bk-input, rgba(0, 0, 0, 0.12));
  box-shadow: inset 0 0 0 1px var(--bk-border); position: relative; cursor: pointer; transition: background 0.15s;
}
.of-switch::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 17px; height: 17px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25); transition: transform 0.15s;
}
.of-switch:checked { background: #34C759; box-shadow: none; }
.of-switch:checked::after { transform: translateX(15px); }

.ob-panel {
  position: absolute;
  top: 56px;
  right: 76px;
  z-index: 60;
  width: 250px;
  max-height: calc(100% - 80px);
  overflow-y: auto;
  padding: 10px 10px 8px;
  border-radius: 14px;
  background: var(--bk-elevated);
  box-shadow: inset 0 0 0 1px var(--bk-border), var(--bk-lift, 0 10px 30px rgba(0, 0, 0, 0.18));
  color: var(--bk-text);
  font-family: var(--font-ui);
  font-size: 12px;
  scrollbar-width: none;
}
.ob-panel::-webkit-scrollbar { display: none; }
.ob-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; margin: -10px -10px 8px; padding: 10px 10px 0; cursor: grab; touch-action: none; user-select: none; }
.ob-head:active { cursor: grabbing; }
.ob-title { font-size: 13px; font-weight: 700; }
.ob-sub { font-size: 11px; color: var(--bk-text-2); }
.ob-live { color: #34C759; font-weight: 600; }
.ob-close { border: none; background: none; color: var(--bk-text-2); font-size: 20px; line-height: 1; cursor: pointer; padding: 0 2px; }
.ob-close:hover { color: var(--bk-text); }
.ob-cols, .ob-row { display: grid; grid-template-columns: 1.2fr 1fr 1fr; gap: 4px; }
.ob-cols { font-size: 10.5px; font-weight: 600; color: var(--bk-text-3, var(--bk-text-2)); padding: 0 4px 4px; text-transform: uppercase; letter-spacing: 0.03em; }
.ob-cols span:not(:first-child), .ob-row span:not(:first-child) { text-align: right; }
.ob-row { position: relative; padding: 2px 4px; font-variant-numeric: tabular-nums; border-radius: 4px; }
.ob-row span { position: relative; z-index: 1; }
.ob-depth { position: absolute; right: 0; top: 1px; bottom: 1px; border-radius: 3px; }
.ob-row--ask .ob-depth { background: rgba(229, 52, 42, 0.13); }
.ob-row--bid .ob-depth { background: rgba(30, 158, 74, 0.14); }
.ob-row--ask .ob-px { color: #E5342A; font-weight: 600; }
.ob-row--bid .ob-px { color: #1E9E4A; font-weight: 600; }
.dark .ob-row--ask .ob-px { color: #FF6961; }
.dark .ob-row--bid .ob-px { color: #32D74B; }
.ob-sz, .ob-total { color: var(--bk-text-2); }
.ob-mid { display: flex; align-items: baseline; justify-content: space-between; padding: 6px 4px; margin: 3px 0; border-top: 1px solid var(--bk-border); border-bottom: 1px solid var(--bk-border); font-variant-numeric: tabular-nums; }
.ob-mid b { font-size: 14px; }
.ob-mid span { font-size: 11px; color: var(--bk-text-2); }
.ob-balance { margin-top: 8px; padding: 0 4px; }
.ob-balance-bar { height: 6px; border-radius: 3px; background: rgba(229, 52, 42, 0.55); overflow: hidden; }
.ob-balance-bar > div { height: 100%; background: rgba(30, 158, 74, 0.8); }
.ob-balance-labels { display: flex; justify-content: space-between; font-size: 10.5px; color: var(--bk-text-2); margin-top: 3px; }
.ob-rows { display: flex; align-items: center; gap: 4px; margin-top: 8px; padding: 0 4px; font-size: 11px; color: var(--bk-text-2); }
.ob-rows button { border: none; border-radius: 6px; padding: 2px 7px; background: var(--bk-input, rgba(0, 0, 0, 0.06)); color: var(--bk-text-2); font-size: 11px; cursor: pointer; }
.ob-rows button.on { background: var(--bk-text); color: var(--bk-elevated); }
.ob-empty { padding: 24px 4px; text-align: center; color: var(--bk-text-2); }

@media (max-width: 768px) {
  .ob-panel { right: 8px; top: 52px; width: 220px; }
}

/* "BTC-PERP" is the first symbol name with a hyphen, which the browser will happily break
   the navbar's symbol button on. No symbol name has a space, so nothing else changes. */
.symbol-btn .symbol-text { white-space: nowrap; }

@media (max-width: 768px) {
  .ob-panel { max-height: calc(100% - 120px); }
}
/* ========================================
   CHART CONTAINER
   ======================================== */
.chart-container {
  position: relative;
  width: 100vw;
  /* 100vh on iOS Safari is the viewport with the browser chrome retracted - its tallest
     state, not its current one. With the toolbar showing, which is its default, the last
     ~90px of this container sit behind that toolbar, and the bottom strip with it: the
     Chartify AI, Trading Panel, Journal and Alerts buttons were simply not on screen.
     dvh follows the visible height as the chrome comes and goes. vh stays first as the
     fallback for browsers without dvh. */
  /* Fills the screen edge to edge, including behind the status bar and home indicator -
     viewport-fit=cover asks for exactly that. Insetting the container instead left the
     body's own background showing as dark bands top and bottom. The navbar and bottom
     strip pad themselves by the insets, so their surfaces reach the edges while their
     contents stay clear of the system UI. */
  height: 100vh;
  height: 100dvh;
  background: #0A0A0A;
  background-image: var(--bg-primary);
  display: flex;
  flex-direction: column;
  overflow: visible;
}

/* ========================================
   TOP NAVBAR
   ======================================== */
.navbar {
  height: 48px;
  background: rgba(255, 255, 255, 0.8);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  display: flex;
  align-items: center;
  justify-content: flex-start;
  padding: 0 0 0 12px;
  flex-shrink: 0;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
  border-radius: 0;
  position: relative;
  z-index: 100;
  /* Scroll horizontally instead of overlapping when the window is too narrow */
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}

.navbar::-webkit-scrollbar {
  display: none;
}

.navbar-left {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  /* The bar's left cell is the drawing rail's column: the same width, and the same 1px
     right edge drawn the same way. The line beside the profile picture is therefore the
     continuation of the one between the rail and the chart, rather than a second line a
     few pixels off it.

     The negative margin cancels the navbar's own 12px of left padding, which would
     otherwise start this cell at x=12 and put its edge at 56 against the rail's 44 - the
     two lines out by exactly that padding. */
  width: 44px;
  margin-left: -12px;
  box-sizing: border-box;
  position: relative;
}

.navbar-center {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-shrink: 0;
  /* Auto side-margins keep it centered between left/right on wide screens,
     and collapse (letting the navbar scroll) when space runs out */
  margin-left: auto;
  margin-right: auto;
}

/* Centred on the window rather than between its neighbours.
   The two ends of this bar are not the same width - a name on the left, two buttons and
   the price scale's column on the right - so auto margins, which can only split the space
   evenly, leave the group about 124px left of the middle. Taking it out of the flow is the
   only way to put it on the centre line.

   Above 1400 only. The group is 777px and the heavier end 301, so true centring needs
   1379px before the group would reach the trading panel; below that this would overlap
   rather than overflow, which is the worse failure. There it keeps the auto margins, which
   centre it between its neighbours and cannot collide. */
@media (min-width: 1400px) {
  .navbar-center {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    margin-left: 0;
    margin-right: 0;
  }

  /* With the group out of the flow there is nothing before these to push them along, so
     the first of the pair collects the slack instead. */
  .navbar > .trading-panel-btn {
    margin-left: auto;
  }
}

.profile-picture {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  /* War var(--bk-elevated) - im Hellmodus reines Weiss, also dieselbe Farbe wie
     die Navigation dahinter, mit einem ebenfalls weissen Buchstaben darauf. */
  background: var(--bk-active);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 17px;
  color: var(--bk-text);
  letter-spacing: 0;
  box-shadow: 0 0 0 2px var(--bk-active);
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  overflow: hidden;
  cursor: pointer;
  flex-shrink: 0;
  margin-left: -8px;
}

/* Sits immediately right of the profile cell's divider, which is where the row proper
   begins. flex-shrink: 0 because it is a name, not a label to be squeezed. */
.navbar-wordmark {
  margin-left: 12px;
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 17px;
  letter-spacing: -0.3px;
  color: var(--bk-text);
  white-space: nowrap;
  flex-shrink: 0;
}

/* A decorative name is the first thing to go when the bar runs short, not the last. The
   threshold is measured rather than picked: with the trading panel and the journal now in
   this row, the bar overflows at 1150 with the name and fits exactly without it, so it can
   only be afforded on a genuinely wide window. 1250 leaves room for a longer ticker, which
   is the other thing that moves this width around. */
@media (max-width: 1250px) {
  .navbar-wordmark {
    display: none;
  }
}

/* Smaller than it was on the right, so it sits inside the rail's 44px column with room
   on both sides instead of overhanging it. The -8px above pulled the picture back against
   the padding of the wrapper it used to sit in; centred in its own cell there is nothing
   to pull back from. */
.navbar-left .profile-picture {
  margin-left: 0;
  width: 28px;
  height: 28px;
  font-size: 13px;
}

.profile-picture::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  padding: 2px;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0.1));
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.profile-picture:hover {
  ;
  box-shadow: 0 0 0 2px var(--bk-active);
}

.profile-picture:hover::before {
  opacity: 1;
}

.profile-picture:active {
  ;
  box-shadow: none;
}

/* Profile Modal */
.profile-modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 420px;
  max-width: 90vw;
  max-height: 85vh;
  background: rgba(255, 255, 255, 0.98);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 16px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  z-index: 10001;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.profile-content {
  flex: 1;
  overflow-y: auto;
  padding: 0;
}

/* --- Desktop profile dropdown ----------------------------------------------
   The desktop profile hangs off the picture in the navbar rather than opening as a
   centred drawer, so the chart stays readable behind it. It is mounted outside the
   navbar: the navbar's backdrop-filter makes it the containing block for fixed
   descendants and it clips its own overflow, so a panel inside it is cut off at the
   navbar's bottom edge and never seen. The top and right below are the usual resting
   place of the picture and are overwritten inline with its measured position as soon as
   the panel opens. The phone keeps .profile-modal - the component picks between the
   two. */
.profile-dropdown-backdrop {
  position: fixed;
  inset: 0;
  z-index: 10000;
}

/* Flush with the top of the window, starting at the drawing rail's right-hand edge - the
   effect measures both, and these are where they land on a full-width window, standing in
   for the frame before that measurement arrives. Square along the top because it meets the
   window's own edge there; rounding it would show the page through the corner. */
.profile-dropdown {
  position: fixed;
  top: 0;
  left: 44px;
  right: auto;
  z-index: 10001;
  width: 340px;
  max-width: calc(100vw - 24px);
  max-height: calc(100vh - 16px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.98);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 0 0 14px 14px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
}

.dark-mode .profile-dropdown {
  background: #101010;
  border: 1px solid #242424;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55);
}

/* The avatar block is sized for a 420px drawer, where it is a header. At dropdown width
   it would be most of the panel before a single action was reached, so it is tightened
   here and only here. */
.profile-dropdown .profile-avatar-section {
  padding: 22px 20px 18px;
}

.profile-dropdown .profile-avatar-large {
  width: 56px;
  height: 56px;
  font-size: 26px;
  margin: 0 auto 12px;
}

.profile-avatar-section {
  text-align: center;
  padding: 36px 32px 32px;
  background: transparent;
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  position: relative;
}

/* The avatar is the first letter of the display name on the circle's gradient - there is
   no picture to upload, so this is the only form it takes. It is set larger than the two
   initials the circle was sized for, and the desktop dropdown scales it down again below,
   its circle being 56px rather than 96px. */
.profile-avatar-large {
  width: 96px;
  height: 96px;
  border-radius: 50%;
  /* Gleicher Fall wie beim kleinen Profilbild: var(--bk-elevated) ist im
     Hellmodus weiss, der Buchstabe war es auch. */
  background: var(--bk-active);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 44px;
  color: var(--bk-text);
  margin: 0 auto 20px;
  box-shadow: none;
  position: relative;
  z-index: 1;
  border: none;
}

.profile-name {
  font-family: var(--font-ui);
  font-size: 24px;
  font-weight: 700;
  color: #1D1D1F;
  margin: 0 0 8px;
  letter-spacing: -0.3px;
}

/* Reads as the heading it replaces until it is focused, so the panel does not look like a
   form when nobody is editing it. */
.profile-name-input {
  display: block;
  width: 100%;
  margin: 0 0 8px;
  padding: 4px 8px;
  text-align: center;
  font-family: var(--font-ui);
  font-size: 24px;
  font-weight: 700;
  letter-spacing: -0.3px;
  color: #1D1D1F;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 8px;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.profile-name-input::placeholder {
  color: #8E8E93;
  font-weight: 600;
}

.profile-name-input:hover {
  border-color: rgba(0, 0, 0, 0.12);
}

.profile-name-input:focus {
  outline: none;
  background: rgba(0, 0, 0, 0.04);
  border-color: rgba(0, 0, 0, 0.18);
}

.dark-mode .profile-name-input {
  color: #F7F7F7;
}

.dark-mode .profile-name-input:hover {
  border-color: rgba(255, 255, 255, 0.16);
}

.dark-mode .profile-name-input:focus {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.24);
}

.profile-email {
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 500;
  color: #718096;
  margin: 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.profile-email::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #10B981;
  box-shadow: none;
}

.profile-section {
  padding: 24px 32px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}

.profile-section:last-child {
  border-bottom: none;
  padding-bottom: 32px;
}

.profile-section-title {
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 700;
  color: #86868B;
  text-transform: uppercase;
  letter-spacing: 1px;
  margin: 0 0 16px;
}

.profile-info-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
}

.profile-info-item {
  background: rgba(0, 0, 0, 0.03);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 12px;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  position: relative;
}

/* For the one value that does not fit half a row. "Active", "Max" and "3 / 5" all sit
   inside 99px; AI credits is two five-figure numbers with a slash between them, and at
   400px wide it wrapped onto a second line while every neighbour stayed on one. Given a
   full row it fits, and the longest number in the panel ends up reading as the heading of
   its own line, which is about right for the one figure people open this to check. */
.profile-info-item--wide {
  grid-column: 1 / -1;
}

.profile-info-item--wide .profile-info-value {
  font-variant-numeric: tabular-nums;
}

.profile-info-label {
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  color: #86868B;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  position: relative;
  z-index: 1;
}

.profile-info-value {
  font-family: var(--font-ui);
  font-size: 16px;
  font-weight: 700;
  color: #1D1D1F;
  letter-spacing: -0.2px;
  position: relative;
  z-index: 1;
}

.profile-actions {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* The Appearance row. Built from the same surface as .profile-action-btn below it so the
   section reads as one stack of controls rather than a control and a stray line of text;
   the switch itself is the one the chart settings already use. */
.profile-toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 12px 18px;
  background: rgba(0, 0, 0, 0.03);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 12px;
}

.profile-toggle-label {
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 600;
  color: #1D1D1F;
}

.dark-mode .profile-toggle-row {
  background: rgba(255, 255, 255, 0.04);
  border-color: #242424;
}

.dark-mode .profile-toggle-label {
  color: #F5F5F7;
}

.profile-action-btn {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  padding: 14px 18px;
  background: rgba(0, 0, 0, 0.03);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 12px;
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 600;
  color: #1D1D1F;
  cursor: pointer;
  transition: background 0.15s ease;
  position: relative;
}

.profile-action-btn:hover {
  background: rgba(0, 0, 0, 0.06);
}

.profile-action-btn svg {
  flex-shrink: 0;
  color: #1D1D1F;
  position: relative;
  z-index: 1;
}

/* Deliberately not a .profile-action-btn. The panel's buttons are things people came to
   do; this is a reference they will open once, so it sits under them as text and takes
   no visual weight. */
.profile-licence-link {
  display: block;
  width: 100%;
  padding: 0 32px 26px;
  box-sizing: border-box;
  background: none;
  border: 0;
  text-align: center;
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 500;
  color: #86868B;
  cursor: pointer;
  transition: color 0.15s ease;
}

.profile-licence-link:hover {
  color: #1D1D1F;
  text-decoration: underline;
}

/* Sits before the title in the same header the close button ends, so the row reads
   back / where you are / close. */
.profile-back-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  margin-right: -6px;
  padding: 0;
  background: none;
  border: 0;
  border-radius: 8px;
  color: #1D1D1F;
  cursor: pointer;
  transition: background 0.15s ease;
}

.profile-back-btn:hover {
  background: rgba(0, 0, 0, 0.06);
}

.profile-licence-intro {
  margin: 0 0 16px;
  font-family: var(--font-ui);
  font-size: 13px;
  line-height: 1.45;
  color: #86868B;
}

.profile-licence-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Each entry is the link, rather than carrying one - the whole row is the target, which
   is the only version that works with a thumb. */
.profile-licence {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 14px 18px;
  background: rgba(0, 0, 0, 0.03);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 12px;
  text-decoration: none;
  transition: background 0.15s ease;
}

.profile-licence:hover {
  background: rgba(0, 0, 0, 0.06);
}

.profile-licence-text {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.profile-licence-name {
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 600;
  color: #1D1D1F;
  overflow-wrap: anywhere;
}

.profile-licence-line {
  font-family: var(--font-ui);
  font-size: 12.5px;
  font-weight: 500;
  color: #86868B;
  overflow-wrap: anywhere;
}

.profile-licence-arrow {
  flex-shrink: 0;
  color: #86868B;
}

/* Symbol Button */
.symbol-btn {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 16px;
  height: 36px;
  background: transparent;
  color: #1D1D1F;
  border: none;
  border-radius: 12px;
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 14px;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: none;
  cursor: pointer;
  position: relative;
}

.symbol-btn::after {
  content: '';
  position: absolute;
  right: -10px;
  top: 50%;
  transform: translateY(-50%);
  width: 1.5px;
  height: 18px;
  background: rgba(0, 0, 0, 0.1);
}

.symbol-btn:hover {
  background: rgba(0, 0, 0, 0.06);
}

.symbol-text {
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 14px;
  color: #1D1D1F;
}

.symbol-logo-small {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  color: white;
  font-weight: 700;
  flex-shrink: 0;
  overflow: hidden;
}

/* Navbar Right */
/* The mirror of .navbar-left at the other end of the bar: this cell is the price scale's
   column - the width is measured off the chart and set inline, because the scale is drawn
   into a canvas and its width follows the number of digits in the price - and it carries
   the same 1px edge on its left. The line beside the tools button is therefore the
   continuation of the chart's own divider between the plot and the scale. */
.navbar-right {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex-shrink: 0;
  /* The slack is taken by the journal before it (see .journal-btn), which leaves this
     packed against the right-hand end - so its left edge is the divider, whatever the row
     before it happens to measure. */
  margin-right: 0;
  box-sizing: border-box;
  position: relative;
}

/* The bar's two dividers, drawn the same way and at the same length so they read as a
   pair: one beside the profile picture, one beside the tools button.

   Drawn as an element rather than as an inset edge on the cells themselves, which is what
   they were. The cells are different heights - the picture is 28px, the tools button 34 -
   and an inset edge takes the height of its own box, so the two lines came out 28 and 40.
   Given the height here they cannot drift apart again. */
.navbar-left::after,
.navbar-right::before {
  content: '';
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 1px;
  height: 28px;
  background: var(--bk-border);
  pointer-events: none;
}

.navbar-left::after {
  right: 0;
}

.navbar-right::before {
  left: 0;
}

/* Timeframe Dropdown */
.timeframe-dropdown-container {
  position: relative;
}

.timeframe-dropdown-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  height: 36px;
  background: transparent;
  border: none;
  border-radius: 12px;
  color: #1D1D1F;
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  white-space: nowrap;
  box-shadow: none;
  position: relative;
}

.timeframe-dropdown-btn::after {
  content: '';
  position: absolute;
  right: -10px;
  top: 50%;
  transform: translateY(-50%);
  width: 1.5px;
  height: 18px;
  background: rgba(0, 0, 0, 0.1);
}

.timeframe-dropdown-btn:hover {
  background: rgba(0, 0, 0, 0.06);
}

.timeframe-text {
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 14px;
  color: #1D1D1F;
}

.timeframe-chevron {
  flex-shrink: 0;
  color: #8E8E93;
  transition: transform 0.18s cubic-bezier(0.4, 0, 0.2, 1);
}

.timeframe-dropdown-btn.open .timeframe-chevron {
  transform: rotate(180deg);
}

.dropdown-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 9999;
}

.timeframe-dropdown-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  background: rgba(255, 255, 255, 0.98);
  backdrop-filter: blur(40px) saturate(180%);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 12px;
  overflow-y: auto;
  overflow-x: hidden;
  z-index: 10000;
  min-width: 140px;
  max-height: 480px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.12);
}

.timeframe-dropdown-menu::-webkit-scrollbar {
  width: 6px;
}

.timeframe-dropdown-menu::-webkit-scrollbar-track {
  background: transparent;
}

.timeframe-dropdown-menu::-webkit-scrollbar-thumb {
  background: rgba(142, 142, 147, 0.2);
  border-radius: 3px;
}

.timeframe-dropdown-menu::-webkit-scrollbar-thumb:hover {
  background: rgba(142, 142, 147, 0.3);
}

.timeframe-group-header {
  padding: 12px 16px 6px 16px;
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 10px;
  color: #8E8E93;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  background: transparent;
  border-top: 1px solid rgba(0, 0, 0, 0.04);
}

.timeframe-group-header:first-child {
  border-top: none;
  padding-top: 8px;
}

.timeframe-dropdown-item {
  width: 100%;
  padding: 10px 16px;
  background: transparent;
  color: #48484A;
  border: none;
  text-align: left;
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 13px;
  transition: all var(--transition-speed) ease;
  cursor: pointer;
}

.timeframe-dropdown-item:hover {
  background: rgba(142, 142, 147, 0.08);
  color: #1D1D1F;
}

.timeframe-dropdown-item.active {
  background: rgba(142, 142, 147, 0.12);
  color: #8E8E93;
  font-weight: 700;
}

/* Chart type: an icon button beside the timeframe, and rows with an icon before the name. */
.chart-type-btn {
  padding: 8px 10px;
  color: #1D1D1F;
}

.chart-type-item {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-ui);
}

.chart-type-item svg {
  flex-shrink: 0;
}

/* Navbar Actions */
/* --- Phone navbar menu -----------------------------------------------------
   Below 768px the navbar's icon buttons collapse into this menu behind the profile
   picture, so the picture can share the first row with the symbol and timeframe
   controls instead of the navbar wrapping onto a second row. The component only
   renders this under that breakpoint, so none of it reaches the desktop layout.
   It is mounted outside the navbar and positioned from a measurement of the tools
   button - see .navbar-menu below. */
.navbar-menu-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1200;
}

/* Mounted outside the navbar and positioned from a measurement of the tools button - the
   bar clips its own overflow, so anchoring this inside the navbar laid it out correctly
   below the bar and then cut every pixel of it away. These coordinates are where the
   button rests on a full-width bar, and stand in for the frame before that measurement
   arrives. */
.navbar-menu {
  position: fixed;
  top: 56px;
  right: 92px;
  z-index: 1201;
  display: flex;
  flex-direction: column;
  min-width: 210px;
  padding: 6px;
  background: rgba(255, 255, 255, 0.98);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 12px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.16);
  /* It opens out of its own top-right corner, growing down and to the left - which is the
     corner it is pinned to, and the only direction it has room to grow in. The menu had no
     entrance at all before this and simply appeared.

     transform-origin is what does the work: scaling about the top right leaves that corner
     still while the opposite one travels, so the panel reads as unfolding from the button
     rather than as sliding in from somewhere off-screen. The slight translate away from
     that corner gives the motion a direction on top of the scale. */
  transform-origin: top right;
  animation: navbarMenuOpen 0.18s cubic-bezier(0.33, 1, 0.68, 1) both;
}

@keyframes navbarMenuOpen {
  from {
    opacity: 0;
    transform: scale(0.92) translate(8px, -8px);
  }
  to {
    opacity: 1;
    transform: scale(1) translate(0, 0);
  }
}

/* An entrance is decoration; the menu still has to appear for someone who has asked the
   system not to animate. */
@media (prefers-reduced-motion: reduce) {
  .navbar-menu {
    animation: none;
  }
}

.navbar-menu.dark-mode {
  background: rgba(28, 28, 30, 0.98);
  border-color: var(--bk-border);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.5);
}

.navbar-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 9px 10px;
  background: transparent;
  border: none;
  border-radius: 8px;
  color: #1D1D1F;
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
}

.navbar-menu-item svg {
  flex-shrink: 0;
}

.navbar-menu-item:active {
  background: rgba(0, 0, 0, 0.06);
}

.navbar-menu-item.active {
  color: var(--bk-text);
}

.navbar-menu.dark-mode .navbar-menu-item {
  color: #F5F5F7;
}

.navbar-menu.dark-mode .navbar-menu-item:active {
  background: rgba(255, 255, 255, 0.08);
}

/* --- Narrow navbar ----------------------------------------------------------
   With its four icon buttons behind one control the bar needs 919px laid out in
   full - 910 for a six-character ticker, a little more for one like EUR/USD.
   Below that .navbar scrolls, and it hides its scrollbar, so whatever does not
   fit is not clipped in a way that shows: it is simply gone, with no hint that
   anything is there to scroll to. This block buys back the 150px between that
   and the 769px where the phone layout takes over, so the scroll never starts. It
   runs to 960px rather than 920: the full-width bar wants 925 for a ticker like
   EUR/USD, so a block ending at 920 left a few pixels overflowing just above it.

   The trims are the ones the phone block already makes for the same reason, at
   half its severity: 8px of gap instead of 20, 10px of side padding on the
   centre buttons instead of 16, and the 36px separating the tools button from
   the profile picture cut to 10. Together they bring the bar to 749px. The
   divider goes with that padding - it is position: fixed at a full-width
   coordinate, so once the gap it sits in has moved it is a stray line. */
@media (min-width: 769px) and (max-width: 960px) {
  .navbar-center {
    gap: 8px;
  }

  .navbar .symbol-btn,
  .navbar .timeframe-dropdown-btn,
  .navbar .indicators-btn {
    padding-left: 10px;
    padding-right: 10px;
  }

  /* Bounds a ticker longer than the ordinary ones rather than letting it push the
     bar back into scrolling. */
  .navbar .symbol-btn {
    max-width: 150px;
  }

  .navbar .symbol-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* Below 960px the bar's own buttons drop their labels and keep their icons.
     Two things made that necessary: the journal moved up into this row, and the
     right-hand cell is now the price scale's column rather than whatever was left
     over - it has to start on the chart's divider, so the row before it can only
     have the plot's width to spend. With labels that came to 788px against the 668
     available at this size; without them there is room to spare, and the tooltips
     still name each one.

     font-size: 0 hides the text and leaves the svg, which carries its own
     dimensions - the same trick the trade checker uses on a phone.

     The indicators button is the exception, and deliberately so: its label sits in a
     span with a size of its own, so this does not reach it. It is the most used
     control in the bar and there is room for exactly one name, so it keeps its. */
  .navbar .indicators-btn {
    font-size: 0;
    gap: 0;
    padding-left: 8px;
    padding-right: 8px;
  }
}

.icon-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 10px;
  color: #1D1D1F;
  cursor: pointer;
  transition: background 0.15s ease;
}

.icon-btn:hover {
  background: rgba(0, 0, 0, 0.06);
}

.icon-btn.active {
  background: var(--bk-active);
  color: var(--bk-text);
}

.icon-btn.active:hover {
  background: var(--bk-active);
}

.icon-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* Replay Controls */
.replay-btn {
  padding: 6px 12px;
  min-height: 34px;
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 10px;
  color: #1D1D1F;
  font-family: var(--font-ui);
  font-weight: 500;
  font-size: 13px;
  cursor: pointer;
  transition: all 0.15s ease;
  white-space: nowrap;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}

.replay-btn:hover:not(:disabled) {
  color: #AEAEB2;
  border-color: rgba(142, 142, 147, 0.4);
  background: rgba(142, 142, 147, 0.08);
}

.replay-btn:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

.replay-controls {
  display: flex;
  align-items: center;
  gap: 12px;
}

.replay-timestamp {
  font-family: var(--font-mono);
  font-size: 12px;
  color: #1D1D1F;
  padding: 0 12px;
  min-width: 180px;
  text-align: center;
}

.replay-exit-btn {
  padding: 6px 12px;
  min-height: 34px;
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 10px;
  color: #1D1D1F;
  font-family: var(--font-ui);
  font-weight: 500;
  font-size: 13px;
  cursor: pointer;
  transition: all 0.15s ease;
  white-space: nowrap;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}

.replay-exit-btn:hover {
  color: #AEAEB2;
  border-color: rgba(142, 142, 147, 0.4);
  background: rgba(142, 142, 147, 0.08);
}

.replay-play-btn {
  font-size: 14px;
  min-width: 44px;
}

/* Speed Selector */
.speed-selector-container {
  position: relative;
}

.speed-selector-btn {
  padding: 6px 12px;
  min-height: 34px;
  min-width: 60px;
  background: rgba(142, 142, 147, 0.15);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(142, 142, 147, 0.3);
  border-radius: 10px;
  color: #1D1D1F;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 13px;
  cursor: pointer;
  transition: all 0.15s ease;
  white-space: nowrap;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}

.speed-selector-btn:hover {
  color: #1D1D1F;
  border-color: rgba(142, 142, 147, 0.4);
  /* Neutral enough to read as a divider in both themes without a theme class. */
  background: rgba(142, 142, 147, 0.45);
}

.speed-dropdown-menu {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(40px) saturate(180%);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 12px;
  overflow: hidden;
  z-index: 10000;
  min-width: 80px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.12);
}

.speed-dropdown-item {
  width: 100%;
  padding: 10px 16px;
  background: transparent;
  color: var(--text-secondary);
  border: none;
  text-align: center;
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 13px;
  transition: all var(--transition-speed) ease;
  cursor: pointer;
}

.speed-dropdown-item:hover {
  background: rgba(142, 142, 147, 0.08);
  color: var(--text-primary);
}

.speed-dropdown-item.active {
  background: rgba(142, 142, 147, 0.12);
  color: #8E8E93;
  font-weight: 700;
}

/* ========================================
   CHART LAYOUT & TOOLBAR
   ======================================== */
.chart-layout {
  display: flex;
  flex: 1;
  overflow: visible;
  min-height: 0;
  position: relative;
}

.drawing-toolbar {
  width: 44px;
  background: rgba(255, 255, 255, 0.8);
  backdrop-filter: blur(80px) saturate(200%);
  -webkit-backdrop-filter: blur(80px) saturate(200%);
  border: 1px solid rgba(0, 0, 0, 0.08);
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20px 0;
  gap: 8px;
  flex-shrink: 0;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05),
    inset 0 1px 0 rgba(255, 255, 255, 0.5);
  border-radius: 0 12px 0 0;
  margin: 8px 0 0 0;
  position: relative;
  z-index: 10;
  height: calc(100% + 36px);
  /* Scroll vertically instead of overflowing when the window is too short */
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: none;
}

.drawing-toolbar::-webkit-scrollbar {
  display: none;
}

.tool-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 8px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 10px;
  color: #3A3A3C;
  cursor: pointer;
  position: relative;
  transition: all 0.15s ease;
}

.tool-btn svg {
  width: 16px;
  height: 16px;
  /* Above the mark below, which is a positioned pseudo-element and would otherwise paint
     over the icon it is meant to sit behind. */
  position: relative;
  z-index: 1;
}

/* The hover and selected marks are drawn on an inset layer rather than on the button
   itself. Painted across the full box they filled the rail edge to edge, so the column
   read as a stack of tiles with one lit up rather than as icons with one picked out. The
   button keeps its size - it is the pointer target, and shrinking that to shrink the mark
   would have made the rail harder to hit. */
.tool-btn::before {
  content: '';
  position: absolute;
  inset: 3px;
  border-radius: 9px;
  background: transparent;
  transition: background var(--transition-speed) ease;
  pointer-events: none;
}

/* A group button is really one control with two halves - the icon that arms the tool and
   the chevron that opens the list - so it gets one highlight that holds both rather than
   a mark cut short of the chevron. It reaches a pixel past the button to take the chevron
   in, which still leaves 3px of rail beyond it. The plain buttons have no chevron and
   keep the square mark. */
.tool-group .tool-btn::before {
  left: 0;
  right: -1px;
}

/* And it lights from either half, so hovering the chevron does not leave the icon beside
   it looking inert - they are one control.

   It holds that light for as long as the panel is open, at the same strength: the pointer
   leaves the button the moment it moves onto the panel, and a highlight that dropped out
   there would flicker on the way. Steady, with the panel sliding out of it, is the whole
   effect - the panel is the loud signal that it is open, the button only has to look
   engaged, so this stays quieter than the active fill below. */
.tool-group:hover .tool-btn::before,
.tool-group:has(.tool-group-caret.open) .tool-btn::before {
  background: rgba(0, 0, 0, 0.04);
}

.dark-mode .tool-group:hover .tool-btn::before,
.dark-mode .tool-group:has(.tool-group-caret.open) .tool-btn::before {
  background: rgba(255, 255, 255, 0.1);
}

.tool-btn:hover {
  color: #1D1D1F;
  background: transparent;
}

.tool-btn:hover::before {
  background: rgba(0, 0, 0, 0.04);
}

/* Das aktive Werkzeug trug vier Mal denselben Wert - Icon, Rahmen, Flaeche und
   Schatten - und war dadurch unsichtbar. Flaeche markiert den Zustand, das Icon
   traegt den vollen Textkontrast. */
.tool-btn.active {
  color: var(--bk-text);
  border-color: transparent;
  background: transparent;
  box-shadow: none;
}

.tool-btn.active::before,
.tool-group:hover .tool-btn.active::before,
.tool-group:has(.tool-group-caret.open) .tool-btn.active::before {
  background: var(--bk-active);
}

.tool-divider {
  width: 28px;
  height: 1px;
  background: rgba(0, 0, 0, 0.1);
  margin: 8px 0;
}

/* A rail button that stands for a group of tools. The icon keeps the rail's 36px square so
   this column still reads as one run of evenly spaced icons; the caret is laid over the
   button's right edge rather than given a column of its own, which would have made this
   the one wide button in a 44px rail. */
.tool-group {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}

.tool-group-caret {
  position: absolute;
  /* -1 rather than -3: at -3 the chevron sat a single pixel from the rail's edge, which
     left no room for the highlight to reach round it. */
  right: -1px;
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 12px;
  height: 26px;
  /* mobile.css puts a 40px floor under every button between 769 and 1024px. That is the
     right size for a lone control and the wrong one for the second of two sharing a 36px
     square: it grew this to 40x40, laid it over the icon, and left the whole button
     opening the list. The floor is lifted here and the target restored below. */
  min-width: 0;
  min-height: 0;
  padding: 0;
  border: none;
  border-radius: 4px;
  background: transparent;
  color: #8E8E93;
  cursor: pointer;
  transition: color 0.15s ease, background 0.15s ease;
}

/* Nothing hovers on a touch screen, so a 12px sliver beside the icon is neither findable
   nor hittable. There the caret stays as the mark that says "there are more of these" and
   stops taking clicks - the button behind it opens the list instead, which is the whole
   40px square. */
@media (hover: none) {
  .tool-group-caret {
    pointer-events: none;
    color: #8E8E93;
  }
}

.tool-group:hover .tool-group-caret,
.tool-group-caret.open {
  color: #1D1D1F;
}


.dark-mode .tool-group-caret {
  color: #6E6E6E;
}

.dark-mode .tool-group:hover .tool-group-caret,
.dark-mode .tool-group-caret.open {
  color: #F7F7F7;
}


/* The panel the caret opens. Fixed and positioned from a measurement of the rail button,
   so it clears the rail's own overflow; the coordinates below are where it lands beside a
   rail resting at the top, and stand in for the frame before that measurement arrives. */
.tool-flyout {
  position: fixed;
  left: 52px;
  top: 96px;
  z-index: 1201;
  display: flex;
  flex-direction: column;
  min-width: 200px;
  padding: 6px;
  background: rgba(255, 255, 255, 0.98);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 12px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.16);
  max-height: calc(100vh - 16px);
  overflow-y: auto;
  /* a finger scrolling to the last tool must not carry on into the chart behind */
  overscroll-behavior: contain;
  scrollbar-width: none;
}

.tool-flyout::-webkit-scrollbar {
  display: none;
}

/* The panel is anchored to the rail's right edge, so it comes out of the rail rather than
   appearing on top of it: a short slide rightwards from under the button that opened it.
   transform-origin keeps that edge still while the rest travels, which is what makes it
   read as unfolding from the rail instead of drifting into place.

   No scale: the panel is full of text, and scaling glyphs for a sixth of a second is the
   difference between this looking crisp and looking like it wobbles. Translate and fade
   only. The panel is mounted fresh each time it opens, so a keyframe runs on mount and
   needs no exit state - closing unmounts it. */
.tool-flyout {
  transform-origin: left center;
  animation: toolFlyoutIn 0.16s cubic-bezier(0.33, 1, 0.68, 1);
}

@keyframes toolFlyoutIn {
  from {
    opacity: 0;
    transform: translateX(-12px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .tool-flyout { animation: none; }
}

/* Das Werkzeugmenue trug seine Farbe als einziges Popover selbst - rgba(28,28,30,.98),
   heller und grauer als jedes andere. Eingesammelt wurde es nie: es fuehrt .dark-mode an
   sich selbst, und die Gruppe "Menues und Popover" am Dateiende adressiert ihre Menues
   ueber .dark-mode .x, was auf ein Element mit der Klasse an sich selbst nicht passt.

   Jetzt am selben Token wie alle anderen, damit es beim naechsten Farbwechsel nicht
   wieder allein zurueckbleibt. */
.tool-flyout.dark-mode {
  background: var(--bk-elevated);
  border-color: var(--bk-border);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.5);
}

.tool-flyout-title {
  padding: 6px 10px 4px;
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #8E8E93;
}

.tool-flyout.dark-mode .tool-flyout-title {
  color: var(--bk-text-2);
}

.tool-flyout-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  background: transparent;
  border: none;
  border-radius: 8px;
  color: #1D1D1F;
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
}

.tool-flyout-item svg {
  flex-shrink: 0;
}

.tool-flyout-label {
  flex: 1;
}

/* Pushed to the far edge and stepped down in weight: it names the key, it is not the row. */
.tool-flyout-shortcut {
  flex-shrink: 0;
  font-size: 11px;
  font-weight: 500;
  color: #8E8E93;
}

.tool-flyout-item:hover {
  background: rgba(0, 0, 0, 0.06);
}

.tool-flyout-item.active {
  background: var(--bk-active);
}

.tool-flyout.dark-mode .tool-flyout-item {
  color: #F5F5F7;
}

.tool-flyout.dark-mode .tool-flyout-shortcut {
  color: var(--bk-text-2);
}

.tool-flyout.dark-mode .tool-flyout-item:hover {
  background: rgba(255, 255, 255, 0.10);
}

.tool-flyout.dark-mode .tool-flyout-item.active {
  background: rgba(255, 255, 255, 0.15);
}

/* ========================================
   PEN TOOLBAR
   ======================================== */
.pen-toolbar {
  position: absolute;
  z-index: 100;
  background: rgba(248, 248, 248, 0.95);
  backdrop-filter: blur(40px) saturate(180%);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  border: 1px solid rgba(0, 0, 0, 0.12);
  border-radius: 12px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15), 0 0 1px rgba(0, 0, 0, 0.1);
  padding: 0;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0;
  user-select: none;
  overflow: visible;
}

.pen-toolbar-handle {
  display: flex;
  align-items: center;
  justify-content: center;
  color: #999;
  cursor: grab;
  padding: 8px 6px;
  border-right: 1px solid rgba(0, 0, 0, 0.1);
  min-height: 36px;
}

.pen-toolbar-handle:active {
  cursor: grabbing;
}

.pen-toolbar-handle svg {
  opacity: 0.3;
}

.pen-toolbar-controls {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0;
  padding: 0;
}

.pen-toolbar-section {
  display: flex;
  flex-direction: row;
  align-items: center;
  padding: 0 6px;
  border-right: 1px solid rgba(0, 0, 0, 0.1);
  min-height: 36px;
  gap: 4px;
  position: relative;
}

.pen-toolbar-section:last-of-type {
  border-right: none;
}

.pen-toolbar-section.pen-dropdown-section {
  padding: 0;
}

/* A line's toolbar carries four controls; a text's carries eight - colour, size, bold,
   italic, background, border, edit and delete - and eight in a row is about 450px, which is
   wider than a phone. The layout effect that keeps this toolbar inside the chart can move a
   box that would hang off the edge, but it cannot make one narrower than the window, so
   the far end simply left the screen with the delete button on it.

   Wrapping to a second row rather than scrolling: every control stays visible and none of
   them is behind a gesture. The cap is on the toolbar so the handle counts towards it, and
   the wrap is on the row inside, which is what actually holds the sections. */
@media (max-width: 768px), (max-height: 500px) and (orientation: landscape) {
  .pen-toolbar {
    max-width: calc(100vw - 16px);
  }

  .pen-toolbar-controls {
    flex-wrap: wrap;
  }

  /* mobile.css floors every button at 44px square with 8px/12px padding. That is the right
     size for a button on its own and the wrong one for a strip of up to eight of them laid
     over a phone-sized chart: with the wrap above it turned the toolbar into a block three
     rows deep. These come back to the size they are on the desktop.

     Every selector is prefixed with .pen-toolbar on purpose. The floor is set on a bare
     `button`, and the toolbar's own sizes are declared further down this file than the
     media query sits, so a one-class selector here would lose on order to the first and on
     nothing to the second. Two classes wins both, wherever the block ends up. */
  .pen-toolbar button {
    min-height: 34px;
    min-width: 0;
    padding: 0 5px;
  }

  .pen-toolbar .pen-tool-btn {
    width: 32px;
    height: 32px;
    min-height: 32px;
    padding: 0;
  }

  .pen-toolbar .pen-toolbar-section,
  .pen-toolbar .pen-toolbar-handle {
    min-height: 34px;
  }

  .pen-toolbar .pen-toolbar-section {
    padding: 0 4px;
    gap: 3px;
  }

  .pen-toolbar .pen-current-color,
  .pen-toolbar .pen-current-thickness {
    min-height: 34px;
    padding: 0 6px;
    gap: 4px;
  }

  .pen-toolbar .pen-toolbar-handle {
    padding: 6px 4px;
  }

  .pen-toolbar .pen-color-display {
    width: 20px;
    height: 20px;
  }
}

.pen-tool-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 8px;
  color: #666;
  cursor: pointer;
  transition: all 0.2s ease;
}

.pen-tool-btn:hover {
  background: rgba(0, 0, 0, 0.05);
  border-color: rgba(0, 0, 0, 0.1);
  color: #333;
}

.pen-tool-btn.active {
  background: rgba(0, 0, 0, 0.08);
  border-color: rgba(0, 0, 0, 0.15);
  color: #000;
}

/* Color Selector */
.pen-current-color {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 8px;
  min-height: 36px;
  background: transparent;
  border: none;
  cursor: pointer;
  transition: all 0.2s ease;
  border-right: 1px solid rgba(0, 0, 0, 0.1);
}

.pen-current-color:hover {
  background: rgba(0, 0, 0, 0.05);
}

.pen-color-display {
  width: 22px;
  height: 22px;
  border-radius: 4px;
  border: 2px solid rgba(0, 0, 0, 0.15);
  position: relative;
}

.pen-color-display::after {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: 4px;
  border: 1px solid rgba(0, 0, 0, 0.2);
  pointer-events: none;
}

.pen-dropdown-icon {
  color: #999;
  transition: transform 0.2s ease;
}

.pen-current-color:hover .pen-dropdown-icon {
  color: #333;
}

/* Color Dropdown */
.pen-color-dropdown {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  background: rgba(248, 248, 248, 0.98);
  backdrop-filter: blur(40px);
  border: 1px solid rgba(0, 0, 0, 0.15);
  border-radius: 12px;
  padding: 12px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
  z-index: 1000;
  animation: dropdownSlideIn 0.2s ease-out;
}

.pen-color-grid {
  display: grid;
  grid-template-columns: repeat(10, 1fr);
  gap: 6px;
  max-width: 280px;
}

.pen-color-swatch {
  width: 22px;
  height: 22px;
  border-radius: 8px;
  border: 2px solid transparent;
  cursor: pointer;
  transition: all 0.2s ease;
  position: relative;
}

.pen-color-swatch::after {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: 8px;
  border: 1px solid rgba(0, 0, 0, 0.3);
  pointer-events: none;
}

.pen-color-swatch:hover {
  ;
  border-color: rgba(0, 0, 0, 0.3);
  z-index: 1;
}

.pen-color-swatch.active {
  border-color: #000;
  transform: scale(1.15);
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.2);
}

/* Thickness Selector */
.pen-current-thickness {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 8px;
  min-height: 36px;
  background: transparent;
  border: none;
  cursor: pointer;
  transition: all 0.2s ease;
  border-right: 1px solid rgba(0, 0, 0, 0.1);
}

.pen-current-thickness:hover {
  background: rgba(0, 0, 0, 0.05);
}

.pen-thickness-text {
  font-size: 11px;
  font-weight: 600;
  color: #666;
  min-width: 28px;
  text-align: center;
}

.pen-current-thickness:hover .pen-thickness-text {
  color: #333;
}

/* Thickness Dropdown */
.pen-thickness-dropdown {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  background: rgba(248, 248, 248, 0.98);
  backdrop-filter: blur(40px);
  border: 1px solid rgba(0, 0, 0, 0.15);
  border-radius: 12px;
  padding: 8px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
  z-index: 1000;
  min-width: 140px;
  animation: dropdownSlideIn 0.2s ease-out;
}

.pen-thickness-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 12px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.2s ease;
  color: #666;
  width: 100%;
}

.pen-thickness-option:hover {
  background: rgba(0, 0, 0, 0.05);
  border-color: rgba(0, 0, 0, 0.1);
  color: #333;
}

.pen-thickness-option.active {
  background: rgba(0, 0, 0, 0.08);
  border-color: rgba(0, 0, 0, 0.15);
  color: #000;
}

.pen-thickness-option span {
  font-size: 11px;
  font-weight: 600;
  min-width: 28px;
}

/* Thirteen sizes rather than the six thicknesses this dropdown was built for, which is
   more than fits above the chart's bottom edge. */
.pen-font-size-dropdown {
  max-height: 260px;
  overflow-y: auto;
}

/* B and I are letters, not icons - they carry the style they switch on, which is the whole
   convention, so they need a text size where the other buttons in this row set an SVG. */
.pen-text-style-btn {
  font-family: 'Outfit', sans-serif;
  font-size: 15px;
  line-height: 1;
}

@keyframes dropdownSlideIn {
  from {
    opacity: 0;
    transform: translateY(-8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.pen-clear-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 8px;
  background: transparent;
  border: none;
  color: #FF3B30;
  cursor: pointer;
  transition: all 0.2s ease;
  min-height: 36px;
  white-space: nowrap;
}

.pen-clear-btn:hover {
  background: rgba(255, 59, 48, 0.1);
  color: #FF3B30;
}

.pen-clear-btn svg {
  color: currentColor;
}

/* Opacity Control */
.pen-opacity-control {
  padding: 12px;
  border-top: 1px solid rgba(0, 0, 0, 0.1);
}

/* Custom Color Adder */
.custom-color-adder {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  background: rgba(248, 248, 248, 0.98);
  backdrop-filter: blur(40px);
  border: 1px solid rgba(0, 0, 0, 0.15);
  border-radius: 12px;
  padding: 12px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
  z-index: 10001;
  display: flex;
  flex-direction: column;
}

/* The hex field, Cancel and Add share one row inside a panel about 252px wide. The field
   was flex:1 with the default min-width:auto, so it could not shrink below an input's
   intrinsic width (~177px) - the row measured ~320px and pushed Add out past the right
   edge of the menu, reachable only by scrolling sideways. The field is now sized to its
   content (#RRGGBB is seven characters) and the two buttons split what is left. */
.custom-color-header {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-bottom: 12px;
}

.custom-color-hex-input {
  flex: 0 0 auto;
  width: 88px;
  min-width: 0;
  height: 32px;
  padding: 0 8px;
  border-radius: 6px;
  border: 1px solid rgba(0, 0, 0, 0.2);
  font-size: 13px;
  font-family: 'SF Mono', 'Monaco', 'Courier New', monospace;
  text-transform: uppercase;
  background: white;
  color: #000;
}

.custom-color-hex-input:focus {
  outline: none;
  border-color: #007AFF;
  box-shadow: 0 0 0 3px rgba(0, 122, 255, 0.1);
}

.custom-color-add-btn {
  flex: 1 1 0;
  min-width: 0;
  white-space: nowrap;
  height: 32px;
  padding: 0 8px;
  border-radius: 8px;
  border: none;
  background: #007AFF;
  color: white;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s ease;
}

.custom-color-add-btn:hover {
  background: #0051D5;
}

.custom-color-cancel-btn {
  flex: 1 1 0;
  min-width: 0;
  white-space: nowrap;
  height: 32px;
  padding: 0 8px;
  border-radius: 8px;
  border: 1px solid rgba(0, 0, 0, 0.2);
  background: transparent;
  color: #000;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s ease;
}

.custom-color-cancel-btn:hover {
  background: rgba(0, 0, 0, 0.05);
}

.custom-color-picker-container {
  display: flex;
  gap: 8px;
}

.custom-color-spectrum {
  flex: 1;
  height: 140px;
  border-radius: 6px;
  position: relative;
  cursor: crosshair;
  border: 1px solid rgba(0, 0, 0, 0.15);
}

.custom-color-marker {
  position: absolute;
  width: 12px;
  height: 12px;
  border: 2px solid white;
  border-radius: 50%;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
  transform: translate(-50%, -50%);
  pointer-events: none;
}

.custom-color-hue-slider {
  width: 20px;
  height: 140px;
  border-radius: 6px;
  position: relative;
  cursor: pointer;
  border: 1px solid rgba(0, 0, 0, 0.15);
  background: linear-gradient(to bottom,
    hsl(0, 100%, 50%),
    hsl(60, 100%, 50%),
    hsl(120, 100%, 50%),
    hsl(180, 100%, 50%),
    hsl(240, 100%, 50%),
    hsl(300, 100%, 50%),
    hsl(360, 100%, 50%)
  );
}

.custom-color-hue-marker {
  position: absolute;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 24px;
  height: 6px;
  border: 2px solid white;
  border-radius: 3px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
  pointer-events: none;
}

.color-picker-add-btn {
  width: 20px;
  height: 20px;
  border-radius: 8px;
  border: none;
  background: transparent;
  cursor: pointer;
  font-size: 18px;
  font-weight: 300;
  color: rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s ease;
  box-sizing: border-box;
}

.color-picker-add-btn:hover {
  color: #007AFF;
  background: rgba(0, 122, 255, 0.08);
}

/* Custom Colors Row */
.custom-colors-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid rgba(0, 0, 0, 0.1);
}

.custom-color-swatch-wrapper {
  position: relative;
  display: inline-block;
}

.custom-color-swatch-wrapper .color-picker-swatch {
  width: 20px;
  height: 20px;
}

/* The remove button used to hang 6px past the top-right of a 20px swatch, so every saved
   colour had a red dot sitting outside its own outline and over its neighbour. It covers
   the swatch instead now - inset to the same rounding, so nothing is drawn outside the
   square - and only appears under the pointer, which leaves a row of plain colours at rest. */
.custom-color-delete {
  position: absolute;
  inset: 0;
  /* The swatch it covers, not the wrapper it sits in - inherit would take the wrapper's
     square corners and put a hard-edged box over a rounded colour. */
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.55);
  color: white;
  border: none;
  cursor: pointer;
  font-size: 13px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.14s ease;
  padding: 0;
  transition: all 0.2s ease;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

/* Right-click a saved colour to arm its remove button; anything else puts it away. On
   hover it appeared the moment the pointer crossed a swatch, so picking a colour meant
   passing under a delete button on the way to it. */
.custom-color-swatch-wrapper.delete-armed .custom-color-delete {
  opacity: 1;
  pointer-events: auto;
}

.custom-color-delete:hover {
  background: rgba(215, 0, 21, 0.8);
}

.pen-opacity-label {
  font-size: 11px;
  font-weight: 600;
  color: #666;
  margin-bottom: 8px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.pen-opacity-slider-wrapper {
  display: flex;
  align-items: center;
  gap: 10px;
}

.pen-opacity-slider {
  flex: 1;
  height: 4px;
  border-radius: 2px;
  background: rgba(0, 0, 0, 0.1);
  outline: none;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

.pen-opacity-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #007AFF;
  border: 2px solid #FFFFFF;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  cursor: pointer;
  transition: all 0.2s ease;
}

.pen-opacity-slider::-webkit-slider-thumb:hover {
  ;
  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3);
}

.pen-opacity-slider::-moz-range-thumb {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #007AFF;
  border: 2px solid #FFFFFF;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  cursor: pointer;
  transition: all 0.2s ease;
}

.pen-opacity-slider::-moz-range-thumb:hover {
  ;
  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3);
}

.pen-opacity-value {
  font-size: 11px;
  font-weight: 600;
  color: #666;
  min-width: 38px;
  text-align: right;
}

.drawing-popup {
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(40px) saturate(180%);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 12px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.12);
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 160px;
}

.drawing-popup.dark-mode {
  background: rgba(30, 30, 30, 0.92);
  border: 1px solid var(--bk-border);
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
}

.drawing-popup-colors {
  display: flex;
  gap: 6px;
  align-items: center;
  flex-wrap: wrap;
}

.drawing-popup-color-btn {
  width: 100%;
  padding: 8px;
  background: rgba(16, 185, 129, 0.1);
  border: 1px solid rgba(16, 185, 129, 0.2);
  border-radius: 8px;
  color: #10B981;
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.15s ease;
}

.drawing-popup.dark-mode .drawing-popup-color-btn {
  background: rgba(16, 185, 129, 0.15);
  border: 1px solid rgba(16, 185, 129, 0.3);
  color: #34D399;
}

.drawing-popup-color-btn:hover {
  background: rgba(16, 185, 129, 0.15);
  border-color: rgba(16, 185, 129, 0.4);
  ;
}

.drawing-popup.dark-mode .drawing-popup-color-btn:hover {
  background: rgba(16, 185, 129, 0.25);
  border-color: rgba(16, 185, 129, 0.5);
}

.drawing-popup-delete {
  width: 100%;
  padding: 8px;
  background: rgba(255, 59, 48, 0.1);
  border: 1px solid rgba(255, 59, 48, 0.2);
  border-radius: 8px;
  color: #FF3B30;
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.15s ease;
}

.drawing-popup.dark-mode .drawing-popup-delete {
  background: rgba(255, 59, 48, 0.15);
  border: 1px solid rgba(255, 59, 48, 0.3);
  color: #FF6B6B;
}

.drawing-popup-delete:hover {
  background: rgba(255, 59, 48, 0.15);
  border-color: rgba(255, 59, 48, 0.4);
  ;
}

.drawing-popup.dark-mode .drawing-popup-delete:hover {
  background: rgba(255, 59, 48, 0.25);
  border-color: rgba(255, 59, 48, 0.5);
}

/* The text tool's inline editor.

   This replaces a small floating panel that held a 13px input at a fixed 160px, sitting
   ten pixels to the right of wherever the click landed. Everything about the words was
   decided in one place and shown in another: you typed grey 13px text in a white box, then
   pressed Enter and something else appeared on the chart. Here the caret is put on the
   chart itself, and the component sets the colour, size, weight and slant inline so what
   is being typed is already the drawing.

   Fixed rather than absolute: the offset is written from the chart container's own
   bounding rect on every frame, which is what keeps the box on its candle through panning,
   zooming and autoscale alike, and does not care where this element sits in the tree.

   No fill and no shadow - it is text on a chart, not a panel over one. The hairline is the
   only chrome, and it is there because an empty editor would otherwise be a bare caret
   with nothing to say a box is waiting for words. Neutral grey so it reads on both themes
   without a theme class, the way the other theme-agnostic hairlines here do.

   resize and overflow are off because the box is sized to its content from JS; a scrollbar
   or a drag corner inside a caret-sized box is noise. white-space: pre stops the textarea
   wrapping at its current width, so a long line grows the box sideways instead of folding
   - line breaks come from the Return key and nowhere else. */
.chart-text-editor {
  position: fixed;
  z-index: 200;
  margin: 0;
  min-width: 10px;
  /* mobile.css floors every textarea at 44px so a form field is comfortable to tap. This
     is not a form field - it is a caret sitting on the chart, sized to the glyphs it holds
     - and the floor made a single line of 14px text open as a 50px box with the words
     stranded at the top of it. The height comes from the content, at any width. */
  min-height: 0;
  border: none;
  outline: none;
  resize: none;
  overflow: hidden;
  background: transparent;
  /* border-box, not content-box. The size is written from scrollWidth/scrollHeight, and
     those already include the padding - so as a content box the 6px of padding was counted
     a second time and the field came out 6px taller and 12px wider than the text inside
     it. All of that slack landed below and to the right of the words, because the content
     sits top-left, which is the box looking too big at the bottom. */
  box-sizing: border-box;
  font-family: 'Outfit', sans-serif;
  white-space: pre;
  caret-color: currentColor;
  box-shadow: 0 0 0 1px rgba(142, 142, 147, 0.5);
  border-radius: 3px;
}

/* Context Menu */
.context-menu-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 249;
}

.context-menu {
  position: fixed;
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(40px) saturate(180%);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 12px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15);
  padding: 8px;
  min-width: 180px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  z-index: 250;
}

.context-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 12px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 8px;
  color: #1D1D1F;
  font-family: 'Outfit', sans-serif;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.15s ease;
}

.context-menu-item:hover {
  border-color: rgba(142, 142, 147, 0.2);
  background: rgba(142, 142, 147, 0.08);
  color: #8E8E93;
}

.context-menu-item svg {
  color: #8E8E93;
}

/* Keyboard hint, pushed to the right edge of the item */
.context-menu-shortcut {
  margin-left: auto;
  padding-left: 16px;
  color: #8E8E93;
  font-size: 11px;
  font-weight: 400;
  white-space: nowrap;
}

/* Context Menu - Dark Mode. Same treatment as .drawing-popup.dark-mode: both are
   blurred floating popups over the chart, so they share a surface. */
.dark-mode .context-menu {
  background: rgba(30, 30, 30, 0.92);
  border: 1px solid var(--bk-border);
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
}

.dark-mode .context-menu-item {
  color: #F7F7F7;
}

/* Light mode dims the label to grey on hover; keep that shift, but stop at a grey
   that still reads against the dark surface. */
.dark-mode .context-menu-item:hover {
  border-color: rgba(255, 255, 255, 0.15);
  background: rgba(255, 255, 255, 0.08);
  color: var(--bk-text-2);
}

/* The hint stays quieter than the label it sits next to, in both themes. */
.dark-mode .context-menu-shortcut {
  color: var(--bk-text-3);
}

.dark-mode .context-menu-item:hover .context-menu-shortcut {
  color: var(--bk-text-2);
}

/* Settings Modal */
.settings-modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: transparent;
  z-index: 300;
  display: flex;
  align-items: center;
  justify-content: center;
}

.chart-settings-modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 520px;
  max-height: 80vh;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(40px);
  -webkit-backdrop-filter: blur(40px);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 16px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
  z-index: 9999;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.chart-settings-header {
  padding: 20px 24px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.chart-settings-header h3 {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 20px;
  color: #1D1D1F;
  margin: 0;
}

.settings-modal-close {
  background: transparent;
  border: none;
  color: #1D1D1F;
  font-size: 24px;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 6px;
  transition: all 0.15s ease;
  line-height: 1;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.settings-modal-close:hover {
  background: rgba(0, 0, 0, 0.05);
}

.chart-settings-color-picker {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 8px;
  width: 278px;
  background: rgba(248, 248, 248, 0.98);
  backdrop-filter: blur(40px);
  -webkit-backdrop-filter: blur(40px);
  border: 1px solid rgba(0, 0, 0, 0.15);
  border-radius: 10px;
  padding: 12px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
  z-index: 10000;
  animation: dropdownSlideIn 0.2s ease-out;
}

.color-picker-grid {
  display: grid;
  grid-template-columns: repeat(10, 1fr);
  gap: 6px;
  width: 254px;
  margin: 0 auto;
}

.color-picker-swatch {
  width: 20px;
  height: 20px;
  border-radius: 8px;
  border: 2px solid transparent;
  cursor: pointer;
  padding: 0;
  transition: all 0.2s ease;
  position: relative;
  box-sizing: border-box;
}

/* mobile.css gives every button a touch-target floor - 44px under 768px, 40px on a tablet,
   36px in short landscape. A colour swatch is a button, so inside those ranges the ten 20px
   columns were forced up to 36-40px each and the grid burst out of its 254px box: four of
   the ten columns ended up outside the menu and could not be clicked at all. These controls
   are sized by the grid around them, and the class beats the bare button selector on
   specificity, so this holds in every one of those ranges. */
.color-picker-swatch,
.color-picker-add-btn,
.custom-color-delete {
  min-width: 0;
  min-height: 0;
}

/* The outline that keeps a white swatch visible against a light menu. It was drawn 1px
   outside the swatch and at a 3px radius against the fill's 8px, so a well-rounded colour
   sat inside a squarer ring: the colour crossed the line along each edge and left a gap at
   every corner. Same radius, same box - the ring now traces the colour exactly. */
.color-picker-swatch::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  border: 1px solid rgba(0, 0, 0, 0.3);
  pointer-events: none;
}

.color-picker-swatch:hover {
  ;
  border-color: rgba(0, 0, 0, 0.3);
  z-index: 1;
}

.color-picker-swatch.active {
  border-color: #000;
  transform: scale(1.15);
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.2);
}

.chart-wrapper {
  flex: 1;
  position: relative;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.4);
  backdrop-filter: blur(40px) saturate(180%);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  margin: 8px;
  border-radius: 16px;
  border: 1px solid var(--bk-border);
  box-shadow: 0 8px 32px rgba(142, 142, 147, 0.08),
    inset 0 1px 0 rgba(255, 255, 255, 0.8);
  z-index: 1;
}

.chart {
  position: relative;
  width: 100%;
  height: 100%;
  background: rgba(255, 255, 255, 0);
  border-radius: 16px;
  overflow: hidden;
}

/* Loading Overlay */
.loading-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(255, 255, 255, 0.3);
  z-index: 100;
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
}

.loading-box {
  padding: 20px 40px;
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(40px) saturate(180%);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 16px;
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 14px;
  color: #1D1D1F;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.12);
}

/* ========================================
   BACKTEST FLOATING CARD
   ======================================== */
.backtest-card {
  position: absolute;
  top: 8px;
  right: 85px;
  width: 240px;
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(40px) saturate(180%);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 16px;
  padding: 16px;
  z-index: 50;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.12);
}

.backtest-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.backtest-title {
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 11px;
  letter-spacing: 0.08em;
  color: #48484A;
  text-transform: uppercase;
}

.close-btn {
  background: none;
  border: none;
  color: var(--text-secondary);
  font-size: 20px;
  line-height: 1;
  padding: 0;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all var(--transition-speed) ease;
}

.close-btn:hover {
  color: var(--text-primary);
}

.backtest-stats {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 16px;
}

.stat-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.stat-row.highlight {
  padding: 12px;
  background: rgba(142, 142, 147, 0.08);
  border: 1px solid rgba(142, 142, 147, 0.2);
  border-radius: 10px;
  margin: 4px 0;
}

.stat-label {
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 11px;
  color: #48484A;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.stat-value {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 14px;
  color: #1D1D1F;
}

.stat-value-large {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 24px;
  color: #1D1D1F;
}

.apply-best-btn {
  width: 100%;
  padding: 10px;
  background: rgba(142, 142, 147, 0.1);
  color: #8E8E93;
  border: 1px solid rgba(142, 142, 147, 0.2);
  border-radius: 10px;
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 13px;
  transition: all var(--transition-speed) ease;
}

.apply-best-btn:hover {
  background: rgba(142, 142, 147, 0.15);
  border-color: rgba(142, 142, 147, 0.3);
  box-shadow: 0 2px 12px rgba(142, 142, 147, 0.2);
  ;
}

/* Backtesting Dashboard (Top-Right Permanent) */
/* Backtest Results in Settings Modal */
.indicator-backtest-results {
  margin-top: 16px;
  padding: 16px;
  background: rgba(142, 142, 147, 0.08);
  border: 1px solid rgba(142, 142, 147, 0.2);
  border-radius: 12px;
}

.backtest-results-header {
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(142, 142, 147, 0.2);
}

.backtest-results-title {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 10px;
  letter-spacing: 0.1em;
  color: #48484A;
  text-transform: uppercase;
}

.backtest-results-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-bottom: 12px;
}

.backtest-result-item {
  padding: 10px;
  background: rgba(255, 255, 255, 0.5);
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.backtest-result-item.best {
  grid-column: 1 / -1;
  background: rgba(16, 185, 129, 0.1);
  border: 1px solid rgba(16, 185, 129, 0.3);
}

.backtest-result-label {
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 9px;
  color: #8E8E93;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.backtest-result-value {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 13px;
  color: #1D1D1F;
}

.backtest-result-value.highlight {
  font-size: 18px;
  font-weight: 700;
  color: #10B981;
}

.apply-backtest-btn {
  width: 100%;
  padding: 10px;
  background: rgba(16, 185, 129, 0.15);
  color: #10B981;
  border: 1px solid rgba(16, 185, 129, 0.3);
  border-radius: 8px;
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 12px;
  transition: all var(--transition-speed) ease;
  cursor: pointer;
}

.apply-backtest-btn:hover {
  background: rgba(16, 185, 129, 0.25);
  border-color: rgba(16, 185, 129, 0.5);
  box-shadow: 0 2px 12px rgba(16, 185, 129, 0.3);
  ;
}

/* ========================================
   BOTTOM STRIP
   ======================================== */
.bottom-strip {
  height: 44px;
  background: rgba(255, 255, 255, 0.8);
  backdrop-filter: blur(80px) saturate(200%);
  -webkit-backdrop-filter: blur(80px) saturate(200%);
  border-top: 1px solid rgba(0, 0, 0, 0.08);
  display: flex;
  align-items: center;
  padding: 0 12px;
  margin-left: 52px;
  gap: 15px;
  flex-shrink: 0;
  box-shadow: 0 -1px 3px rgba(0, 0, 0, 0.05);
  border-radius: 12px 12px 0 0;
  /* Scroll horizontally instead of overlapping when the window is too narrow */
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}

.bottom-strip::-webkit-scrollbar {
  display: none;
}

.strip-item {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
}

.strip-label {
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 10px;
  color: #8E8E93;
  letter-spacing: 0.15em;
  text-transform: uppercase;
}

.strip-value {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 13px;
  color: #1D1D1F;
}

.strip-value.trend-up {
  color: var(--success-green);
}

.strip-value.trend-down {
  color: var(--danger-red);
}

.time-display {
  transition: opacity 0.2s ease;
  user-select: none;
}

.time-display:hover {
  opacity: 0.7;
}

/* ========================================
   SYMBOL MODAL
   ======================================== */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.25);
  z-index: 1500;
  display: flex;
  align-items: center;
  justify-content: center;
}

.symbol-modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 760px;
  max-width: calc(100vw - 32px);
  max-height: 82vh;
  background: rgba(255, 255, 255, 0.88);
  backdrop-filter: blur(60px) saturate(180%);
  -webkit-backdrop-filter: blur(60px) saturate(180%);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 16px;
  z-index: 1501;
  display: flex;
  flex-direction: column;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.18);
  overflow: hidden;
}

.modal-header {
  padding: 22px 24px 16px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.modal-header h3 {
  font-family: var(--font-ui);
  font-weight: 800;
  font-size: 26px;
  color: #1D1D1F;
  margin: 0;
  letter-spacing: -0.01em;
}

/* The padding above was 0, so the field sat flush against the header's bottom edge with
   16px of air below it - which is what made it look cut off along its top rather than
   spaced. Matching the two also fixes the icon: it centres on 50% of this box, and while
   the padding was lopsided that put it eight pixels below the middle of the field it is
   supposed to sit inside. */
.modal-search {
  position: relative;
  padding: 14px 24px;
}

.modal-search-icon {
  position: absolute;
  left: 38px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-secondary);
  pointer-events: none;
}

.modal-search input {
  width: 100%;
  padding: 12px 16px 12px 42px;
  background: rgba(120, 120, 128, 0.08);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 10px;
  color: var(--text-primary);
  font-family: var(--font-ui);
  font-size: 14.5px;
  font-weight: 500;
  /* A ring of the same geometry at zero alpha, so focusing grows one rather than
     switching it on: box-shadow interpolates layer by layer, and from "none" the
     first frame is already the full 3px. */
  box-shadow: 0 0 0 0 rgba(142, 142, 147, 0);
  /* Named properties rather than "all" - "all" also animated the border-radius and
     the text colour on every state change, which is what made the field look like it
     was settling rather than responding. */
  transition: border-color 0.18s ease, background-color 0.18s ease, box-shadow 0.18s ease;
}

.modal-search input::placeholder {
  color: var(--text-secondary);
}

/* Category Filter Buttons */
.category-filters {
  display: flex;
  flex-shrink: 0;
  gap: 6px;
  padding: 0 24px 16px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}

.category-filters::-webkit-scrollbar {
  display: none;
}

.category-btn {
  flex: none;
  padding: 7px 14px;
  background: transparent;
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 8px;
  color: var(--text-secondary);
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: all var(--transition-speed) ease;
  white-space: nowrap;
}

.category-btn:hover {
  color: var(--text-primary);
  border-color: rgba(0, 0, 0, 0.22);
}

.category-btn.active {
  background: #1D1D1F;
  color: #FFFFFF;
  border-color: #1D1D1F;
}

.category-btn.active:hover {
  background: #000000;
  border-color: #000000;
}

.modal-content {
  flex: 1;
  overflow-y: auto;
  padding: 8px 0 12px;
}

.symbol-section {
  margin-bottom: 4px;
}

.symbol-section:last-child {
  margin-bottom: 0;
}

.section-header {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.08em;
  color: #8E8E93;
  padding: 12px 24px 6px;
  text-transform: uppercase;
}

/* The "NQ is coming soon, use NAS100" note at the top of the symbol search. Tinted with NAS100's own blue rather than a theme colour, so it reads the
   same on light and dark. */
.nq-notice {
  margin: 8px 16px 6px;
  padding: 12px 14px;
  border-radius: 12px;
  background: rgba(10, 132, 255, 0.08);
  border: 1px solid rgba(10, 132, 255, 0.28);
  font-family: var(--font-ui);
  animation: nq-notice-in 0.18s ease-out;
}

@keyframes nq-notice-in {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}

.nq-notice-title {
  font-size: 13px;
  font-weight: 700;
  color: #0A84FF;
  margin-bottom: 4px;
}

.nq-notice-text {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.45;
  /* Set outright: the modal's inherited colour is the dark theme's near-white even in
     light mode, since every row sets its own. */
  color: #3A3A3C;
}

.dark-mode .nq-notice-text {
  color: var(--bk-text-2);
}

.nq-notice-text strong {
  color: #1D1D1F;
}

.dark-mode .nq-notice-text strong {
  color: #F7F7F7;
}

.nq-notice-btn {
  margin-top: 10px;
  padding: 7px 14px;
  border: none;
  border-radius: 8px;
  background: #0A84FF;
  color: #FFFFFF;
  font-family: var(--font-ui);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}

.nq-notice-btn:hover {
  background: #0071E3;
}

.nq-notice-current {
  margin-top: 8px;
  font-size: 12px;
  font-weight: 600;
  color: #0A84FF;
}

.soon-badge {
  font-size: 9px;
  padding: 2px 8px;
  background-color: rgba(142, 142, 147, 0.1);
  color: #8E8E93;
  border-radius: 10px;
  font-weight: 600;
  letter-spacing: 0.5px;
}

.symbol-list {
  display: flex;
  flex-direction: column;
}

.symbol-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 24px;
  background: transparent;
  border: none;
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
  font-family: var(--font-ui);
  color: var(--text-primary);
  text-align: left;
  transition: background var(--transition-speed) ease;
  cursor: pointer;
  width: 100%;
}

.symbol-section:last-child .symbol-list .symbol-item:last-child {
  border-bottom: none;
}

.symbol-logo {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  color: white;
  font-weight: 700;
  flex-shrink: 0;
  overflow: hidden;
}

/* Ein Firmenzeichen sitzt IM Kreis, nicht auf ihm.

   Die Kachel ist rund und schneidet ab, was ueber sie hinausgeht. Krypto- und
   Flaggensymbole sind selbst als randlose Scheibe gezeichnet - sie sind der Kreis und
   sollen ihn ausfuellen. Ein Firmenzeichen ist dagegen ein Quadrat oder ein Schriftzug
   auf nichts: auf volle Breite gelegt schnitt der Radius ihm die Ecken ab, was man an
   Microsofts vier Quadraten sofort sah.

   18 Prozent, weil ein Quadrat nur bis 70,7 Prozent des Durchmessers in seinen Kreis
   passt (die Seite betraegt d/Wurzel 2). Das laesst 64 Prozent, also etwas Luft, statt
   das Zeichen genau an die Kante zu setzen - und ergibt nebenbei die Groesse, die man
   von einer Marktliste kennt.

   Die Klasse setzt SymbolLogo nur fuer selbst gehostete Zeichen; die entfernten URLs der
   Krypto-Eintraege bleiben unberuehrt. */
.symbol-logo.is-company-mark img,
.symbol-logo-small.is-company-mark img,
.asset-ticker-logo.is-company-mark img,
.wl-row-logo.is-company-mark img {
  box-sizing: border-box;
  padding: 18%;
}

/* Breite Schriftzuege. 18 Prozent sind fuer ein quadratisches Zeichen gedacht, dessen
   Ecken sonst am Radius haengen; auf einem Schriftzug im Verhaeltnis 9:1 schneiden sie
   einen ohnehin duennen Streifen auf zwei Pixel herunter. Hier bleibt nur so viel Rand,
   dass das Zeichen die Kante nicht beruehrt - in der Waagerechten durch die Mitte ist
   der Kreis so breit wie sein Durchmesser, es wird also nichts abgeschnitten.
   Die Klasse setzt SymbolLogo aus den Proportionen der Datei selbst, nicht aus einer
   Liste: eine neue Wortmarke bekommt sie damit von allein. */
.symbol-logo.is-wide-mark img,
.symbol-logo-small.is-wide-mark img,
.asset-ticker-logo.is-wide-mark img,
.wl-row-logo.is-wide-mark img {
  padding: 0 6%;
}

/* Die helle Scheibe darunter. Ein Firmenzeichen ist in seinen eigenen Farben
   gezeichnet und fuer hellen Grund gemacht, also bekommt es hier einen - im
   Dunkelmodus stand Metas Blau auf #101010 fast nicht mehr, und ein Zeichen aus
   reiner dunkler Tinte waere gar nicht zu sehen gewesen. Die Alternative waere,
   die Marke selbst aufzuhellen, und an einer geschuetzten Marke wird nichts
   umgefaerbt.

   Das ist auch, was in der Marktliste von TradingView zu sehen ist, nur an anderer
   Stelle: dort steckt die Scheibe in der Symboldatei selbst, weshalb deren Kachel
   ohne Hintergrund und ohne Innenabstand auskommt. Unsere Dateien sind die blanken
   Zeichen, also zeichnen wir die Scheibe. */
.symbol-logo.is-company-mark,
.symbol-logo-small.is-company-mark,
.asset-ticker-logo.is-company-mark,
.wl-row-logo.is-company-mark {
  background: var(--bk-mark-disc);
}

.symbol-item-main {
  display: flex;
  align-items: baseline;
  gap: 9px;
  flex: 1;
  min-width: 0;
}

.symbol-ticker {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 14.5px;
  letter-spacing: 0.2px;
  color: var(--text-primary);
  flex-shrink: 0;
}

.symbol-fullname {
  font-size: 13px;
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.symbol-item-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
  justify-content: flex-end;
  min-width: 150px;
}

.symbol-type {
  font-size: 12px;
  color: var(--text-secondary);
  text-transform: lowercase;
  white-space: nowrap;
}

.symbol-source {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-primary);
  white-space: nowrap;
}

.symbol-favorite-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 8px;
  border: none;
  background: transparent;
  color: #C7C7CC;
  font-size: 16px;
  cursor: pointer;
  transition: opacity var(--transition-speed) ease, color var(--transition-speed) ease;
  opacity: 0;
  flex-shrink: 0;
}

.symbol-item:hover .symbol-favorite-btn {
  opacity: 1;
}

/* Both row icons are SVGs of the same box, and display:block keeps them off the text
   baseline so neither picks up a descender gap and drifts against the other. */
.symbol-favorite-btn svg,
.symbol-watchlist-btn svg {
  display: block;
}

.symbol-favorite-btn.favorite {
  opacity: 1;
  color: #F5C518;
}

.symbol-favorite-btn:hover {
  color: #B17B00;
}

.symbol-watchlist-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 8px;
  border: none;
  background: transparent;
  color: #C7C7CC;
  cursor: pointer;
  transition: opacity var(--transition-speed) ease, color var(--transition-speed) ease;
  opacity: 0;
  flex-shrink: 0;
}

.symbol-item:hover .symbol-watchlist-btn {
  opacity: 1;
}

/* Filled bookmark, same as the lit star: the row has to say the symbol is already on a
   list without being hovered. */
.symbol-watchlist-btn.watched {
  opacity: 1;
  color: #0A84FF;
}

.symbol-watchlist-btn:hover {
  color: #0060DF;
}

.symbol-item:not(.disabled):hover {
  background: rgba(0, 0, 0, 0.035);
}

/* ========================================
   ADD-TO-WATCHLIST PICKER
   Sits above .symbol-modal (1501), which stays open behind it.
   ======================================== */
.watchlist-picker-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.28);
  z-index: 1600;
}

.watchlist-picker {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 380px;
  max-width: calc(100vw - 32px);
  max-height: 70vh;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(60px) saturate(180%);
  -webkit-backdrop-filter: blur(60px) saturate(180%);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 16px;
  z-index: 1601;
  display: flex;
  flex-direction: column;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.22);
  overflow: hidden;
}

.watchlist-picker-header {
  padding: 18px 20px 12px;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
}

.watchlist-picker-title {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.watchlist-picker-title h3 {
  font-family: var(--font-ui);
  font-weight: 800;
  font-size: 19px;
  color: #1D1D1F;
  margin: 0;
  letter-spacing: -0.01em;
}

.watchlist-picker-symbol {
  font-family: var(--font-mono);
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.3px;
  color: var(--text-secondary);
}

.watchlist-picker-list {
  flex: 1;
  overflow-y: auto;
  padding: 0 12px;
  min-height: 0;
}

.watchlist-picker-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 10px;
  background: transparent;
  border: none;
  border-radius: 9px;
  font-family: var(--font-ui);
  font-size: 14px;
  color: var(--text-primary);
  text-align: left;
  cursor: pointer;
  transition: background var(--transition-speed) ease;
}

.watchlist-picker-row:hover {
  background: rgba(0, 0, 0, 0.05);
}

.watchlist-picker-check {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 5px;
  border: 1.5px solid rgba(0, 0, 0, 0.18);
  color: #FFFFFF;
  flex-shrink: 0;
}

.watchlist-picker-row.checked .watchlist-picker-check {
  background: #0A84FF;
  border-color: #0A84FF;
}

.watchlist-picker-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}

.watchlist-picker-count {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-secondary);
  flex-shrink: 0;
}

.watchlist-picker-empty {
  padding: 18px 10px 22px;
  text-align: center;
  font-family: var(--font-ui);
  font-size: 13.5px;
  color: var(--text-secondary);
}

.watchlist-picker-create {
  display: flex;
  gap: 8px;
  padding: 12px 20px 18px;
  border-top: 1px solid rgba(0, 0, 0, 0.07);
}

.watchlist-picker-create input {
  flex: 1;
  min-width: 0;
  padding: 9px 12px;
  border-radius: 9px;
  border: 1px solid rgba(0, 0, 0, 0.12);
  background: rgba(255, 255, 255, 0.7);
  font-family: var(--font-ui);
  font-size: 13.5px;
  color: var(--text-primary);
  outline: none;
}

.watchlist-picker-create input:focus {
  border-color: #0A84FF;
}

.watchlist-picker-create-btn {
  padding: 9px 16px;
  border-radius: 8px;
  border: none;
  background: #0A84FF;
  color: #FFFFFF;
  font-family: var(--font-ui);
  font-size: 13.5px;
  font-weight: 700;
  cursor: pointer;
  flex-shrink: 0;
  transition: opacity var(--transition-speed) ease;
}

.watchlist-picker-create-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.symbol-item.disabled {
  opacity: 0.4;
  cursor: not-allowed;
  color: var(--text-secondary);
}

/* ========================================
   SETTINGS DRAWER
   ======================================== */
.settings-drawer {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(0.95);
  width: 480px;
  max-height: 80vh;
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(60px) saturate(180%);
  -webkit-backdrop-filter: blur(60px) saturate(180%);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 20px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15), 0 0 1px rgba(0, 0, 0, 0.05);
  z-index: 1501;
  display: flex;
  flex-direction: column;
  opacity: 0;
  pointer-events: none;
  transition: all 0.2s ease;
  overflow: hidden;
}

.settings-drawer.open {
  transform: translate(-50%, -50%) scale(1);
  opacity: 1;
  pointer-events: all;
}

.drawer-header {
  padding: 24px 24px 20px 24px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.drawer-header h3 {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 18px;
  color: #1D1D1F;
  margin: 0;
  letter-spacing: 0.5px;
}

.drawer-content {
  flex: 1;
  padding: 24px;
  overflow-y: auto;
}

/* Per-indicator settings modal (EMA/SMA/BB/VWAP/S&R). Adopts the Swift Algo X panel's
   proportions and header weight so the two read as the same surface; the rows inside use
   that panel's .indicator-param-row / .param-row-head classes directly.
   Scoped, because .drawer-header and .drawer-content are shared with the watchlist drawer. */
.settings-drawer.indicator-params-modal {
  width: 520px;
  border-radius: 16px;
}

.settings-drawer.indicator-params-modal .drawer-header {
  padding: 20px 24px;
}

.settings-drawer.indicator-params-modal .drawer-header h3 {
  font-size: 20px;
  letter-spacing: normal;
}

.form-group {
  margin-bottom: 20px;
}

.form-group label {
  display: block;
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 11px;
  color: #48484A;
  margin-bottom: 8px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.form-group input,
.form-group select {
  width: 100%;
  padding: 10px 12px;
  background: rgba(255, 255, 255, 0.8);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 10px;
  color: #1D1D1F;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 500;
  transition: all var(--transition-speed) ease;
}

.form-group input:focus,
.form-group select:focus {
  border-color: #8E8E93;
  outline: none;
  box-shadow: 0 0 0 4px rgba(142, 142, 147, 0.1);
}

.form-group-checkbox {
  display: flex;
  align-items: center;
}

.form-group-checkbox label {
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  margin: 0;
}

.form-group-checkbox input[type="checkbox"] {
  width: 18px;
  height: 18px;
  cursor: pointer;
  accent-color: var(--accent-gray);
  background-color: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-radius: 4px;
}

.form-group-checkbox span {
  font-family: var(--font-ui);
  font-weight: 500;
  font-size: 11px;
  color: #48484A;
  letter-spacing: 0.08em;
}

.apply-btn {
  width: calc(100% - 48px);
  margin: 0 24px 24px 24px;
  padding: 14px;
  background: linear-gradient(135deg, #8E8E93, #AEAEB2);
  color: white;
  border: none;
  border-radius: 12px;
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 14px;
  transition: all var(--transition-speed) ease;
  box-shadow: 0 4px 15px rgba(142, 142, 147, 0.25);
}

.apply-btn:hover {
  ;
  box-shadow: 0 6px 25px rgba(142, 142, 147, 0.35);
}

/* The same wash the centred dialogs use - see .modal-overlay, which this matches on
   purpose. In dark mode this used to turn white at 20%, and a white veil over a black
   chart does not read as "dimmed" but as fogged: the candles behind the trading panel and
   the journal looked blurred while the market list, on the same black, did not. One dim
   for both, in both themes; no .dark-mode variant belongs here. */
.drawer-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.25);
  z-index: 1500;
}

/* ========================================
   WATCHLIST DRAWER
   ======================================== */
.watchlist-drawer {
  position: absolute;
  top: 60px;
  right: 20px;
  width: 360px;
  max-height: calc(100vh - 100px);
  /* Same surface recipe as .symbol-modal - the drawer used a lighter blur and a tighter
     shadow, which read as a different material sitting on the same chart. */
  background: rgba(255, 255, 255, 0.88);
  backdrop-filter: blur(60px) saturate(180%);
  -webkit-backdrop-filter: blur(60px) saturate(180%);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 16px;
  z-index: 50;
  display: flex;
  flex-direction: column;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.18);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
  transform: translateY(-10px);
  overflow: hidden;
}

.watchlist-drawer.open {
  opacity: 1;
  pointer-events: all;
  transform: translateY(0);
}

/* ========================================
   POSITION SIZE CALCULATOR
   Same shell as the watchlist drawer so the two read as one family
   ======================================== */
.position-calc-drawer {
  position: absolute;
  top: 60px;
  right: 20px;
  width: 340px;
  max-height: calc(100vh - 100px);
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(40px) saturate(180%);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 16px;
  z-index: 50;
  display: flex;
  flex-direction: column;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.12);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
  transform: translateY(-10px);
}

.position-calc-drawer.open {
  opacity: 1;
  pointer-events: all;
  transform: translateY(0);
}

.calc-field-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  padding-bottom: 18px;
  margin-bottom: 18px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}

.calc-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.calc-field-wide {
  grid-column: 1 / -1;
}

.calc-field-label {
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: #48484A;
}

.calc-optional {
  font-weight: 500;
  color: #8E8E93;
  text-transform: none;
  letter-spacing: 0;
}

.calc-input-wrap {
  position: relative;
  display: flex;
  align-items: center;
}

.calc-input {
  width: 100%;
  min-width: 0;
  padding: 9px 11px;
  background: rgba(255, 255, 255, 0.8);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 10px;
  color: #1D1D1F;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 500;
  outline: none;
  transition: all 0.15s ease;
}

.calc-input.has-prefix {
  padding-left: 24px;
}

.calc-input.has-suffix {
  padding-right: 26px;
}

/* Spinners crowd an already narrow field and nobody steps prices with them */
.calc-input::-webkit-outer-spin-button,
.calc-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.calc-input[type='number'] {
  -moz-appearance: textfield;
  appearance: textfield;
}

.calc-input-prefix,
.calc-input-suffix {
  position: absolute;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  color: #8E8E93;
  pointer-events: none;
}

.calc-input-prefix {
  left: 11px;
}

.calc-input-suffix {
  right: 11px;
}

.calc-empty {
  font-family: var(--font-ui);
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.5;
  color: #8E8E93;
  padding: 4px 2px;
}

.calc-error {
  color: var(--danger-red);
}

.calc-result {
  text-align: center;
  padding: 16px 12px;
  background: rgba(0, 0, 0, 0.03);
  border: 1px solid rgba(0, 0, 0, 0.06);
  border-radius: 12px;
  margin-bottom: 16px;
}

.calc-result-label {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #48484A;
  margin-bottom: 8px;
}

.calc-direction {
  padding: 2px 7px;
  border-radius: 5px;
  font-size: 10px;
  letter-spacing: 0.04em;
}

.calc-direction.long {
  background: rgba(52, 199, 89, 0.14);
  color: #1E8E3E;
}

.calc-direction.short {
  background: rgba(255, 59, 48, 0.12);
  color: #C7261C;
}

.calc-result-value {
  font-family: var(--font-mono);
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.5px;
  color: #1D1D1F;
  line-height: 1.15;
  overflow-wrap: anywhere;
}

.calc-result-sub {
  font-family: var(--font-ui);
  font-size: 11.5px;
  font-weight: 500;
  color: #8E8E93;
  margin-top: 4px;
}

.calc-rows {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.calc-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  font-family: var(--font-ui);
  font-size: 12.5px;
  font-weight: 500;
  color: #48484A;
}

.calc-row-value {
  font-family: var(--font-mono);
  font-weight: 600;
  color: #1D1D1F;
  text-align: right;
  overflow-wrap: anywhere;
}

.calc-risk {
  color: var(--danger-red);
}

.calc-reward {
  color: #1E8E3E;
}

.calc-note {
  margin-top: 14px;
  padding: 10px 12px;
  background: rgba(255, 149, 0, 0.1);
  border: 1px solid rgba(255, 149, 0, 0.22);
  border-radius: 10px;
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.45;
  color: #9A5B00;
}

/* ========================================
   WATCHLIST DRAWER CONTENTS
   Rebuilt to the market list's language: flat rows on hairlines, 28px logo discs,
   mono tickers over a secondary name, icons that surface on row hover. The previous
   version used gradient pill buttons that lifted on hover, bordered cards per list and
   italic empty states - none of which appear anywhere else in Chartify.
   Everything is scoped to .watchlist-drawer, because .drawer-header and .drawer-content
   are shared with the settings and position-size drawers.
   ======================================== */
.watchlist-drawer .drawer-header {
  padding: 20px 20px 14px;
  border-bottom: none;
}

.watchlist-drawer .drawer-header h3 {
  font-weight: 800;
  font-size: 22px;
  letter-spacing: -0.01em;
}

.watchlist-drawer .drawer-content {
  padding: 0 0 10px;
}

/* --- Create bar ---------------------------------------------------------- */
.wl-create {
  display: flex;
  gap: 8px;
  padding: 0 20px 14px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.07);
}

.wl-create-input,
.wl-add-input {
  flex: 1;
  min-width: 0;
  padding: 9px 12px;
  border-radius: 9px;
  border: 1px solid rgba(0, 0, 0, 0.12);
  background: rgba(255, 255, 255, 0.7);
  font-family: var(--font-ui);
  font-size: 13.5px;
  color: var(--text-primary);
  outline: none;
  transition: border-color var(--transition-speed) ease;
}

.wl-create-input:focus,
.wl-add-input:focus {
  border-color: #0A84FF;
}

.wl-create-btn,
.wl-add-btn {
  padding: 9px 16px;
  border-radius: 8px;
  border: none;
  background: #0A84FF;
  color: #FFFFFF;
  font-family: var(--font-ui);
  font-size: 13.5px;
  font-weight: 700;
  cursor: pointer;
  flex-shrink: 0;
  transition: opacity var(--transition-speed) ease;
}

.wl-create-btn:disabled,
.wl-add-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* --- One watchlist ------------------------------------------------------- */
.wl-group {
  padding-bottom: 4px;
}

/* Reads as .section-header does in the market list, so a watchlist name and a market
   category are the same kind of label. */
.wl-group-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 20px 6px;
}

.wl-group-name {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #8E8E93;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.wl-group-count {
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 700;
  color: #8E8E93;
  background: rgba(0, 0, 0, 0.06);
  border-radius: 20px;
  padding: 1px 7px;
  flex-shrink: 0;
}

.wl-group-actions {
  display: flex;
  gap: 2px;
  margin-left: auto;
  flex-shrink: 0;
}

.wl-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: #C7C7CC;
  cursor: pointer;
  transition: background var(--transition-speed) ease, color var(--transition-speed) ease;
}

.wl-icon-btn svg {
  display: block;
}

.wl-icon-btn:hover {
  background: rgba(0, 0, 0, 0.05);
  color: var(--text-primary);
}

.wl-icon-btn.active {
  color: #0A84FF;
  background: rgba(10, 132, 255, 0.1);
}

.wl-icon-btn.danger:hover {
  background: rgba(255, 59, 48, 0.1);
  color: #FF3B30;
}

/* --- Add-a-symbol row ---------------------------------------------------- */
.wl-add-row {
  display: flex;
  gap: 8px;
  padding: 4px 20px 10px;
}

.wl-add-input {
  font-family: var(--font-mono);
  font-size: 12.5px;
  letter-spacing: 0.3px;
}

/* --- Symbol rows --------------------------------------------------------- */
.wl-row {
  display: flex;
  align-items: center;
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
  transition: background var(--transition-speed) ease;
}

.wl-row:hover {
  background: rgba(0, 0, 0, 0.035);
}

.wl-row-main {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1;
  min-width: 0;
  padding: 9px 4px 9px 20px;
  background: transparent;
  border: none;
  font-family: var(--font-ui);
  text-align: left;
  cursor: pointer;
}

.wl-row-logo {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  color: white;
  font-weight: 700;
  flex-shrink: 0;
  overflow: hidden;
}

.wl-row-text {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}

.wl-row-ticker {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.2px;
  color: var(--text-primary);
  flex-shrink: 0;
}

.wl-row-name {
  font-size: 12px;
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

/* Hidden until the row is hovered, the way the market list treats its row icons. */
.wl-row-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  margin-right: 16px;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: #C7C7CC;
  cursor: pointer;
  opacity: 0;
  flex-shrink: 0;
  transition: opacity var(--transition-speed) ease, background var(--transition-speed) ease, color var(--transition-speed) ease;
}

.wl-row-remove svg {
  display: block;
}

.wl-row:hover .wl-row-remove {
  opacity: 1;
}

.wl-row-remove:hover {
  background: rgba(255, 59, 48, 0.1);
  color: #FF3B30;
}

/* --- Empty states -------------------------------------------------------- */
.wl-empty {
  padding: 4px 20px 12px;
  font-family: var(--font-ui);
  font-size: 12.5px;
  color: var(--text-secondary);
}

.wl-none {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 40px 32px 44px;
  text-align: center;
  color: #C7C7CC;
}

.wl-none-title {
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 700;
  color: var(--text-primary);
  margin-top: 2px;
}

.wl-none-hint {
  font-family: var(--font-ui);
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--text-secondary);
}

/* ========================================
   SCROLLBAR STYLING
   ======================================== */
/* The chat's own bar. The platform default is a grey slab sized for a document, which
   reads as browser chrome dropped into the panel - and in dark mode it is a bright edge
   running down a black surface. Narrower, no track, and a thumb that only asserts itself
   under the pointer.

   Both scrollable parts of the panel take it: the transcript, and the composer once a
   question outgrows its box. Scoped to .chatbot-modal so the phone card gets it too. */
.chatbot-modal .chatbot-messages,
.chatbot-modal .ai-composer textarea {
  scrollbar-width: thin;
  scrollbar-color: rgba(0, 0, 0, 0.18) transparent;
}

.chatbot-modal .chatbot-messages::-webkit-scrollbar,
.chatbot-modal .ai-composer textarea::-webkit-scrollbar {
  width: 6px;
}

/* A visible groove down a column this narrow reads as a second border. */
.chatbot-modal .chatbot-messages::-webkit-scrollbar-track,
.chatbot-modal .ai-composer textarea::-webkit-scrollbar-track {
  background: transparent;
}

.chatbot-modal .chatbot-messages::-webkit-scrollbar-thumb,
.chatbot-modal .ai-composer textarea::-webkit-scrollbar-thumb {
  background: rgba(0, 0, 0, 0.18);
  border-radius: 3px;
  transition: background 0.15s ease;
}

.chatbot-modal .chatbot-messages::-webkit-scrollbar-thumb:hover,
.chatbot-modal .ai-composer textarea::-webkit-scrollbar-thumb:hover {
  background: rgba(0, 0, 0, 0.34);
}

/* Inverted rather than dimmed: on the black panel the thumb has to be lighter than what
   it sits on, and the light-mode alpha would be invisible. */
.chatbot-modal.dark-mode .chatbot-messages,
.chatbot-modal.dark-mode .ai-composer textarea {
  scrollbar-color: rgba(255, 255, 255, 0.16) transparent;
}

.chatbot-modal.dark-mode .chatbot-messages::-webkit-scrollbar-thumb,
.chatbot-modal.dark-mode .ai-composer textarea::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.16);
}

.chatbot-modal.dark-mode .chatbot-messages::-webkit-scrollbar-thumb:hover,
.chatbot-modal.dark-mode .ai-composer textarea::-webkit-scrollbar-thumb:hover {
  background: rgba(255, 255, 255, 0.32);
}


.drawer-content::-webkit-scrollbar,
.modal-content::-webkit-scrollbar {
  width: 8px;
}

.drawer-content::-webkit-scrollbar-track,
.modal-content::-webkit-scrollbar-track {
  background: rgba(0, 0, 0, 0.03);
}

.drawer-content::-webkit-scrollbar-thumb,
.modal-content::-webkit-scrollbar-thumb {
  background: rgba(0, 0, 0, 0.2);
  border-radius: 4px;
}

.drawer-content::-webkit-scrollbar-thumb:hover,
.modal-content::-webkit-scrollbar-thumb:hover {
  background: rgba(0, 0, 0, 0.3);
}

/* ========================================
   REPLAY MODAL MODES
   ======================================== */
.replay-modal {
  max-width: 500px;
}

/* The picker is a fixed stack - two ways in, a calendar, a time and a confirm - so
   unlike the symbol list it cannot simply scroll for longer when the window is short.
   These three give it back the room the shared modal chrome was holding, and only for
   this modal: the market list keeps the roomier header and padding it was designed with.
   82vh -> 94vh is worth about 70px at a 600px-tall window, which together with the
   scaling inside the picker is the difference between the Start button being on screen
   and being below the fold. */
.replay-modal-content {
  padding: 24px;
}

/* Short and wide: the two ways of starting a replay stop being a stack and become a
   choice side by side. Stacked, "Select on Chart" and the OR above the calendar cost
   about 130px of height that a 600px-tall window does not have, and the Start button
   ended up under the fold. Side by side they cost nothing, and the modal is 500px wide
   - room enough for a 140px card beside a calendar that never goes below 238px. The
   540px floor is where that stops fitting - below it the stack comes back.
   The OR goes with it: two things next to each other already read as alternatives. */
@media (max-height: 700px) and (min-width: 540px) {
  .replay-modal .replay-mode-buttons {
    display: grid;
    grid-template-columns: minmax(140px, 0.85fr) minmax(238px, 1.15fr);
    align-items: stretch;
    gap: 14px;
  }

  .replay-modal .replay-mode-divider {
    display: none;
  }

  /* Fills its column rather than sitting at the top of it, so the two cards are the
     same height and the row does not look half-empty. */
  .replay-modal .replay-mode-btn {
    justify-content: center;
  }
}

@media (max-height: 820px) {
  .replay-modal {
    max-height: 94vh;
  }

  .replay-modal-content {
    padding: clamp(12px, 2.4vh, 24px);
  }

  .replay-modal .modal-header {
    padding: clamp(10px, 1.8vh, 22px) 24px clamp(6px, 1.2vh, 16px);
  }

  .replay-modal .modal-header h3 {
    font-size: clamp(17px, 3.2vh, 26px);
  }

}

.replay-mode-buttons {
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 2vh, 16px);
}

.replay-mode-btn {
  width: 100%;
  padding: clamp(10px, 2.6vh, 20px);
  background: rgba(255, 255, 255, 0.6);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  transition: all var(--transition-speed) ease;
  cursor: pointer;
}

.replay-mode-btn:hover {
  background: rgba(142, 142, 147, 0.1);
  border-color: rgba(142, 142, 147, 0.3);
  ;
  box-shadow: 0 4px 16px rgba(142, 142, 147, 0.15);
}

.replay-mode-icon {
  font-size: clamp(20px, 4vh, 32px);
  color: #8E8E93;
  line-height: 1;
}

.replay-mode-text {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 16px;
  color: #1D1D1F;
}

.replay-mode-desc {
  font-family: var(--font-ui);
  font-size: 12px;
  line-height: 1.3;
  color: var(--text-secondary);
}

.replay-mode-divider {
  text-align: center;
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 12px;
  color: var(--text-secondary);
  letter-spacing: 2px;
}

.replay-mode-datetime {
  padding: clamp(10px, 2vh, 16px);
  background: rgba(255, 255, 255, 0.8);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 12px;
}

.replay-datetime-label {
  display: block;
  margin-bottom: clamp(4px, 1vh, 8px);
  font-size: 13px;
  font-family: var(--font-ui);
  font-weight: 500;
  color: #48484A;
}

/* --- The replay calendar --------------------------------------------------
   Replaces the browser's datetime-local field, which renders as a different control in
   every browser and shows nothing about which dates the chart actually holds. */
.replay-calendar {
  display: flex;
  flex-direction: column;
  gap: clamp(5px, 1.4vh, 10px);
  /* Capped and centred rather than filling the panel. The cells are square, so across the
     full 600px of the modal each one would be about 78px and six rows of them would be
     taller than the sheet - the time row and the confirm button ended up below the fold.
     At this width a cell is roughly 44px, which is a comfortable target and looks like a
     calendar rather than a spreadsheet. */
  /* Tied to the window's height as well as capped in absolute terms: the cells are
     square, so their width is what drives how tall the grid is. Narrowing the
     calendar is therefore the cheapest way to buy vertical room in a short window,
     and it keeps the cells looking like a calendar rather than squashed bars. */
  max-width: clamp(238px, 46vh, 330px);
  margin: 0 auto;
  width: 100%;
}

.replay-cal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.replay-cal-month {
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 600;
  color: #1D1D1F;
  /* The month name changes width as the calendar is paged - "May 2026" against
     "September 2026" - and without a fixed centre the two arrows shuffle sideways on
     every step. */
  flex: 1;
  text-align: center;
}

.replay-cal-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  width: clamp(24px, 4.4vh, 28px);
  height: clamp(24px, 4.4vh, 28px);
  flex-shrink: 0;
  background: transparent;
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 8px;
  color: #48484A;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.replay-cal-nav:hover:not(:disabled) {
  background: rgba(0, 0, 0, 0.05);
  color: #1D1D1F;
}

/* The arrows stop at the ends of the loaded data rather than paging for ever through
   months that cannot hold a candle. */
.replay-cal-nav:disabled {
  opacity: 0.3;
  cursor: default;
}

.replay-cal-weekdays,
.replay-cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}

.replay-cal-weekdays span {
  text-align: center;
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #8E8E93;
  padding-bottom: 2px;
}

.replay-cal-day {
  aspect-ratio: 1;
  /* Square while there is room, squashed rather than scrolled once there is not. */
  max-height: clamp(24px, 4.7vh, 46px);
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 8px;
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  color: #1D1D1F;
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease;
  /* mobile.css floors every button at 44px for touch, which on a seven-column grid is
     taller than the calendar needs and pushes the confirm button off a short sheet. The
     cells are square by aspect-ratio and stay comfortably tappable at that size. */
  min-height: 0;
  min-width: 0;
  padding: 0;
}

.replay-cal-day:hover:not(:disabled) {
  background: rgba(0, 0, 0, 0.06);
}

/* The days either side of the shown month. Kept visible rather than blanked so the weeks
   read as continuous, but clearly not part of what is being chosen. */
.replay-cal-day.outside {
  color: #C7C7CC;
}

/* A day with no candles behind it. The replay jumps to the first candle at or after the
   chosen moment, so picking one of these did nothing at all before - now it cannot be
   picked, and the range the chart holds is visible at a glance. */
.replay-cal-day:disabled {
  opacity: 0.25;
  cursor: default;
}

.replay-cal-day.selected {
  background: #1D1D1F;
  border-color: #1D1D1F;
  color: #FFFFFF;
  font-weight: 600;
}

.replay-cal-time {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-top: 2px;
}

.replay-time-label {
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  color: #48484A;
}

/* One control made of two fields. The border is on the wrapper, not on each half,
   so HH:MM reads as a single time rather than as two boxes that happen to sit
   next to each other - and the focus ring can then belong to the whole thing. */
.replay-time-field {
  display: flex;
  align-items: center;
  gap: 2px;
  flex: 1;
  padding: 8px 12px;
  background: var(--bk-input);
  border: 1px solid var(--bk-border);
  border-radius: var(--bk-r-control);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.replay-time-field:focus-within {
  border-color: var(--bk-border-strong);
  box-shadow: 0 0 0 3px rgba(142, 142, 147, 0.12);
}

/* Sized in ch so both halves are exactly two digits wide whatever the font does,
   which keeps the colon dead centre instead of drifting as the numbers change. */
.replay-time-seg {
  width: 2ch;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--bk-text);
  font-family: var(--font-mono);
  font-size: 15px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  text-align: center;
  min-height: 0;
  min-width: 0;
}

.replay-time-seg:focus {
  outline: none;
}

/* The selection is the only thing marking which half is being edited, so it has to
   be visible - the wrapper owns the focus ring and cannot say which side has it. */
.replay-time-seg::selection {
  background: rgba(var(--brand-rgb), 0.35);
}

.replay-time-colon {
  font-family: var(--font-mono);
  font-size: 15px;
  font-weight: 500;
  color: var(--bk-text-3);
  line-height: 1;
}

/* Confirms the choice. This used to live only in the phone block, because with a
   datetime-local field a desktop browser reported a complete value in one go and could
   start the replay straight from onChange. A calendar cannot: choosing a day is one of
   two steps, and starting there would put the time out of reach. So every layout gets
   the button now. */
.replay-datetime-confirm {
  flex-direction: row;
  justify-content: center;
  padding: clamp(9px, 1.8vh, 12px);
  margin-top: clamp(8px, 1.6vh, 12px);
}

.replay-datetime-confirm:disabled {
  opacity: 0.45;
  cursor: default;
}

.replay-mode-footer {
  margin-top: clamp(8px, 2vh, 16px);
  font-size: 12px;
  font-family: var(--font-ui);
  color: #8E8E93;
  text-align: center;
  line-height: 1.5;
}

/* ========================================
   CHART SELECTION MODE
   ======================================== */
/* --- The replay cut -------------------------------------------------------
   Where the chart will be cut when a replay start is picked. This replaced a dashed
   horizontal line that tracked the cursor's height: replay is chosen by time, so the
   price the pointer happens to sit at was never part of the decision. */
.replay-cut-line {
  position: fixed;
  width: 0;
  border-left: 2px solid #8E8E93;
  pointer-events: none;
  z-index: 900;
}

/* The scissors, on the line rather than beside it. Held a little above centre so it is
   clear of the timestamp that follows the pointer. */
.replay-cut-scissors {
  position: absolute;
  left: -1px;
  top: 38%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: #8E8E93;
  color: #FFFFFF;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
}

/* The bars that are about to be cut away. Blurred rather than merely dimmed: a dim reads
   as "not selected", a blur reads as "not there", which is what is about to be true of
   them. Sized in JS to span from the line to where the plot ends, so it never washes over
   the price scale. */
.replay-cut-veil {
  position: fixed;
  pointer-events: none;
  z-index: 899;
  backdrop-filter: blur(2.5px);
  -webkit-backdrop-filter: blur(2.5px);
  background: rgba(255, 255, 255, 0.35);
}

.selection-tooltip {
  position: fixed;
  background: rgba(142, 142, 147, 0.95);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  color: white;
  padding: 8px 12px;
  border-radius: 8px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  pointer-events: none;
  z-index: 901;
  white-space: nowrap;
  box-shadow: 0 4px 12px rgba(142, 142, 147, 0.3);
}

/* A grid item keeps min-width: auto whatever its track says, so these cards refused to
   go below their own content and the dashboard grew a horizontal scrollbar that led
   nowhere - nothing was painted out there, the panel just slid sideways onto empty
   space. The tracks are minmax(0, ...) in the markup; this is the other half of it. */
.journal-main-grid > *,
.journal-trades-row > *,
.journal-stats-grid > * {
  min-width: 0;
}

.journal-stat-info {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  margin-left: 6px;
  cursor: help;
  opacity: 0.5;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  font-size: 14px;
  color: rgba(255, 255, 255, 0.8);
  background: rgba(255, 255, 255, 0.08);
  border-radius: 50%;
  border: 1.5px solid rgba(255, 255, 255, 0.2);
}

.journal-stat-info:hover {
  opacity: 1;
  ;
  background: rgba(255, 255, 255, 0.15);
  border-color: rgba(255, 255, 255, 0.4);
  box-shadow: 0 0 12px rgba(255, 255, 255, 0.2);
}

.journal-stat-info::after {
  content: attr(data-tooltip);
  position: absolute;
  top: calc(100% + 14px);
  left: 50%;
  transform: translateX(-50%) translateY(-4px);
  background: linear-gradient(135deg, rgba(30, 30, 35, 0.98) 0%, rgba(20, 20, 25, 0.98) 100%);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  color: #E5E7EB;
  padding: 12px 16px;
  border-radius: 10px;
  font-size: 12.5px;
  font-weight: 500;
  white-space: normal;
  width: 260px;
  text-align: center;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1), visibility 0.3s, transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 99999;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.1);
  line-height: 1.6;
  letter-spacing: 0.2px;
}

.journal-stat-info:hover::after {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
}

.dark-mode .journal-stat-info::after {
  background: linear-gradient(135deg, rgba(30, 30, 35, 0.98) 0%, rgba(20, 20, 25, 0.98) 100%);
  color: #E5E7EB;
}

.journal-stat-info::before {
  content: '';
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  border: 6px solid transparent;
  border-bottom-color: rgba(30, 30, 35, 0.98);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s, visibility 0.3s;
  z-index: 99999;
  filter: drop-shadow(0 -2px 4px rgba(0, 0, 0, 0.3));
}

.journal-stat-info:hover::before {
  opacity: 1;
  visibility: visible;
}

/* The Log New Trade screenshot picker. Its file input is invisible over the button, so
   the ring has to come from the button when the input inside it has keyboard focus. */
.journal-image-picker:has(input:focus-visible) {
  outline: 2px solid #007AFF;
  outline-offset: 2px;
}

.journal-image-picker:hover {
  border-color: #007AFF !important;
}

/* ========================================
   INDICATORS
   ======================================== */
.indicators-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  height: 36px;
  background: transparent;
  border: none;
  border-radius: 12px;
  color: #1D1D1F;
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  white-space: nowrap;
  box-shadow: none;
  position: relative;
}

.indicators-btn::after {
  content: '';
  position: absolute;
  right: -10px;
  top: 50%;
  transform: translateY(-50%);
  width: 1.5px;
  height: 18px;
  background: rgba(0, 0, 0, 0.1);
}

.indicators-btn:last-child::after {
  display: none;
}

/* The journal is the last button in the navbar, but not the navbar's last child - the
   tools cell follows it - so :last-child above does not reach it and it drew a second
   line ten pixels short of the cell's own. */
.navbar > .journal-btn::after {
  display: none;
}

/* The phone's separators are elements, and the desktop's are the pseudo-elements above.
   They are only rendered below 768px - the markup asks the same media query this stylesheet
   does - so this is here for the frame after a window is dragged wide, before the resize
   listener has re-rendered the bar without them. See the flat-row block at the end of the
   file for what they are and why they exist. */
.navbar-divider {
  display: none;
}

/* The pair sits hard against the divider, with the bar's slack collecting to the left of
   both rather than opening a gap inside the row. Which element carries that job depends on
   the layout: in the flow one it is .navbar-center's own margin-right, which packs
   everything after it to the far end. Only when the group is lifted out of the flow - see
   the centred layout below - does the trading panel have to do it itself, and it takes the
   margin there rather than here. Given here as well it would be a third claim on the space
   the group's two margins share, and the group would sit left of where it belongs. */

/* The clock is the strip's last child, so the rule above never matches a button there and
   the final one drew its separator into the empty gap before the clock. Scoped to the
   strip, because .indicators-btn is borrowed by the navbar and the settings-modal
   backtest button, which are last children in their own rows. */
.bottom-strip .indicators-btn:last-of-type::after {
  display: none;
}

.indicators-btn:hover {
  background: rgba(0, 0, 0, 0.06);
}

/* The Backtest button in the Swift Algo X settings borrows .indicators-btn from the bottom
   strip, where buttons sit in a row divided by ::after separators and are deliberately
   borderless. In the settings modal there is no separator and every neighbouring control
   is outlined, so it needs an outline of its own - matched to the modal's inputs/selects.
   Scoped to this extra class so the bottom-strip buttons stay borderless. */
.indicators-btn.indicator-backtest-btn {
  border: 1px solid rgba(0, 0, 0, 0.1);
}

.indicators-btn.indicator-backtest-btn:hover {
  border-color: rgba(0, 0, 0, 0.2);
}

.indicators-btn svg {
  stroke: #1D1D1F;
  width: 16px;
  height: 16px;
}

.indicators-text {
  color: #1D1D1F;
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 14px;
}

.indicators-count {
  background: var(--bk-active);
  color: var(--bk-text-2);
  font-size: 11px;
  padding: 3px 7px;
  border-radius: 10px;
  font-weight: 700;
  line-height: 1;
}

.indicator-modal {
  position: absolute;
  z-index: 100;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(40px) saturate(180%);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 16px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15);
  width: 600px;
  max-height: min(780px, 85vh);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  user-select: none;
}

.indicator-modal-handle {
  display: flex;
  justify-content: center;
  color: #C7C7CC;
  cursor: grab;
  padding: 8px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}

.indicator-modal-handle:active {
  cursor: grabbing;
}

.indicator-section {
  margin-bottom: 12px;
}

.indicator-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px;
  border-radius: 10px;
  transition: background 0.15s ease;
  cursor: pointer;
}

.indicator-item:hover {
  background: rgba(0, 0, 0, 0.03);
}

.indicator-item-left {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.indicator-item-name {
  font-size: 15px;
  color: #1D1D1F;
  font-weight: 500;
}

.indicator-item-desc {
  font-size: 12px;
  color: #8E8E93;
}

.indicator-add-btn {
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(142, 142, 147,0.1);
  border: 1px solid rgba(142, 142, 147,0.25);
  border-radius: 8px;
  color: #AEAEB2;
  font-size: 20px;
  cursor: pointer;
  transition: all 0.15s ease;
  line-height: 1;
}

.indicator-add-btn:hover {
  background: rgba(142, 142, 147,0.2);
  border-color: rgba(142, 142, 147,0.5);
}

.indicator-item-actions {
  display: flex;
  align-items: center;
  gap: 6px;
}

/* Library cards on the Invite-only tab. Two to a row even while there is only one card, so
   a card is card-sized rather than a banner, and the next invite-only script has its slot.
   One to a row on a phone, where half the sheet leaves the animation too small to follow. */
.indicator-card-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  padding: 6px 16px 4px;
}

@media (max-width: 520px) {
  .indicator-card-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* --preview-ground is the chart's background as it actually shows, set inline from the
   user's chart design, and on-light / on-dark say which ink reads on it. Both follow the
   chart rather than the app theme: a white chart in a dark app still wants dark ink. */
.indicator-card {
  position: relative;
  aspect-ratio: 640 / 426;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid rgba(0, 0, 0, 0.1);
  background: var(--preview-ground, #FFFFFF);
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.indicator-card:hover,
.indicator-card:focus-visible {
  border-color: rgba(0, 0, 0, 0.45);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.08);
  outline: none;
}

.indicator-card.added {
  cursor: default;
}

.indicator-card.added:hover {
  border-color: rgba(0, 0, 0, 0.1);
  box-shadow: none;
}

.indicator-card-image {
  display: block;
  width: 100%;
  height: 100%;
}

/* The fade the name sits on, in the chart's own ground, so the name reads without a band
   of some other colour across the picture. */
.indicator-card-footer {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 6px;
  padding: 26px 10px 8px;
  background: linear-gradient(to top, var(--preview-ground, #FFFFFF) 35%, transparent);
  pointer-events: none;
}

.indicator-card-name {
  font-size: 13px;
  font-weight: 600;
  color: #1D1D1F;
  line-height: 1.2;
}

.indicator-card-added {
  flex-shrink: 0;
  font-size: 10px;
  font-weight: 600;
  color: #6E6E73;
  padding: 2px 6px;
  border-radius: 999px;
  background: rgba(142, 142, 147, 0.16);
}

/* The button is only the hit area - the phone stylesheet grows every button to 44px for
   touch, and a visible 44px box would cover a quarter of the card. The chip inside is what
   shows, and it stays the same size at every width. */
.indicator-card-star {
  position: absolute;
  top: 0;
  right: 0;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: flex-start;
  justify-content: flex-end;
  padding: 6px;
  background: none;
  border: none;
  cursor: pointer;
}

.indicator-card-star-chip {
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  line-height: 1;
  color: #8E8E93;
  background: rgba(255, 255, 255, 0.85);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 6px;
}

.indicator-card-star.favorite .indicator-card-star-chip {
  color: #F5C518;
}

.indicator-card.on-dark .indicator-card-name {
  color: #FFFFFF;
}

.indicator-card.on-dark .indicator-card-added {
  color: #AEAEB2;
  background: rgba(255, 255, 255, 0.1);
}

.indicator-card.on-dark .indicator-card-star-chip {
  color: #AEAEB2;
  background: rgba(21, 22, 25, 0.8);
  border-color: rgba(255, 255, 255, 0.12);
}

.indicator-card.on-dark .indicator-card-star.favorite .indicator-card-star-chip {
  color: #FFD24D;
}

.dark-mode .indicator-card {
  border-color: #2A2A2A;
}

.dark-mode .indicator-card:hover,
.dark-mode .indicator-card:focus-visible {
  border-color: rgba(255, 255, 255, 0.7);
  box-shadow: none;
}

.dark-mode .indicator-card.added:hover {
  border-color: #2A2A2A;
}

.indicator-item:hover .symbol-favorite-btn {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

.active-indicator-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  background: rgba(142, 142, 147,0.05);
  border: 1px solid rgba(142, 142, 147,0.1);
  border-radius: 8px;
  margin-bottom: 4px;
}

.active-indicator-left {
  display: flex;
  align-items: center;
  gap: 8px;
}

.active-indicator-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}

.active-indicator-name {
  font-size: 13px;
  color: #1D1D1F;
  font-weight: 500;
}

.active-indicator-param {
  font-size: 11px;
  color: #8E8E93;
  font-family: 'JetBrains Mono', monospace;
}

.active-indicator-actions {
  display: flex;
  align-items: center;
  gap: 4px;
}

.indicator-settings-btn {
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 8px;
  color: #8E8E93;
  cursor: pointer;
  transition: all 0.15s ease;
}

.indicator-settings-btn:hover {
  color: #48484A;
  border-color: rgba(142, 142, 147,0.3);
  background: rgba(142, 142, 147,0.08);
}

.indicator-visibility-btn {
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 8px;
  color: #8E8E93;
  cursor: pointer;
  transition: all 0.15s ease;
}

.indicator-visibility-btn:hover {
  color: #48484A;
  border-color: rgba(142, 142, 147,0.3);
  background: rgba(142, 142, 147,0.08);
}

.swift-algo-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  background: rgba(142, 142, 147,0.08);
  border: 1px solid rgba(142, 142, 147,0.15);
  border-radius: 8px;
  margin-bottom: 4px;
}

.indicator-remove-btn {
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 8px;
  color: #8E8E93;
  font-size: 18px;
  cursor: pointer;
  transition: all 0.15s ease;
  line-height: 1;
}

.indicator-remove-btn:hover {
  color: #FF3B30;
  border-color: rgba(255,59,48,0.3);
  background: rgba(255,59,48,0.08);
}

.indicator-settings-panel {
  background: rgba(0, 0, 0, 0.02);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 8px;
  padding: 12px;
  margin-bottom: 4px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.indicator-param-row {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.indicator-param-row label {
  font-size: 13px;
  font-weight: 500;
  color: #48484A;
}

/* Label line of a setting, with its info "i" pinned to the right edge of the row. */
.param-row-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

/* Keeps a long label from pushing the icon off the row */
.param-row-head > label {
  flex: 1;
  min-width: 0;
}

.info-tip-btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 50%;
  color: #AEAEB2;
  cursor: help;
  transition: color 0.15s ease, background 0.15s ease;
}

.info-tip-btn:hover,
.info-tip-btn.open {
  color: #1D1D1F;
  background: rgba(0, 0, 0, 0.06);
}

/* Above the settings modal (z-index 10000), same as the sensitivity menu */
.info-tip-popover {
  z-index: 10002;
  padding: 10px 12px;
  background: rgba(255, 255, 255, 0.98);
  backdrop-filter: blur(40px) saturate(180%);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 10px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15);
  color: #48484A;
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.45;
  /* Copy with newlines in it (the sensitivity suggestions) renders as a list */
  white-space: pre-line;
  animation: dropdownSlideIn 0.15s ease-out;
  /* Never let the card swallow a click meant for the panel underneath */
  pointer-events: none;
}

.indicator-param-row input[type="number"],
.indicator-param-row input[type="text"] {
  width: 100%;
  padding: 10px 12px;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 8px;
  color: #1D1D1F;
  font-size: 13px;
  font-family: var(--font-ui);
  font-weight: 500;
  outline: none;
  -moz-appearance: textfield;
}

.indicator-param-row input[type="number"]::-webkit-outer-spin-button,
.indicator-param-row input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.indicator-param-row input[type="number"]:focus,
.indicator-param-row input[type="text"]:focus {
  border-color: rgba(142, 142, 147,0.4);
  box-shadow: 0 0 0 3px rgba(142, 142, 147,0.1);
}

.indicator-param-row input[type="color"] {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 2px solid rgba(0, 0, 0, 0.1);
  cursor: pointer;
  padding: 0;
  background: none;
  transition: all 0.2s ease;
}

.indicator-param-row input[type="color"]:hover {
  ;
  border-color: rgba(0, 0, 0, 0.3);
}

.indicator-apply-btn {
  width: 100%;
  padding: 8px;
  margin-top: 8px;
  background: rgba(142, 142, 147,0.15);
  border: 1px solid rgba(142, 142, 147,0.3);
  border-radius: 8px;
  color: #AEAEB2;
  font-size: 12px;
  font-family: var(--font-ui);
  cursor: pointer;
  transition: all 0.15s ease;
}

/* New Tabbed Settings Modal */
.indicator-settings-modal-wrapper {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 520px;
  max-height: 80vh;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(40px);
  -webkit-backdrop-filter: blur(40px);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 16px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
  z-index: 10000;
  display: flex;
  flex-direction: column;
  overflow: visible;
}

.indicator-settings-modal-header {
  padding: 20px 24px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.indicator-settings-modal-header h3 {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 20px;
  color: #1D1D1F;
  margin: 0;
}

.indicator-settings-tabs {
  display: flex;
  border-bottom: 2px solid rgba(0, 0, 0, 0.08);
  padding: 0 24px;
  gap: 0;
}

.indicator-settings-tab {
  flex: 1;
  padding: 12px 16px;
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  color: #8E8E93;
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s ease;
  margin-bottom: -2px;
}

.indicator-settings-tab:hover {
  color: #48484A;
}

.indicator-settings-tab.active {
  color: #1D1D1F;
  border-bottom-color: #1D1D1F;
}

.indicator-settings-content {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 24px;
  max-height: calc(80vh - 200px);
  min-height: 300px;
}

.indicator-settings-tab-content {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.settings-section-header {
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 700;
  color: #48484A;
  letter-spacing: 0.5px;
  padding: 8px 0 4px;
  margin-top: 8px;
}

.indicator-param-row select {
  flex: 1;
  padding: 10px 12px;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 8px;
  color: #1D1D1F;
  font-size: 13px;
  font-family: var(--font-ui);
  font-weight: 500;
  outline: none;
  cursor: pointer;
}

.indicator-param-row select:focus {
  border-color: rgba(142, 142, 147, 0.4);
  box-shadow: 0 0 0 3px rgba(142, 142, 147, 0.1);
}

/* The signal-frequency block (mode + Custom EMA + EMA period) starts a new group after the
   Trade Checker toggle, and the container's uniform 16px gap did not read as a break.
   Adds to that gap rather than replacing it: 16 + 12 = 28px above this row only. */
.indicator-param-row.signal-mode-row {
  margin-top: 12px;
}

/* Signal frequency - segmented control.
   Replaces a native <select> for three mutually exclusive options. Showing all three at
   once makes the Spam -> Rapid -> Default ordering (most signals to fewest) readable at a
   glance rather than hiding two of them behind a dropdown. */
.signal-mode-segmented {
  display: flex;
  gap: 4px;
  padding: 4px;
  background: rgba(0, 0, 0, 0.04);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 10px;
}

.signal-mode-option {
  flex: 1;
  padding: 8px 10px;
  background: transparent;
  border: none;
  border-radius: 8px;
  color: #48484A;
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.18s cubic-bezier(0.4, 0, 0.2, 1);
}

.signal-mode-option:hover:not(.active) {
  background: rgba(0, 0, 0, 0.05);
  color: #1D1D1F;
}

/* The selected segment lifts off the track rather than filling with an accent colour,
   which keeps it quiet next to the coloured controls further down the panel. */
.signal-mode-option.active {
  background: #FFFFFF;
  color: #1D1D1F;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
}

.signal-mode-option:focus-visible {
  outline: 2px solid rgba(142, 142, 147, 0.5);
  outline-offset: 1px;
}

/* Indicator Sensitivity - custom picker replacing the native <select>, which renders as
   the OS widget and ignores the app's theming entirely. The trigger deliberately matches
   .indicator-param-row input/select so the row still lines up with the number fields
   around it; only the popup is new. */
.sensitivity-dropdown-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 10px 12px;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 8px;
  color: #1D1D1F;
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.sensitivity-dropdown-btn:hover {
  border-color: rgba(142, 142, 147, 0.4);
}

/* Same focus treatment the panel's inputs use, so an open picker reads as the active field */
.sensitivity-dropdown-btn.open {
  border-color: rgba(142, 142, 147, 0.4);
  box-shadow: 0 0 0 3px rgba(142, 142, 147, 0.1);
}

.sensitivity-dropdown-chevron {
  flex-shrink: 0;
  color: #8E8E93;
  transition: transform 0.18s cubic-bezier(0.4, 0, 0.2, 1);
}

.sensitivity-dropdown-btn.open .sensitivity-dropdown-chevron {
  transform: rotate(180deg);
}

/* Above the settings modal, which sits at z-index 10000 */
.sensitivity-dropdown-overlay {
  position: fixed;
  inset: 0;
  z-index: 10001;
}

.sensitivity-dropdown-menu {
  z-index: 10002;
  padding: 4px;
  background: rgba(255, 255, 255, 0.98);
  backdrop-filter: blur(40px) saturate(180%);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 12px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15);
  overflow-y: auto;
  overflow-x: hidden;
  animation: dropdownSlideIn 0.18s ease-out;
}

.sensitivity-dropdown-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 9px 12px;
  background: transparent;
  border: none;
  border-radius: 8px;
  color: #1D1D1F;
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition: background 0.12s ease;
}

.sensitivity-dropdown-item:hover {
  background: rgba(0, 0, 0, 0.05);
}

.sensitivity-dropdown-item.active {
  background: rgba(0, 0, 0, 0.06);
  font-weight: 600;
}

.sensitivity-dropdown-item.active svg {
  color: var(--bk-text);
}

/* Swift Algo sensitivity that does not suit the chart's timeframe (utils/swiftSensitivity.js):
   a tag on the option in the picker, a line under the picker, a sign on the chart's badge.
   Amber - a warning, not an error: it can still be applied. */
.sensitivity-flag {
  margin-left: auto;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 600;
  color: #B26A00;
  background: rgba(245, 185, 66, 0.18);
  white-space: nowrap;
}
.dark-mode .sensitivity-flag { color: #F5B942; background: rgba(245, 185, 66, 0.14); }

.sensitivity-warning {
  display: flex;
  align-items: flex-start;
  gap: 7px;
  margin-top: 8px;
  padding: 8px 10px;
  border-radius: 8px;
  font-size: 12px;
  line-height: 1.4;
  color: #8A5300;
  background: rgba(245, 185, 66, 0.16);
  box-shadow: inset 0 0 0 1px rgba(245, 185, 66, 0.35);
}
.sensitivity-warning svg { flex: 0 0 auto; margin-top: 1px; }
.dark-mode .sensitivity-warning { color: #F5B942; background: rgba(245, 185, 66, 0.10); box-shadow: inset 0 0 0 1px rgba(245, 185, 66, 0.28); }

.swift-sensitivity-flag {
  display: inline-flex;
  align-items: center;
  margin-left: 4px;
  color: #D48A00;
  cursor: help;
}
.dark-mode .swift-sensitivity-flag { color: #F5B942; }

/* "How to find the best sensitivity" under the picker (SensitivityGuide.jsx): a quiet text
   button in the panel's greys, opening a card in place. The rows inside echo the picker's
   own menu items. */
.sensitivity-guide-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  align-self: flex-start;
  padding: 4px 0;
  background: none;
  border: none;
  color: #8E8E93;
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: color 0.15s ease;
}
.sensitivity-guide-toggle:hover,
.sensitivity-guide-toggle.open { color: #1D1D1F; }
.sensitivity-guide-chevron { transition: transform 0.18s cubic-bezier(0.4, 0, 0.2, 1); }
.sensitivity-guide-toggle.open .sensitivity-guide-chevron { transform: rotate(180deg); }

.sensitivity-guide-card {
  margin-top: 8px;
  padding: 12px;
  background: rgba(0, 0, 0, 0.025);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 10px;
  font-family: var(--font-ui);
  animation: dropdownSlideIn 0.18s ease-out;
}

.sensitivity-guide-lead {
  margin: 0;
  font-size: 12px;
  line-height: 1.45;
  color: #6E6E73;
}

.sensitivity-guide-heading {
  margin: 12px 0 6px;
  font-size: 11px;
  font-weight: 600;
  color: #8E8E93;
}

.sensitivity-guide-options {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.sensitivity-guide-option {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 7px 8px;
  background: transparent;
  border: none;
  border-radius: 8px;
  color: #1D1D1F;
  font-family: var(--font-ui);
  text-align: left;
  cursor: pointer;
  transition: background 0.12s ease;
}
.sensitivity-guide-option:hover { background: rgba(0, 0, 0, 0.05); }
.sensitivity-guide-option.active { background: rgba(0, 0, 0, 0.06); }

.sensitivity-guide-value {
  flex: 0 0 auto;
  min-width: 38px;
  padding: 3px 0;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.9);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
  font-size: 12px;
  font-weight: 600;
  text-align: center;
}

.sensitivity-guide-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  font-size: 12px;
  line-height: 1.3;
}
.sensitivity-guide-text strong { font-weight: 600; }
.sensitivity-guide-text span { color: #8E8E93; }

.sensitivity-guide-use {
  flex: 0 0 auto;
  font-size: 11px;
  font-weight: 600;
  color: #8E8E93;
  opacity: 0;
  transition: opacity 0.12s ease;
}
.sensitivity-guide-option:hover .sensitivity-guide-use,
.sensitivity-guide-option:focus-visible .sensitivity-guide-use { opacity: 1; }
.sensitivity-guide-check { flex: 0 0 auto; }
/* No hover on a touch screen: show it from the start */
@media (hover: none) {
  .sensitivity-guide-use { opacity: 1; }
}

.sensitivity-guide-notes {
  margin: 10px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
  line-height: 1.45;
  color: #6E6E73;
}
.sensitivity-guide-notes strong { font-weight: 600; color: #B26A00; }

.sensitivity-guide-table {
  display: flex;
  flex-direction: column;
  font-size: 12px;
}
.sensitivity-guide-row {
  display: flex;
  justify-content: space-between;
  padding: 5px 8px;
  border-radius: 6px;
  color: #6E6E73;
}
.sensitivity-guide-row.current {
  background: rgba(0, 0, 0, 0.05);
  color: #1D1D1F;
  font-weight: 600;
}

.dark-mode .sensitivity-guide-toggle { color: var(--bk-text-3); }
.dark-mode .sensitivity-guide-toggle:hover,
.dark-mode .sensitivity-guide-toggle.open { color: #F7F7F7; }
.dark-mode .sensitivity-guide-card { background: rgba(255, 255, 255, 0.025); border-color: #242424; }
.dark-mode .sensitivity-guide-lead,
.dark-mode .sensitivity-guide-notes,
.dark-mode .sensitivity-guide-row { color: var(--bk-text-2); }
.dark-mode .sensitivity-guide-heading,
.dark-mode .sensitivity-guide-text span,
.dark-mode .sensitivity-guide-use { color: var(--bk-text-3); }
.dark-mode .sensitivity-guide-option { color: #F7F7F7; }
.dark-mode .sensitivity-guide-option:hover { background: rgba(255, 255, 255, 0.08); }
.dark-mode .sensitivity-guide-option.active { background: rgba(255, 255, 255, 0.12); }
.dark-mode .sensitivity-guide-value { background: var(--bk-input); box-shadow: inset 0 0 0 1px #303030; }
.dark-mode .sensitivity-guide-notes strong { color: #F5B942; }
.dark-mode .sensitivity-guide-row.current { background: rgba(255, 255, 255, 0.08); color: #F7F7F7; }

.sensitivity-dropdown-menu::-webkit-scrollbar {
  width: 6px;
}

.sensitivity-dropdown-menu::-webkit-scrollbar-track {
  background: transparent;
}

.sensitivity-dropdown-menu::-webkit-scrollbar-thumb {
  background: rgba(142, 142, 147, 0.2);
  border-radius: 3px;
}

/* ========================================
   INDICATOR PRESETS
   ======================================== */
.preset-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.preset-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.preset-select-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  flex: 1;
  min-width: 0;
  padding: 10px 12px;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 8px;
  color: #1D1D1F;
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.preset-select-btn:hover {
  border-color: rgba(142, 142, 147, 0.4);
}

.preset-select-btn.open {
  border-color: rgba(142, 142, 147, 0.4);
  box-shadow: 0 0 0 3px rgba(142, 142, 147, 0.1);
}

.preset-select-value {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.preset-select-chevron {
  flex-shrink: 0;
  color: #8E8E93;
  transition: transform 0.18s cubic-bezier(0.4, 0, 0.2, 1);
}

.preset-select-btn.open .preset-select-chevron {
  transform: rotate(180deg);
}

.preset-save-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  padding: 10px 12px;
  background: rgba(0, 0, 0, 0.04);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 8px;
  color: #1D1D1F;
  font-family: var(--font-ui);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease;
}

.preset-save-btn:hover:not(:disabled) {
  background: rgba(0, 0, 0, 0.07);
}

/* Inline list rather than a portalled popover, so it scrolls with the panel
   instead of detaching from its button. The section sits at the bottom of the
   Inputs tab, so opening it scrolls the new content into view (see the
   scrollIntoView effect that watches presetMenuOpen / isNamingPreset). */
.preset-menu {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 190px;
  overflow-y: auto;
  padding: 4px;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 10px;
}

.preset-empty {
  padding: 10px 10px;
  color: #8E8E93;
  font-family: var(--font-ui);
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.45;
}

.preset-item {
  display: flex;
  align-items: center;
  gap: 2px;
  border-radius: 8px;
  transition: background 0.12s ease;
}

.preset-item:hover {
  background: rgba(0, 0, 0, 0.05);
}

.preset-item.active {
  background: rgba(0, 0, 0, 0.06);
}

.preset-item-load {
  flex: 1;
  min-width: 0;
  padding: 9px 10px;
  background: transparent;
  border: none;
  border-radius: 8px;
  color: #1D1D1F;
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  text-align: left;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
}

.preset-item.active .preset-item-load {
  font-weight: 600;
}

.preset-item-action {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  background: transparent;
  border: none;
  border-radius: 7px;
  color: #8E8E93;
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease;
}

.preset-item-action:hover:not(:disabled) {
  background: rgba(0, 0, 0, 0.07);
  color: #1D1D1F;
}

.preset-item-action.danger:hover:not(:disabled) {
  background: rgba(255, 59, 48, 0.1);
  color: var(--danger-red);
}

.preset-name-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.preset-name-input {
  flex: 1;
  min-width: 0;
  padding: 10px 12px;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 8px;
  color: #1D1D1F;
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  outline: none;
}

.preset-name-confirm,
.preset-name-cancel {
  flex-shrink: 0;
  padding: 10px 14px;
  border-radius: 8px;
  font-family: var(--font-ui);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  border: 1px solid transparent;
}

.preset-name-confirm {
  background: #1D1D1F;
  color: #FFFFFF;
}

.preset-name-confirm:hover:not(:disabled) {
  background: #2C2C2E;
}

.preset-name-cancel {
  background: transparent;
  border-color: rgba(0, 0, 0, 0.1);
  color: #48484A;
}

.preset-name-cancel:hover {
  background: rgba(0, 0, 0, 0.04);
}

.preset-message {
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 500;
  color: #48484A;
  padding: 0 2px;
}

.preset-message.error {
  color: var(--danger-red);
}

.style-row {
  display: flex;
  align-items: center;
  padding: 12px 0;
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}

.style-checkbox-label {
  display: flex;
  align-items: center;
  gap: 12px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  color: #1D1D1F;
}

.style-checkbox-label input[type="checkbox"] {
  width: 18px;
  height: 18px;
  cursor: pointer;
}

.style-color-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 0;
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}

.style-color-row label {
  font-size: 13px;
  font-weight: 500;
  color: #48484A;
}

.style-color-row input[type="color"] {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 2px solid rgba(0, 0, 0, 0.1);
  cursor: pointer;
  padding: 0;
  background: white;
  transition: all 0.2s ease;
}

.style-color-row input[type="color"]:hover {
  ;
  border-color: rgba(0, 0, 0, 0.3);
}

.visibility-row {
  display: flex;
  align-items: center;
  padding: 12px 0;
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}

.visibility-checkbox-label {
  display: flex;
  align-items: center;
  gap: 12px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  color: #1D1D1F;
}

.visibility-checkbox-label input[type="checkbox"] {
  width: 18px;
  height: 18px;
  cursor: pointer;
}

.style-visibility-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 0;
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}

.style-visibility-left {
  display: flex;
  align-items: center;
  gap: 12px;
}

.style-visibility-left input[type="checkbox"] {
  width: 18px;
  height: 18px;
  cursor: pointer;
}

.style-visibility-left span {
  font-size: 14px;
  font-weight: 600;
  color: #1D1D1F;
}

.style-visibility-right {
  display: flex;
  align-items: center;
  gap: 12px;
  position: relative;
}

/* Rendered only while a colour is set - see the Design elements row. Quiet on purpose: it
   undoes a choice, it is not one of its own. */
.shell-color-reset {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-size: 11px;
  font-weight: 500;
  color: var(--bk-text-2);
  cursor: pointer;
}

.shell-color-reset:hover {
  color: var(--bk-text);
}

.style-visibility-right label {
  font-size: 13px;
  font-weight: 500;
  color: #48484A;
}

.chart-candles-select {
  padding: 8px 12px;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 8px;
  color: #1D1D1F;
  font-size: 13px;
  font-family: var(--font-ui);
  font-weight: 500;
  outline: none;
  cursor: pointer;
  min-width: 100px;
}

.chart-candles-select:focus {
  border-color: rgba(142, 142, 147, 0.4);
  box-shadow: 0 0 0 3px rgba(142, 142, 147, 0.1);
}

/* Chart design templates -------------------------------------------------- */
/* A block rather than a .style-visibility-row: the rows in this panel are one label and
   one control on a single line, and six previews do not fit that shape at any width worth
   supporting. It keeps the same bottom rule so it still reads as part of the list. */
.chart-template-block {
  padding: 12px 0;
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}

.chart-template-header {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 10px;
}

.chart-template-header span:first-child {
  font-size: 14px;
  font-weight: 600;
  color: #1D1D1F;
}

.chart-template-custom {
  font-size: 11px;
  font-weight: 500;
  color: var(--bk-text-2, #8E8E93);
}

/* auto-fit rather than a fixed count, so the six chips reflow to three, two or one column
   as the drawer narrows without a media query per breakpoint. */
.chart-template-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(92px, 1fr));
  gap: 8px;
}

.chart-template-chip {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  padding: 6px;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 10px;
  cursor: pointer;
  font: inherit;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}

.chart-template-chip:hover {
  border-color: rgba(var(--brand-rgb, 90, 51, 245), 0.45);
  transform: translateY(-1px);
}

.chart-template-chip.active {
  border-color: var(--brand, #5A33F5);
  box-shadow: 0 0 0 3px rgba(var(--brand-rgb, 90, 51, 245), 0.16);
}

/* The chequerboard is what a fully transparent template background sits on, so "follows
   the app" is visible as itself rather than as an accidental white swatch. */
.chart-template-preview {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 46px;
  border-radius: 6px;
  overflow: hidden;
  background-image:
    linear-gradient(45deg, rgba(0, 0, 0, 0.06) 25%, transparent 25%),
    linear-gradient(-45deg, rgba(0, 0, 0, 0.06) 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, rgba(0, 0, 0, 0.06) 75%),
    linear-gradient(-45deg, transparent 75%, rgba(0, 0, 0, 0.06) 75%);
  background-size: 10px 10px;
  background-position: 0 0, 0 5px, 5px -5px, -5px 0;
}

/* The inline background sits on its own layer above the chequerboard, so an opaque
   template covers it and a transparent one lets it through. */
.chart-template-preview > * {
  position: relative;
  z-index: 1;
}

.chart-template-candle {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 10px;
  height: 34px;
}

.chart-template-wick {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 2px;
  border-radius: 1px;
}

.chart-template-body {
  position: relative;
  width: 10px;
  height: 20px;
  border-radius: 2px;
  box-sizing: border-box;
}

.chart-template-body.short {
  height: 13px;
}

.chart-template-name {
  font-size: 11px;
  font-weight: 600;
  color: #1D1D1F;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dark-mode .chart-template-block {
  border-bottom: 1px solid var(--bk-border);
}

.dark-mode .chart-template-header span:first-child,
.dark-mode .chart-template-name {
  color: #F7F7F7;
}

.dark-mode .chart-template-chip {
  background: rgba(30, 30, 30, 0.9);
  border-color: rgba(255, 255, 255, 0.12);
}

.dark-mode .chart-template-preview {
  background-image:
    linear-gradient(45deg, rgba(255, 255, 255, 0.07) 25%, transparent 25%),
    linear-gradient(-45deg, rgba(255, 255, 255, 0.07) 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, rgba(255, 255, 255, 0.07) 75%),
    linear-gradient(-45deg, transparent 75%, rgba(255, 255, 255, 0.07) 75%);
}

.custom-color-picker-simple {
  position: relative;
  display: inline-block;
  cursor: pointer;
}

.custom-color-picker-simple .color-preview-simple {
  display: block;
  width: 36px;
  height: 36px;
  border-radius: 6px;
  border: 2px solid rgba(0, 0, 0, 0.4);
  cursor: pointer;
  transition: all 0.2s ease;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.3);
}

.custom-color-picker-simple:hover .color-preview-simple {
  border-color: rgba(0, 0, 0, 0.5);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.4);
}

.indicator-settings-footer {
  display: flex;
  gap: 12px;
  padding: 16px 24px;
  border-top: 1px solid rgba(0, 0, 0, 0.08);
}

/* Plays the walkthrough again. Left of the other two and pushed away from them, because it
   explains rather than changes anything - see the margin-left: auto on Reset Colors. */
.indicator-rewatch-tour-btn {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 10px 14px;
  background: transparent;
  border: 1px solid rgba(142, 142, 147, 0.3);
  border-radius: 10px;
  color: #1D1D1F;
  font-size: 13px;
  font-family: var(--font-ui);
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s ease;
}

.indicator-rewatch-tour-btn:hover {
  background: rgba(142, 142, 147, 0.14);
}

/* A flex child with no explicit basis will shrink, and an SVG shrinks all the way: on the
   phone footer, where the buttons share the row, this one was squashed to zero width and the
   button lost its icon without losing its gap. */
.indicator-rewatch-tour-btn svg {
  flex: none;
}

.dark-mode .indicator-rewatch-tour-btn {
  border-color: var(--bk-border);
  color: var(--bk-text);
}

.dark-mode .indicator-rewatch-tour-btn:hover {
  background: rgba(255, 255, 255, 0.07);
}

.indicator-reset-colors-btn {
  flex: 0 0 auto;
  padding: 10px 18px;
  background: rgba(142, 142, 147, 0.15);
  border: 1px solid rgba(142, 142, 147, 0.3);
  border-radius: 10px;
  color: #1D1D1F;
  font-size: 14px;
  font-family: var(--font-ui);
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s ease;
}

.indicator-reset-colors-btn:hover {
  /* Neutral enough to read as a divider in both themes without a theme class. */
  background: rgba(142, 142, 147, 0.45);
  border-color: rgba(142, 142, 147, 0.4);
}

.indicator-cancel-settings-btn {
  flex: 0 0 auto;
  padding: 12px 20px;
  background: rgba(142, 142, 147, 0.15);
  border: 1px solid rgba(142, 142, 147, 0.3);
  border-radius: 10px;
  color: #1D1D1F;
  font-size: 14px;
  font-family: var(--font-ui);
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s ease;
}

.indicator-cancel-settings-btn:hover {
  /* Neutral enough to read as a divider in both themes without a theme class. */
  background: rgba(142, 142, 147, 0.45);
  border-color: rgba(142, 142, 147, 0.4);
}

/* The row is read left to right: play the walkthrough, undo the colours, then commit. The
   first two are sized by their labels and sit together; this one takes the rest of the row,
   which is what makes it read as the action the panel is for. */
.indicator-apply-settings-btn {
  flex: 1;
  padding: 10px 18px;
  background: rgba(142, 142, 147, 0.15);
  border: 1px solid rgba(142, 142, 147, 0.3);
  border-radius: 10px;
  color: #1D1D1F;
  font-size: 14px;
  font-family: var(--font-ui);
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s ease;
}

.indicator-apply-settings-btn:hover {
  /* Neutral enough to read as a divider in both themes without a theme class. */
  background: rgba(142, 142, 147, 0.45);
  border-color: rgba(142, 142, 147, 0.4);
}

.indicator-apply-btn:hover {
  background: rgba(142, 142, 147,0.25);
}

.indicator-apply-btn:active {
  background: rgba(142, 142, 147,0.35);
}

/* ========================================
   ASSET TICKER OVERLAY
   ======================================== */
.asset-ticker-overlay {
  position: absolute;
  top: 12px;
  left: 12px;
  display: flex;
  align-items: center;
  gap: 8px;
  z-index: 60;
  pointer-events: none;
  user-select: none;
  font-size: 14px;
  font-family: var(--font-mono);
  font-weight: 700;
  color: #1D1D1F;
  line-height: 1;
}

.asset-ticker-symbol {
  color: #1D1D1F;
  font-weight: 700;
}

.asset-ticker-timeframe {
  color: #1D1D1F;
  font-weight: 700;
}

.asset-ticker-separator {
  color: #8E8E93;
  font-weight: 400;
}

/* The exchange between market and timeframe (crypto: COINBASE), set exactly
   like the two either side of it. */
.asset-ticker-exchange {
  color: #1D1D1F;
  font-weight: 700;
}

.dark-mode .asset-ticker-exchange {
  color: #F7F7F7;
  opacity: 1;
}

.asset-ticker-price {
  color: #1D1D1F;
}

/* ── the legend as a control ───────────────────────────────────────────────
   The overlay keeps pointer-events:none so a drag started in this corner still
   pans the chart underneath. Only the two controls take the pointer back. */
.asset-ticker-main {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 7px;
  margin: -3px -7px;
  border: none;
  border-radius: 6px;
  background: transparent;
  font: inherit;
  color: inherit;
  cursor: pointer;
  pointer-events: auto;
  transition: background var(--transition-speed) ease;
}

.asset-ticker-main:hover {
  background: rgba(142, 142, 147, 0.16);
}

.dark-mode .asset-ticker-main:hover {
  background: rgba(255, 255, 255, 0.10);
}

/* Hidden until the legend is hovered, the way the market rows reveal theirs.
   visibility rather than display: the row keeps its width either way, so the
   ticker beside it never shifts as the icons come and go. */
.asset-ticker-actions {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-left: 2px;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--transition-speed) ease, visibility var(--transition-speed) ease;
}

.asset-ticker-overlay:hover .asset-ticker-actions,
.asset-ticker-overlay:focus-within .asset-ticker-actions {
  opacity: 1;
  visibility: visible;
}

.asset-ticker-act {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: none;
  border-radius: 5px;
  background: transparent;
  color: #8E8E93;
  cursor: pointer;
  pointer-events: auto;
  transition: background var(--transition-speed) ease, color var(--transition-speed) ease;
}

.asset-ticker-act:hover {
  background: rgba(142, 142, 147, 0.16);
  color: #1D1D1F;
}

.asset-ticker-act.on {
  color: #F59E0B;
}

.asset-ticker-act.on:hover {
  color: #D97C06;
}

.dark-mode .asset-ticker-act {
  color: var(--bk-text-2);
}

.dark-mode .asset-ticker-act:hover {
  background: rgba(255, 255, 255, 0.10);
  color: #F7F7F7;
}

.dark-mode .asset-ticker-act.on {
  color: #FFD60A;
}

/* Nothing hovers on a touch screen, so the three controls would be unreachable.
   They sit out permanently there instead. */
@media (hover: none) {
  .asset-ticker-actions {
    opacity: 1;
    visibility: visible;
  }

  /* mobile.css gives every button a 44px box. That is the right size for a thumb and
     the wrong size for an 11px legend: it took the row to 44px tall and pushed it down
     into the trade ticket. So the drawn box stays small and the 44px target is restored
     as an invisible inset overlay - the legend keeps its line, the thumb keeps its
     target. Same reasoning for the label: it carries its own target rather than the
     blanket one. */
  .asset-ticker-main,
  .asset-ticker-act {
    min-width: 0;
    min-height: 0;
  }

  .asset-ticker-main {
    padding: 6px 7px;
    margin: -6px -7px;
  }

  .asset-ticker-act {
    width: 26px;
    height: 26px;
    padding: 0;
    position: relative;
  }

  .asset-ticker-act::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
  }
}

/* Das Zeichen des Assets, links vom Kürzel. Es sitzt in derselben flex-Reihe wie
   der Text, nimmt also den 8px-Abstand der Legende mit; eine eigene Marge würde
   sich damit addieren. Kein pointer-events nötig - die Legende ist als Ganzes
   durchlässig, damit ein Zug in dieser Ecke weiterhin den Chart bewegt. */
.asset-ticker-logo {
  width: 17px;
  height: 17px;
  flex-shrink: 0;
  border-radius: 50%;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 9px;
  font-weight: 700;
  color: #FFFFFF;
  line-height: 1;
}

.asset-ticker-logo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

/* ========================================
   INDICATOR BADGES OVERLAY
   ======================================== */
.indicator-badges-overlay {
  position: absolute;
  top: 78px;
  left: 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  z-index: 50;
  pointer-events: all;
}

.indicator-badge {
  display: flex;
  flex-direction: column;
  gap: 0;
  background: transparent;
  transition: all 0.2s ease;
  cursor: default;
}

/* An oscillator's badge is portalled into its own pane rather than living in the overlay
   above, so it positions itself against that pane. `left` matches
   .indicator-badges-overlay so a pane legend lines up with the price-chart badges. The
   box shrink-wraps its content, leaving the rest of the pane free for the chart's own
   mouse handling. */
.indicator-badge-in-pane {
  position: absolute;
  top: 6px;
  left: 12px;
  z-index: 3;
  pointer-events: all;
}

.indicator-badge-content {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1;
  min-width: 0;
}

.indicator-badge-color {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  flex-shrink: 0;
}

.indicator-badge-name {
  font-size: 13px;
  font-weight: 500;
  color: #1D1D1F;
  font-family: var(--font-ui);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
}

.indicator-badge-icon-btn {
  background: transparent;
  border: none;
  color: #8E8E93;
  cursor: pointer;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.15s ease;
  opacity: 0.8;
}

.indicator-badge-icon-btn:hover {
  opacity: 1;
  color: #48484A;
}

.indicator-badge-controls {
  display: flex;
  align-items: center;
  gap: 3px;
  animation: badgeControlsFadeIn 0.15s ease-out;
}

@keyframes badgeControlsFadeIn {
  from {
    opacity: 0;
    transform: translateX(-4px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

.indicator-badge-btn {
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(142, 142, 147, 0.08);
  border: 1px solid rgba(142, 142, 147, 0.15);
  border-radius: 8px;
  color: #8E8E93;
  cursor: pointer;
  transition: all 0.15s ease;
  flex-shrink: 0;
}

.indicator-badge-btn:hover {
  background: rgba(142, 142, 147, 0.15);
  border-color: rgba(142, 142, 147, 0.3);
  color: #48484A;
}

.indicator-badge-delete:hover {
  background: rgba(255, 59, 48, 0.1);
  border-color: rgba(255, 59, 48, 0.3);
  color: #FF3B30;
}

.indicator-badge-settings:hover {
  background: rgba(0, 122, 255, 0.08);
  border-color: rgba(0, 122, 255, 0.2);
  color: #007AFF;
}

.indicator-badge-inline-settings {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px;
  margin-top: 6px;
  border-top: 1px solid rgba(0, 0, 0, 0.08);
  background: rgba(0, 0, 0, 0.02);
  border-radius: 0 0 6px 6px;
  animation: badgeSettingsFadeIn 0.2s ease-out;
}

@keyframes badgeSettingsFadeIn {
  from {
    opacity: 0;
    max-height: 0;
    padding-top: 0;
    padding-bottom: 0;
  }
  to {
    opacity: 1;
    max-height: 500px;
    padding-top: 10px;
    padding-bottom: 10px;
  }
}

.indicator-badge-clickable {
  cursor: pointer;
}

.indicator-badge-clickable:hover {
  color: #48484A;
}

.indicator-badge-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 4px 0;
}

.indicator-badge-icons {
  display: flex;
  align-items: center;
  gap: 6px;
}

.indicator-badge-icon-btn {
  animation: fadeIn 0.15s ease-out;
}

/* ========================================
   DARK MODE STYLES
   ======================================== */

.dark-mode {
  background: #000000;
}

.dark-mode .chart-container {
  background: #000000;
}

.dark-mode .chart-wrapper {
  background: #000000;
  box-shadow: none;
  border: 1px solid #242424;
}

/* Navbar - Dark Mode */
.dark-mode .navbar {
  background: #050505;
  border-bottom: 1px solid var(--bk-border);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03);
}

.dark-mode .profile-picture {
  background: var(--bk-elevated);
  color: #F7F7F7;
  box-shadow: 0 0 0 2px var(--bk-active);
}

.dark-mode .profile-picture:hover {
  box-shadow: 0 0 0 2px var(--bk-active);
}

/* Symbol Button - Dark Mode */
.dark-mode .symbol-btn {
  background: transparent;
  border-color: transparent;
  color: #F7F7F7;
}

.dark-mode .symbol-btn:hover {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.15);
}

.dark-mode .symbol-text {
  color: #F7F7F7;
  font-weight: 700;
}

.dark-mode .symbol-btn::after {
  background: rgba(255, 255, 255, 0.15);
}

/* Timeframe Dropdown - Dark Mode */
.dark-mode .timeframe-dropdown-btn {
  background: transparent;
  border-color: transparent;
  color: #F7F7F7;
}

.dark-mode .timeframe-dropdown-btn:hover {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.15);
}

.dark-mode .timeframe-text {
  color: #F7F7F7;
  font-weight: 600;
}

.dark-mode .timeframe-chevron {
  color: var(--bk-text-2);
}

.dark-mode .timeframe-dropdown-btn::after {
  background: rgba(255, 255, 255, 0.15);
}

.dark-mode .timeframe-dropdown-menu {
  background: #101010;
  border: 1px solid #242424;
}

.dark-mode .symbol-item {
  background: transparent;
  border-bottom: 1px solid var(--bk-border);
}

.dark-mode .symbol-item:not(.disabled):hover {
  background: rgba(255, 255, 255, 0.045);
}

.dark-mode .symbol-favorite-btn {
  color: var(--bk-text-off);
}

.dark-mode .symbol-item:hover .symbol-favorite-btn {
  opacity: 1;
}

.dark-mode .indicator-item:hover .symbol-favorite-btn {
  opacity: 1;
}

.dark-mode .symbol-favorite-btn.favorite {
  opacity: 1;
  color: #FFD24D;
}

.dark-mode .symbol-favorite-btn:hover {
  color: #FFE066;
}

.dark-mode .symbol-watchlist-btn {
  color: var(--bk-text-off);
}

.dark-mode .symbol-item:hover .symbol-watchlist-btn {
  opacity: 1;
}

.dark-mode .symbol-watchlist-btn.watched {
  opacity: 1;
  color: #0A84FF;
}

.dark-mode .symbol-watchlist-btn:hover {
  color: #7FBEFF;
}

.dark-mode .watchlist-picker {
  background: #101010;
  border: 1px solid #242424;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.55);
}

.dark-mode .watchlist-picker-title h3 {
  color: #F5F5F7;
}

.dark-mode .watchlist-picker-row {
  color: #F5F5F7;
}

.dark-mode .watchlist-picker-row:hover {
  background: rgba(255, 255, 255, 0.07);
}

.dark-mode .watchlist-picker-check {
  border-color: var(--bk-border);
}

.dark-mode .watchlist-picker-row.checked .watchlist-picker-check {
  background: #0A84FF;
  border-color: #0A84FF;
}

.dark-mode .watchlist-picker-create {
  border-top: 1px solid var(--bk-border);
}

.dark-mode .watchlist-picker-create input {
  background: rgba(255, 255, 255, 0.06);
  border-color: var(--bk-border);
  color: #F5F5F7;
}

.dark-mode .watchlist-picker-create input:focus {
  border-color: #0A84FF;
}

.dark-mode .timeframe-option {
  background: transparent;
}

.dark-mode .timeframe-option:hover {
  background: rgba(255, 255, 255, 0.1);
}

.dark-mode .timeframe-option.active {
  background: rgba(255, 255, 255, 0.15);
}

/* Icons and Buttons - Dark Mode */
.dark-mode .icon-btn {
  width: 34px;
  height: 34px;
  color: #F7F7F7;
  background: transparent;
  border: 1px solid transparent;
}

.dark-mode .icon-btn:hover {
  background: rgba(255, 255, 255, 0.06);
}

/* Der Werkzeugknopf war das einzige gruene Element in der Leiste.
   ───────────────────────────────────────────────────────────────
   .icon-btn traegt nur dieser eine Knopf (JSX: title="Tools"), und offen stand er auf
   einem gruenen Wasch mit gruenem Rahmen - eine Signalfarbe fuer "das Menue ist auf",
   waehrend jeder andere geoeffnete Knopf der Leiste dafuer nur eine Graustufe benutzt.
   Durch den 150ms-Uebergang auf background las sich das Aufgehen als gruenes Aufleuchten.

   Jetzt --bk-active, dieselbe Flaeche, die der Hellmodus schon immer hatte und die auch
   :active auf den Leistenknoepfen setzt. Der Rahmen bleibt, damit die Hoehe stimmt, wird
   aber unsichtbar - transparent statt entfernt, weil .icon-btn 1px Rahmen einrechnet. */
.dark-mode .icon-btn.active {
  background: var(--bk-active);
  color: var(--bk-text);
  border: 1px solid transparent;
}

/* Gleiche Flaeche wie im Ruhezustand, wie im Hellmodus auch: ein Knopf, dessen Menue
   offen ist, hat nichts mehr anzubieten, worauf ein Hover hinweisen koennte. */
.dark-mode .icon-btn.active:hover {
  background: var(--bk-active);
  color: var(--bk-text);
  border: 1px solid transparent;
}

/* Drawing Toolbar - Dark Mode */
.dark-mode .drawing-toolbar {
  background: #111111;
  border: 1px solid #242424;
  box-shadow: none;
  padding: 12px 0;
  gap: 8px;
}

/* --bk-text-2 is #949494 in dark mode, which left the rail's icons at 6.0:1 against the
   #151619 the shell paints under them. The same icons in light mode rest at #3A3A3C on
   #FAFAFA - 10.9:1 - and the navbar's icon buttons a few pixels away rest at #F7F7F7, so
   the rail read as the one dim run of chrome on the screen rather than as a deliberate
   resting state. #E8E8E8 measures 14.8:1 and sits with the navbar, while staying a step
   under the #F7F7F7 that hover and active use so the three states still separate.

   Note the back is #151619, not the #111111 set on .dark-mode .drawing-toolbar above:
   a later rule repaints the three bars, and that is what these icons land on. */
.dark-mode .tool-btn {
  color: #E8E8E8;
  background: transparent;
  width: 36px;
  height: 36px;
  padding: 8px;
}

.dark-mode .tool-btn:hover {
  color: #F7F7F7;
  background: transparent;
}

.dark-mode .tool-btn:hover::before {
  background: rgba(255, 255, 255, 0.1);
}

.dark-mode .tool-btn.active {
  color: #F7F7F7;
  background: transparent;
}

.dark-mode .tool-btn.active::before,
.dark-mode .tool-group:hover .tool-btn.active::before,
.dark-mode .tool-group:has(.tool-group-caret.open) .tool-btn.active::before {
  background: rgba(255, 255, 255, 0.15);
}

.dark-mode .tool-divider {
  background: rgba(255, 255, 255, 0.2);
  width: 28px;
  height: 1px;
  margin: 8px 0;
}

.dark-mode .tool-badge {
  background: #FFFFFF;
  color: #000000;
}

/* Pen Toolbar - Dark Mode */
.dark-mode .pen-toolbar {
  background: rgba(50, 50, 55, 0.95);
  border: 1px solid var(--bk-border);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6), 0 0 1px rgba(255, 255, 255, 0.15);
}

.dark-mode .pen-toolbar-handle {
  border-right: 1px solid var(--bk-border);
  color: var(--bk-text-2);
}

.dark-mode .pen-toolbar-section {
  border-right: 1px solid var(--bk-border);
}

/* Same rail, same resting state - see .dark-mode .tool-btn above. */
.dark-mode .pen-tool-btn {
  color: #E8E8E8;
}

.dark-mode .pen-tool-btn:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.15);
  color: #F7F7F7;
}

.dark-mode .pen-tool-btn.active {
  background: rgba(255, 255, 255, 0.2);
  border-color: rgba(255, 255, 255, 0.25);
  color: #F7F7F7;
}

.dark-mode .pen-current-color {
  border-right: 1px solid var(--bk-border);
}

.dark-mode .pen-current-color:hover {
  background: rgba(255, 255, 255, 0.1);
}

.dark-mode .pen-color-display {
  border: 2px solid var(--bk-border);
}

.dark-mode .pen-dropdown-icon {
  color: var(--bk-text-2);
}

.dark-mode .pen-current-color:hover .pen-dropdown-icon {
  color: #F7F7F7;
}

.dark-mode .pen-color-dropdown {
  background: rgba(70, 70, 75, 0.98);
  border: 1px solid var(--bk-border);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.7);
}

.dark-mode .pen-color-swatch:hover {
  border-color: rgba(255, 255, 255, 0.5);
}

.dark-mode .pen-color-swatch.active {
  border-color: #FFFFFF;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.3);
}

.dark-mode .pen-current-thickness {
  border-right: 1px solid var(--bk-border);
}

.dark-mode .pen-current-thickness:hover {
  background: rgba(255, 255, 255, 0.1);
}

.dark-mode .pen-thickness-text {
  color: var(--bk-text-2);
}

.dark-mode .pen-current-thickness:hover .pen-thickness-text {
  color: #F7F7F7;
}

.dark-mode .pen-thickness-dropdown {
  background: rgba(70, 70, 75, 0.98);
  border: 1px solid var(--bk-border);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.7);
}

.dark-mode .pen-thickness-option {
  color: var(--bk-text-2);
}

.dark-mode .pen-thickness-option:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.15);
  color: #F7F7F7;
}

.dark-mode .pen-thickness-option.active {
  background: rgba(255, 255, 255, 0.2);
  border-color: rgba(255, 255, 255, 0.25);
  color: #F7F7F7;
}

.dark-mode .pen-clear-btn {
  color: #FF453A;
}

.dark-mode .pen-clear-btn:hover {
  background: rgba(255, 69, 58, 0.15);
  color: #FF5F52;
}

/* Pen Opacity Control - Dark Mode */
.dark-mode .pen-opacity-control {
  border-top: 1px solid var(--bk-border);
}

.dark-mode .pen-opacity-label {
  color: var(--bk-text-2);
}

.dark-mode .pen-opacity-slider {
  background: rgba(255, 255, 255, 0.1);
}

.dark-mode .pen-opacity-slider::-webkit-slider-thumb {
  background: #0A84FF;
  border-color: #1C1C1E;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
}

.dark-mode .pen-opacity-slider::-moz-range-thumb {
  background: #0A84FF;
  border-color: #1C1C1E;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
}

.dark-mode .pen-opacity-value {
  color: var(--bk-text-2);
}

/* Custom Color Adder - Dark Mode */
.dark-mode .custom-color-adder {
  background: rgba(70, 70, 75, 0.98);
  border: 1px solid var(--bk-border);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.7);
}

.dark-mode .custom-color-hex-input {
  background: rgba(30, 30, 30, 0.8);
  border: 1px solid var(--bk-border);
  color: var(--bk-text-2);
}

.dark-mode .custom-color-hex-input:focus {
  border-color: #0A84FF;
  box-shadow: 0 0 0 3px rgba(10, 132, 255, 0.2);
}

.dark-mode .custom-color-add-btn {
  background: #0A84FF;
}

.dark-mode .custom-color-add-btn:hover {
  background: #0051D5;
}

.dark-mode .custom-color-cancel-btn {
  border: 1px solid var(--bk-border);
  color: var(--bk-text-2);
}

.dark-mode .custom-color-cancel-btn:hover {
  background: rgba(255, 255, 255, 0.1);
}

.dark-mode .custom-color-spectrum {
  border: 1px solid var(--bk-border);
}

.dark-mode .custom-color-hue-slider {
  border: 1px solid var(--bk-border);
}

.dark-mode .color-picker-add-btn {
  color: rgba(255, 255, 255, 0.4);
}

.dark-mode .color-picker-add-btn:hover {
  color: #0A84FF;
  background: rgba(10, 132, 255, 0.12);
}

.dark-mode .custom-colors-row {
  border-top: 1px solid var(--bk-border);
}

.dark-mode .custom-color-delete {
  background: #FF453A;
  border: 2px solid rgba(70, 70, 75, 0.98);
}

.dark-mode .custom-color-delete:hover {
  background: #FF2D20;
}

/* Color Picker - Dark Mode */
.dark-mode .color-display {
  border: 1px solid var(--bk-border);
}

.dark-mode .color-picker-popup {
  background: #101010;
  border: 1px solid #242424;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
}

/* Bottom Strip - Dark Mode */
.dark-mode .bottom-strip {
  background: #111111;
  border-top: 1px solid #242424;
  box-shadow: none;
}

.dark-mode .strip-label {
  color: var(--bk-text-2);
}

.dark-mode .strip-value {
  color: #F7F7F7;
}

/* Indicator Badges - Dark Mode */
.dark-mode .indicator-badges-overlay {
  color: #F7F7F7;
}

.dark-mode .indicator-badge {
  background: transparent;
  border: none;
  box-shadow: none;
}

.dark-mode .indicator-badge-name {
  color: #F7F7F7;
  font-weight: 600;
}

.dark-mode .indicator-badge-icon-btn {
  color: var(--bk-text-2);
}

.dark-mode .indicator-badge-icon-btn:hover {
  color: #F7F7F7;
  background: rgba(255, 255, 255, 0.1);
}

/* Asset Ticker - Dark Mode */
.dark-mode .asset-ticker-overlay {
  color: #F7F7F7;
  opacity: 1;
}

.dark-mode .asset-ticker-symbol {
  color: #F7F7F7;
  opacity: 1;
  font-weight: 700;
}

.dark-mode .asset-ticker-timeframe {
  color: #F7F7F7;
  opacity: 1;
  font-weight: 700;
}

.dark-mode .asset-ticker-separator {
  color: #F7F7F7;
  opacity: 1;
}

/* Modals - Dark Mode */
.dark-mode .profile-modal,
.dark-mode .alert-modal {
  background: #101010;
  border: 1px solid #242424;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
}

/* Matched to .dark-mode .indicator-modal. This was rgba(19, 22, 28, 0.94) - translucent
   and blue-tinted, where the indicator panel is a flat neutral grey - so the two read as
   different surfaces despite opening from adjacent buttons. The backdrop-filter on the
   base rule is left alone: it now has nothing to show through an opaque background, but
   the indicator modal carries a redundant one too, so removing only this one would be
   the odd case rather than the tidy one. */
.dark-mode .symbol-modal {
  background: #101010;
  border: 1px solid #242424;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
}

.dark-mode .chart-settings-modal {
  background: #101010;
  border: 1px solid #242424;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.8);
}

.dark-mode .chart-settings-header {
  border-bottom: 1px solid #242424;
}

.dark-mode .chart-settings-header h3 {
  color: #F7F7F7;
}

.dark-mode .settings-modal-close {
  color: var(--bk-text-2);
}

.dark-mode .settings-modal-close:hover {
  background: rgba(255, 255, 255, 0.1);
  color: #F7F7F7;
}

.dark-mode .chart-settings-color-picker {
  background: rgba(70, 70, 75, 0.98);
  border: 1px solid var(--bk-border);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.7);
}

.dark-mode .color-picker-swatch::after {
  border: 1px solid var(--bk-border);
}

.dark-mode .color-picker-swatch:hover {
  border-color: rgba(255, 255, 255, 0.5);
}

.dark-mode .color-picker-swatch.active {
  border-color: #FFFFFF;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.3);
}

.dark-mode .modal-header h3,
.dark-mode .drawer-header h3 {
  color: #F7F7F7;
}

.dark-mode .close-btn {
  color: var(--bk-text-2);
  background: transparent;
}

.dark-mode .close-btn:hover {
  color: #F7F7F7;
  background: rgba(255, 255, 255, 0.1);
}

.dark-mode .modal-search-icon {
  color: var(--bk-text-2);
}

.dark-mode .modal-search input {
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--bk-border);
  color: #F7F7F7;
}

.dark-mode .modal-search input::placeholder {
  color: var(--bk-text-2);
}

.dark-mode .category-filters {
  border-bottom: 1px solid var(--bk-border);
}

.dark-mode .section-header {
  color: var(--bk-text-2);
}

.dark-mode .soon-badge {
  background-color: rgba(255, 255, 255, 0.05);
  color: var(--bk-text-2);
}

/* Settings Drawer - Dark Mode */

/* The two indicator settings windows stand on the colour of the three bars.
   ─────────────────────────────────────────────────────────────────────────
   --bk-elevated is the #151619 that the navbar, the tool rail and the bottom strip carry,
   and that every other floating panel - market, indicators, alerts, journal, profile -
   already stands on. These two windows were the last surfaces left a step below it at
   #101010, which is what made them read as a darker hole cut into the app rather than as
   part of it.

   The fields inside follow the same move: --bk-input instead of pure #000000, the token
   the market and indicator search boxes use, so a field is told apart from its panel by
   its border rather than by being black. Colour only - every control keeps the geometry,
   the state classes and the handlers it had. */
.dark-mode .settings-drawer {
  background: var(--bk-elevated);
  border-left: 2px solid #242424;
  box-shadow: -8px 0 32px rgba(0, 0, 0, 0.5);
}

.dark-mode .form-group label {
  color: var(--bk-text-2);
}

.dark-mode .form-group input,
.dark-mode .form-group select {
  background: var(--bk-input);
  border: 1px solid #242424;
  color: #F7F7F7;
}

.dark-mode .form-group input:focus,
.dark-mode .form-group select:focus {
  border-color: #303030;
  background: var(--bk-hover);
}

/* Replay Modal - Dark Mode */
.dark-mode .replay-mode-btn {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid #242424;
}

.dark-mode .replay-mode-btn:hover {
  background: rgba(255, 255, 255, 0.08);
  border-color: #303030;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
}

.dark-mode .replay-mode-icon {
  color: var(--bk-text-2);
}

.dark-mode .replay-mode-text {
  color: #F7F7F7;
}

.dark-mode .replay-mode-desc {
  color: var(--bk-text-2);
}

.dark-mode .replay-mode-divider {
  color: var(--bk-text-2);
}

.dark-mode .replay-mode-datetime {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid #242424;
}

.dark-mode .replay-datetime-label {
  color: var(--bk-text-2);
}

.dark-mode .replay-cal-month {
  color: #F7F7F7;
}

.dark-mode .replay-cal-nav {
  border-color: #242424;
  color: var(--bk-text-2);
}

.dark-mode .replay-cal-nav:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.06);
  color: #F7F7F7;
}

.dark-mode .replay-cal-weekdays span {
  color: var(--bk-text-2);
}

.dark-mode .replay-cal-day {
  color: #F7F7F7;
}

.dark-mode .replay-cal-day:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.08);
}

.dark-mode .replay-cal-day.outside {
  color: #5A5A5A;
}

/* The selection inverts in each theme - dark chip on light, light chip on dark - so it
   reads as the picked day either way rather than disappearing into the panel. */
.dark-mode .replay-cal-day.selected {
  background: #F7F7F7;
  border-color: #F7F7F7;
  color: #0B0B0B;
}

.dark-mode .replay-time-label {
  color: var(--bk-text-2);
}

/* Nothing here but the colours: the geometry above is shared, and both themes now
   draw the same control rather than deferring to whatever the browser ships. */
.dark-mode .replay-time-field {
  background: var(--bk-input);
  border-color: var(--bk-border);
}

.dark-mode .replay-time-field:focus-within {
  border-color: var(--bk-border-strong);
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.06);
}

.dark-mode .replay-time-seg {
  color: var(--bk-text);
}

.dark-mode .replay-time-colon {
  color: var(--bk-text-3);
}

.dark-mode .replay-mode-footer {
  color: var(--bk-text-2);
}

.dark-mode .replay-cut-line {
  border-left-color: #E5E5EA;
}

.dark-mode .replay-cut-scissors {
  background: #E5E5EA;
  color: #0B0B0B;
}

/* Black rather than white here: the veil has to read as taking the candles away, and on a
   black chart a white wash lifts them instead. */
.dark-mode .replay-cut-veil {
  background: rgba(0, 0, 0, 0.45);
}

.dark-mode .selection-tooltip {
  background: rgba(26, 26, 26, 0.95);
  color: #F7F7F7;
  border: 1px solid #242424;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
}

/* Indicator Modal - Dark Mode */
.dark-mode .indicator-modal {
  background: #101010;
  border: 1px solid #242424;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
}

.dark-mode .indicator-modal-handle {
  color: var(--bk-text-2);
}

.dark-mode .indicator-item {
  background: transparent;
  border-bottom: 1px solid var(--bk-border);
}

.dark-mode .indicator-item:hover {
  background: rgba(255, 255, 255, 0.05);
}

.dark-mode .indicator-item-name {
  color: #F7F7F7;
}

.dark-mode .indicator-item-desc {
  color: var(--bk-text-2);
}

.dark-mode .indicator-add-btn {
  color: #F7F7F7;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid var(--bk-border);
}

.dark-mode .indicator-add-btn:hover {
  background: rgba(255, 255, 255, 0.15);
}

/* Tabbed Settings Modal - Dark Mode */

/* Swift Algo X's settings window - same surface as the drawer above, and for the same
   reason. Its header, tabs, content and footer are all transparent, so this one
   declaration carries the whole window; the sensitivity trigger, the preset controls and
   the colour swatches inside it come off #000000 onto --bk-input further down. */
.dark-mode .indicator-settings-modal-wrapper {
  background: var(--bk-elevated);
  border: 1px solid #242424;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.8);
}

.dark-mode .indicator-settings-modal-header {
  border-bottom: 1px solid #242424;
}

.dark-mode .indicator-settings-modal-header h3 {
  color: #F7F7F7;
}

.dark-mode .indicator-settings-tabs {
  border-bottom: 2px solid #242424;
}

.dark-mode .indicator-settings-tab {
  color: var(--bk-text-2);
}

.dark-mode .indicator-settings-tab:hover {
  color: var(--bk-text-2);
}

.dark-mode .indicator-settings-tab.active {
  color: #F7F7F7;
  border-bottom-color: #FFFFFF;
}

.dark-mode .settings-section-header {
  color: var(--bk-text-2);
}

.dark-mode .indicator-param-row label {
  color: var(--bk-text-2);
}

.dark-mode .indicator-param-row input[type="number"],
.dark-mode .indicator-param-row input[type="text"],
.dark-mode .indicator-param-row select {
  background: var(--bk-input);
  border: 1px solid #242424;
  color: #F7F7F7;
}

.dark-mode .indicator-param-row input[type="number"]:focus,
.dark-mode .indicator-param-row input[type="text"]:focus,
.dark-mode .indicator-param-row select:focus {
  border-color: #303030;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.05);
}

/* Info "i" and its card - dark mode */
.dark-mode .info-tip-btn {
  color: var(--bk-text-3);
}

.dark-mode .info-tip-btn:hover,
.dark-mode .info-tip-btn.open {
  color: #F7F7F7;
  background: rgba(255, 255, 255, 0.1);
}

.dark-mode .info-tip-popover {
  background: var(--bk-card);
  border-color: #242424;
  color: var(--bk-text-2);
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.6);
}

/* Indicator Sensitivity picker - dark mode. Trigger matches the panel's inputs; the popup
   matches .timeframe-dropdown-menu, the navbar's equivalent picker. */
.dark-mode .sensitivity-dropdown-btn {
  background: var(--bk-input);
  border-color: #242424;
  color: #F7F7F7;
}

.dark-mode .sensitivity-dropdown-btn:hover,
.dark-mode .sensitivity-dropdown-btn.open {
  border-color: #303030;
}

.dark-mode .sensitivity-dropdown-btn.open {
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.05);
}

/* Indicator presets - dark mode */
.dark-mode .preset-select-btn,
.dark-mode .preset-name-input {
  background: var(--bk-input);
  border-color: #242424;
  color: #F7F7F7;
}

.dark-mode .preset-select-btn:hover,
.dark-mode .preset-select-btn.open {
  border-color: #303030;
}

.dark-mode .preset-select-btn.open {
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.05);
}

.dark-mode .preset-save-btn {
  background: rgba(255, 255, 255, 0.06);
  border-color: #242424;
  color: #F7F7F7;
}

.dark-mode .preset-save-btn:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.1);
}

.dark-mode .preset-menu {
  background: var(--bk-card);
  border-color: #242424;
}

.dark-mode .preset-item:hover {
  background: rgba(255, 255, 255, 0.06);
}

.dark-mode .preset-item.active {
  background: rgba(255, 255, 255, 0.09);
}

.dark-mode .preset-item-load {
  color: #F7F7F7;
}

.dark-mode .preset-item-action:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.1);
  color: #F7F7F7;
}

.dark-mode .preset-name-confirm {
  background: #FFFFFF;
  color: #1D1D1F;
}

.dark-mode .preset-name-confirm:hover:not(:disabled) {
  background: #E5E5EA;
}

.dark-mode .preset-name-cancel {
  border-color: #242424;
  color: var(--bk-text-3);
}

.dark-mode .preset-name-cancel:hover {
  background: rgba(255, 255, 255, 0.06);
}

.dark-mode .preset-message {
  color: var(--bk-text-3);
}

.dark-mode .preset-empty {
  color: var(--bk-text-3);
}

.dark-mode .sensitivity-dropdown-menu {
  background: var(--bk-card);
  border-color: #242424;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.6);
}

.dark-mode .sensitivity-dropdown-item {
  color: #F7F7F7;
}

.dark-mode .sensitivity-dropdown-item:hover {
  background: rgba(255, 255, 255, 0.08);
}

.dark-mode .sensitivity-dropdown-item.active {
  background: rgba(255, 255, 255, 0.12);
}

.dark-mode .sensitivity-dropdown-menu::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.15);
}

/* Segmented control - dark mode. Track border matches the inputs/selects above. */
.dark-mode .signal-mode-segmented {
  background: rgba(255, 255, 255, 0.04);
  border-color: #242424;
}

.dark-mode .signal-mode-option {
  color: var(--bk-text-2);
}

.dark-mode .signal-mode-option:hover:not(.active) {
  background: rgba(255, 255, 255, 0.06);
  color: #F7F7F7;
}

.dark-mode .signal-mode-option.active {
  background: #2A2A2A;
  color: #F7F7F7;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}

.dark-mode .signal-mode-option:focus-visible {
  outline-color: rgba(255, 255, 255, 0.4);
}

.dark-mode .indicator-param-row input[type="color"] {
  border: 2px solid #242424;
}

.dark-mode .indicator-param-row input[type="color"]:hover {
  border-color: rgba(255, 255, 255, 0.3);
}

.dark-mode .style-row,
.dark-mode .style-color-row,
.dark-mode .visibility-row,
.dark-mode .style-visibility-row {
  border-bottom: 1px solid var(--bk-border);
}

.dark-mode .style-checkbox-label,
.dark-mode .visibility-checkbox-label {
  color: #F7F7F7;
}

.dark-mode .style-color-row label {
  color: var(--bk-text-2);
}

.dark-mode .style-color-row input[type="color"] {
  background: var(--bk-input);
  border: 2px solid #242424;
}

.dark-mode .style-color-row input[type="color"]:hover {
  border-color: rgba(255, 255, 255, 0.3);
}

.dark-mode .style-visibility-left span {
  color: #F7F7F7;
}

.dark-mode .style-visibility-right label {
  color: var(--bk-text-2);
}

.dark-mode .chart-candles-select {
  background: rgba(30, 30, 30, 0.9);
  border: 1px solid var(--bk-border);
  color: #F7F7F7;
}

.dark-mode .chart-candles-select:focus {
  border-color: rgba(255, 255, 255, 0.3);
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.1);
}

.dark-mode .custom-color-picker-simple .color-preview-simple {
  border: 2px solid var(--bk-border);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.2);
}

.dark-mode .custom-color-picker-simple:hover .color-preview-simple {
  border-color: rgba(0, 0, 0, 0.7);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.3);
}

.dark-mode .indicator-settings-footer {
  border-top: 1px solid #242424;
}

.dark-mode .indicator-cancel-settings-btn {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid #242424;
  color: #F7F7F7;
}

.dark-mode .indicator-cancel-settings-btn:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: #303030;
}

.dark-mode .indicator-reset-colors-btn {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid #242424;
  color: #F7F7F7;
}

.dark-mode .indicator-reset-colors-btn:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: #303030;
}

.dark-mode .indicator-apply-settings-btn {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid #242424;
  color: #F7F7F7;
}

.dark-mode .indicator-apply-settings-btn:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: #303030;
}

/* Symbol Categories - Dark Mode */
.dark-mode .symbol-categories {
  border-bottom: 1px solid var(--bk-border);
}

.dark-mode .category-btn {
  color: var(--bk-text-2);
  background: transparent;
  border: 1px solid var(--bk-border);
}

.dark-mode .category-btn:hover {
  color: #F7F7F7;
  border-color: rgba(255, 255, 255, 0.22);
}

.dark-mode .category-btn.active {
  color: #0B0E11;
  background: #FFFFFF;
  border-color: #FFFFFF;
}

.dark-mode .category-btn.active:hover {
  background: #E5E5EA;
  border-color: #E5E5EA;
}

.dark-mode .symbol-list-item {
  background: transparent;
  border-bottom: 1px solid var(--bk-border);
  color: #F7F7F7;
}

.dark-mode .symbol-list-item:hover {
  background: rgba(255, 255, 255, 0.05);
}

.dark-mode .symbol-list-item.unavailable {
  color: var(--bk-text-2);
}

.dark-mode .symbol-item {
  background: transparent;
  border-bottom: 1px solid var(--bk-border);
  color: #F7F7F7;
}

.dark-mode .replay-exit-btn:hover {
  color: #F7F7F7;
  border-color: rgba(255, 255, 255, 0.4);
  background: rgba(255, 255, 255, 0.08);
}

.trend-table-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 12px;
  color: #1D1D1F;
  letter-spacing: 0px;
  cursor: grab;
  user-select: none;
  background: transparent;
}

.trend-table-header:active {
  cursor: grabbing;
}

.trend-table {
  width: 100%;
  font-family: var(--font-ui);
  font-size: 10px;
  padding: 14px;
}

.trend-table-row {
  display: grid;
  grid-template-columns: 60px 45px 65px 50px;
  gap: 6px;
  padding: 8px 0;
  background: transparent;
  border: none;
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
  align-items: center;
  transition: all 0.2s ease;
  border-radius: 0;
  margin: 0;
  font-weight: 500;
}

.trend-table-row:hover {
  background: rgba(0, 0, 0, 0.02);
  transform: none;
  box-shadow: none;
}

.trend-table-header-row {
  display: grid;
  grid-template-columns: 60px 45px 65px 50px;
  gap: 6px;
  font-weight: 600;
  font-size: 7px;
  color: #48484A;
  background: transparent;
  border: none;
  border-bottom: 2px solid rgba(0, 0, 0, 0.08);
  padding: 4px 0 8px;
  text-transform: uppercase;
  letter-spacing: 0.1px;
  border-radius: 0;
  margin-bottom: 6px;
}

.trend-table-header-row:hover {
  background: transparent;
  transform: none;
}

.trend-table-cell {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  flex-direction: row;
  gap: 4px;
  font-weight: 500;
  font-size: 11px;
  color: #1D1D1F;
  line-height: 1.4;
  white-space: nowrap;
}

.trend-table-header-row .trend-table-cell {
  align-items: center;
  justify-content: flex-start;
  flex-direction: row;
  white-space: nowrap;
  gap: 3px;
  font-size: 7px;
}

.timeframe-cell {
  font-weight: 700;
  font-size: 14px;
  color: #1D1D1F;
  letter-spacing: 0px;
  font-family: var(--font-ui);
}

.strength-text {
  font-size: 10px;
  font-weight: 700;
  padding: 6px 10px;
  border-radius: 8px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  transition: all 0.2s ease;
}

.strength-text::before {
  content: '';
  width: 5px;
  height: 5px;
  border-radius: 50%;
  display: block;
  animation: pulse 2s ease-in-out infinite;
}

.strength-text.low::before {
  background: #FF453A;
  box-shadow: none;
}

.strength-text.medium::before {
  background: #FF9F0A;
  box-shadow: none;
}

.strength-text.high::before {
  background: #30D158;
  box-shadow: none;
}

.strength-text.low {
  color: #FF3B30;
  background: rgba(255, 59, 48, 0.1);
  border: 1px solid rgba(255, 69, 58, 0.2);
  box-shadow: none;
}

.strength-text.medium {
  color: #FF9500;
  background: rgba(255, 149, 0, 0.1);
  border: 1px solid rgba(255, 159, 10, 0.2);
  box-shadow: none;
}

.strength-text.high {
  color: #34C759;
  background: rgba(52, 199, 89, 0.1);
  border: 1px solid rgba(52, 199, 89, 0.2);
  box-shadow: none;
}

.ranging-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  display: block;
  border: 2px solid;
  transition: all 0.2s ease;
  position: relative;
}

.ranging-dot.trending {
  background: #34C759;
  border-color: rgba(52, 199, 89, 0.4);
  box-shadow: none;
}

.ranging-dot.ranging {
  background: #FF3B30;
  border-color: rgba(255, 59, 48, 0.4);
  box-shadow: none;
}

.overall-row {
  background: transparent;
  font-weight: 700;
  border: none;
  border-top: 2px solid rgba(0, 0, 0, 0.08);
  border-bottom: none;
  margin-top: 8px;
  padding-top: 12px;
  box-shadow: none;
  border-radius: 0;
}

.overall-row:hover {
  background: rgba(0, 0, 0, 0.02);
  transform: none;
  box-shadow: none;
}

.overall-badge,
.strength-badge,
.ranging-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  height: 20px;
  padding: 0 6px;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 700;
  margin-right: 4px;
  border: 1px solid;
}

/* Overall Ratio Styling */
.overall-ratio {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  height: 26px;
  padding: 6px 10px;
  border-radius: 8px;
  font-size: 11px;
  font-weight: 700;
  border: 1px solid;
  letter-spacing: 0.2px;
  font-family: var(--font-ui);
  transition: all 0.2s ease;
}

.overall-ratio.bullish,
.overall-ratio.trending,
.overall-ratio.high {
  background: rgba(52, 199, 89, 0.15);
  color: #34C759;
  border-color: rgba(52, 199, 89, 0.3);
  box-shadow: none;
}

.overall-ratio.bearish,
.overall-ratio.ranging,
.overall-ratio.low {
  background: rgba(255, 59, 48, 0.15);
  color: #FF3B30;
  border-color: rgba(255, 59, 48, 0.3);
  box-shadow: none;
}

.overall-ratio.neutral {
  background: rgba(255, 204, 0, 0.15);
  color: #FFCC00;
  border-color: rgba(255, 204, 0, 0.3);
  box-shadow: none;
}

/* Dark Mode for Trend Table/Sparkline Card */
.dark-mode .sparkline-card {
  /* Muss hier stehen bleiben, obwohl .sparkline-card oben schon --bk-elevated traegt:
     die Karte traegt .dark-mode selbst, also greift die blanke .dark-mode-Regel weiter
     unten (background: var(--bk-app)) auf sie - gleiche Spezifitaet, aber spaeter. Ohne
     diese Zeile wird die Karte im Dunkelmodus schwarz. */
  background: var(--bk-elevated);
  border-color: var(--bk-border);
  color: #e5e5e5;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
}

.dark-mode .sparkline-title {
  color: #F7F7F7;
}

.dark-mode .sparkline-column-headers,
.dark-mode .sparkline-row {
  border-color: var(--bk-border);
}

.dark-mode .sparkline-column-header {
  color: rgba(255, 255, 255, 0.6);
}

.dark-mode .sparkline-cell-tf {
  color: rgba(255, 255, 255, 0.85);
}

.dark-mode .footer-stat {
  background: rgba(37, 37, 37, 0.8);
  border-color: var(--bk-border);
}

.dark-mode .footer-label {
  color: rgba(255, 255, 255, 0.5);
}

.dark-mode .footer-value {
  color: #F7F7F7;
}

.dark-mode .sparkline-close-btn {
  color: rgba(255, 255, 255, 0.6);
}

.dark-mode .sparkline-close-btn:hover {
  background: rgba(239, 68, 68, 0.15);
  color: #ef4444;
}

.dark-mode .live-text {
  color: #10b981;
}

.dark-mode .live-dot {
  background: #10b981;
  box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.15);
}

.dark-mode .sparkline-card {
  --sparkline-up: #10b981;
  --sparkline-up-dark: #059669;
  --sparkline-up-bg: rgba(16, 185, 129, 0.15);
  --sparkline-down: #ef4444;
  --sparkline-down-dark: #dc2626;
  --sparkline-down-bg: rgba(239, 68, 68, 0.15);
  --sparkline-med: #f59e0b;
  --sparkline-med-dark: #d97706;
  --sparkline-text: #e5e5e5;
  --sparkline-text-muted: #9ca3af;
  --sparkline-text-faint: #6b7280;
  --sparkline-border: rgba(255, 255, 255, 0.1);
  --sparkline-border-soft: rgba(255, 255, 255, 0.08);
  --sparkline-surface: rgba(37, 37, 37, 0.5);
}

.trend-table-mini .trend-table-row {
  grid-template-columns: 38px 28px 42px 32px;
  gap: 3px;
  padding: 3px 0;
}

.trend-table-mini .trend-table-header-row {
  font-size: 6px;
  padding: 2px 0 4px;
  margin-bottom: 4px;
}

.trend-table-mini .trend-table-cell {
  font-size: 8px;
  gap: 2px;
}

.trend-table-mini .timeframe-cell {
  font-size: 7px;
}

.trend-table-mini .strength-text {
  font-size: 6.5px;
  padding: 1px 4px;
  border-radius: 5px;
}

.trend-table-mini .strength-text::before {
  width: 2.5px;
  height: 2.5px;
}

.trend-table-mini .ranging-dot {
  width: 6px;
  height: 6px;
  border-width: 1.5px;
}

.trend-table-mini .overall-ratio {
  font-size: 7px;
  padding: 1px 4px;
  min-width: 20px;
  height: 12px;
}

.trend-table-mini .trend-table-size-selector {
  padding: 2px;
  gap: 1px;
  border-radius: 5px;
}

.trend-table-mini .trend-table-header-actions {
  gap: 4px;
}

.trend-table-tiny {
  font-size: 9px;
  min-width: 240px;
}

.trend-table-tiny .trend-table-header {
  padding: 8px 12px;
  font-size: 10px;
}

.trend-table-tiny .trend-table {
  padding: 5px;
}

.trend-table-tiny .trend-table-row {
  grid-template-columns: 58px 44px 62px 48px;
  gap: 5px;
  padding: 6px 7px;
}

.trend-table-tiny .trend-table-header-row {
  font-size: 8px;
  padding: 7px 7px;
}

.trend-table-tiny .timeframe-cell {
  font-size: 8.5px;
}

.trend-table-tiny .strength-text {
  font-size: 8px;
  padding: 3px 6px;
  border-radius: 10px;
}

.trend-table-tiny .strength-text::before {
  width: 4.5px;
  height: 4.5px;
}

.trend-table-tiny .ranging-dot {
  width: 10px;
  height: 10px;
  border-width: 2px;
}

.trend-table-tiny .overall-ratio {
  font-size: 8.5px;
  padding: 3px 6px;
  min-width: 28px;
  height: 20px;
}

.trend-table-medium {
  /* Default size - no overrides needed */
}

.trend-table-big {
  font-size: 14px;
  min-width: 380px;
}

.trend-table-big .trend-table-header {
  padding: 14px 18px;
  font-size: 15px;
}

.trend-table-big .trend-table {
  padding: 10px;
}

.trend-table-big .trend-table-row {
  grid-template-columns: 95px 70px 100px 75px;
  gap: 10px;
  padding: 10px 8px;
}

.trend-table-big .trend-table-header-row {
  font-size: 13px;
  padding: 12px 8px;
}

.trend-table-big .timeframe-cell {
  font-size: 13px;
}

.trend-table-big .strength-text {
  font-size: 13px;
  padding: 5px 10px;
}

.trend-table-big .strength-text::before {
  width: 7px;
  height: 7px;
}

.trend-table-big .ranging-dot {
  width: 12px;
  height: 12px;
  border-width: 2.5px;
}

.trend-table-big .overall-ratio {
  font-size: 13px;
  padding: 4px 9px;
}

/* Size Selector */
.trend-table-header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.trend-table-size-selector {
  display: flex;
  align-items: center;
  gap: 2px;
  background: rgba(0, 0, 0, 0.05);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 8px;
  padding: 3px;
}

.dark-mode .trend-table-size-selector {
  background: rgba(255, 255, 255, 0.06);
  border-color: var(--bk-border);
}

@keyframes trendTableSlideIn {
  from {
    opacity: 0;
    transform: translateY(20px) scale(0.96);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

@keyframes pulse {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.6;
  }
}

@keyframes pulseGlow {
  0%, 100% {
    box-shadow: 0 0 10px currentColor, 0 0 0 2px rgba(255, 255, 255, 0.1), inset 0 1px 2px rgba(255, 255, 255, 0.4);
  }
  50% {
    box-shadow: 0 0 16px currentColor, 0 0 0 3px rgba(255, 255, 255, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.4);
  }
}

.dark-mode .symbol-ticker {
  color: #F7F7F7;
}

.dark-mode .symbol-fullname {
  color: var(--bk-text-2);
}

.dark-mode .symbol-type {
  color: var(--bk-text-2);
}

.dark-mode .symbol-source {
  color: var(--bk-text-2);
}

/* Profile Section - Dark Mode */
.dark-mode .profile-section-title {
  color: var(--bk-text-2);
}

.dark-mode .profile-stat {
  background: #000000;
  border: 1px solid #242424;
}

.dark-mode .profile-stat-value {
  color: #F7F7F7;
}

.dark-mode .profile-stat-label {
  color: var(--bk-text-2);
}

/* Chart Settings - Dark Mode */
.dark-mode .chart-settings-section-title {
  color: var(--bk-text-2);
}

.dark-mode .chart-settings-label {
  color: var(--bk-text-2);
}

/* Replay Controls - Dark Mode */
.dark-mode .replay-controls {
  background: #101010;
  border: 1px solid #242424;
}

.dark-mode .replay-btn {
  background: #000000;
  border: 1px solid #242424;
  color: #F7F7F7;
}

/* ========================================
   NEW TREND TABLE STYLES
   ======================================== */
.new-trend-table {
  min-width: 380px;
  max-width: 450px;
  background: rgba(255, 255, 255, 0.98);
  backdrop-filter: blur(40px) saturate(180%);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  border-radius: 12px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), 
              0 2px 8px rgba(0, 0, 0, 0.08);
  border: 1px solid rgba(142, 142, 147, 0.15);
  overflow: hidden;
  z-index: 9999;
  animation: trendTableFadeIn 0.3s ease-out;
}

@keyframes trendTableFadeIn {
  from {
    opacity: 0;
    transform: translateY(-10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.new-trend-table-header {
  background: linear-gradient(135deg, #007AFF 0%, #0051D5 100%);
  color: white;
  padding: 12px 16px;
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 14px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  cursor: grab;
  user-select: none;
}

.new-trend-table-header:active {
  cursor: grabbing;
}

.new-trend-table-body {
  padding: 8px;
  max-height: 500px;
  overflow-y: auto;
}

.new-trend-table table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-ui);
}

.new-trend-table thead th {
  background: rgba(142, 142, 147, 0.08);
  color: #1D1D1F;
  font-weight: 600;
  font-size: 12px;
  text-align: left;
  padding: 10px 12px;
  border-bottom: 1px solid rgba(142, 142, 147, 0.15);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.new-trend-table tbody tr {
  border-bottom: 1px solid rgba(142, 142, 147, 0.1);
  transition: background-color 0.2s ease;
}

.new-trend-table tbody tr:hover {
  background: rgba(0, 122, 255, 0.05);
}

.new-trend-table tbody td {
  padding: 10px 12px;
  font-size: 13px;
  color: #1D1D1F;
}

.new-trend-table tbody tr.overall-row {
  background: rgba(0, 122, 255, 0.08);
  font-weight: 600;
  border-top: 2px solid rgba(0, 122, 255, 0.3);
}

.new-trend-table tbody tr.overall-row:hover {
  background: rgba(0, 122, 255, 0.12);
}

.new-trend-table tbody tr.overall-row td {
  font-weight: 600;
}

/* Dark Mode Styles for New Trend Table */
.dark-mode .new-trend-table {
  background: rgba(28, 28, 30, 0.98);
  border: 1px solid rgba(84, 84, 88, 0.3);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4), 
              0 2px 8px rgba(0, 0, 0, 0.3);
}

.dark-mode .new-trend-table-header {
  background: linear-gradient(135deg, #0A84FF 0%, #0051D5 100%);
}

.dark-mode .new-trend-table thead th {
  background: rgba(84, 84, 88, 0.2);
  color: #F5F5F7;
  border-bottom: 1px solid rgba(84, 84, 88, 0.4);
}

.dark-mode .new-trend-table tbody tr {
  border-bottom: 1px solid rgba(84, 84, 88, 0.3);
}

.dark-mode .new-trend-table tbody tr:hover {
  background: rgba(10, 132, 255, 0.15);
}

.dark-mode .new-trend-table tbody td {
  color: #F5F5F7;
}

.dark-mode .new-trend-table tbody tr.overall-row {
  background: rgba(10, 132, 255, 0.2);
  border-top: 2px solid rgba(10, 132, 255, 0.4);
}

.dark-mode .new-trend-table tbody tr.overall-row:hover {
  background: rgba(10, 132, 255, 0.25);
}

/* Scrollbar Styling */
.new-trend-table-body::-webkit-scrollbar {
  width: 6px;
}

.new-trend-table-body::-webkit-scrollbar-track {
  background: rgba(142, 142, 147, 0.08);
  border-radius: 3px;
}

.new-trend-table-body::-webkit-scrollbar-thumb {
  background: rgba(142, 142, 147, 0.3);
  border-radius: 3px;
}

.new-trend-table-body::-webkit-scrollbar-thumb:hover {
  background: rgba(142, 142, 147, 0.5);
}

.dark-mode .new-trend-table-body::-webkit-scrollbar-track {
  background: rgba(84, 84, 88, 0.2);
}

.dark-mode .new-trend-table-body::-webkit-scrollbar-thumb {
  background: rgba(84, 84, 88, 0.5);
}

.dark-mode .new-trend-table-body::-webkit-scrollbar-thumb:hover {
  background: rgba(84, 84, 88, 0.7);
}

.dark-mode .replay-exit-btn:hover {
  color: #F7F7F7;
  border-color: rgba(255, 255, 255, 0.4);
  background: rgba(255, 255, 255, 0.08);
}

.dark-mode .indicators-btn {
  background: transparent;
  border-color: transparent;
  color: #F7F7F7;
}

.dark-mode .indicators-btn:hover {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.15);
}

/* Matches the modal's inputs/selects in dark mode. Needs the doubled class to outrank
   `.dark-mode .indicators-btn`, which clears the border for the bottom-strip buttons. */
.dark-mode .indicators-btn.indicator-backtest-btn {
  border-color: #242424;
}

.dark-mode .indicators-btn.indicator-backtest-btn:hover {
  border-color: #303030;
}

.dark-mode .indicators-btn svg {
  stroke: #F7F7F7;
}

.dark-mode .indicators-btn::after {
  background: rgba(255, 255, 255, 0.15);
}

.dark-mode .indicators-text {
  color: #F7F7F7;
}

.dark-mode .indicators-count {
  background: var(--bk-active);
  color: var(--bk-text-2);
}

.dark-mode .speed-btn {
  background: #000000;
  border: 1px solid #242424;
  color: #F7F7F7;
}

.dark-mode .speed-btn:hover {
  color: #F7F7F7;
  border-color: rgba(255, 255, 255, 0.4);
  background: rgba(255, 255, 255, 0.08);
}

.dark-mode .speed-selector-btn {
  background: rgba(142, 142, 147, 0.2);
  border: 1px solid rgba(142, 142, 147, 0.4);
  color: #F5F5F7;
}

.dark-mode .speed-selector-btn:hover {
  background: rgba(142, 142, 147, 0.3);
  border-color: rgba(142, 142, 147, 0.5);
  color: #F7F7F7;
}

.dark-mode .balance-input {
  background: rgba(30, 30, 32, 0.9);
  border-color: var(--bk-border);
  color: #F5F5F7;
}

.dark-mode .balance-input:focus {
  border-color: #0A84FF;
  background: rgba(42, 42, 46, 1);
}

.dark-mode .balance-arrow {
  background: rgba(255, 255, 255, 0.08);
  color: var(--bk-text-2);
}

.dark-mode .balance-arrow:hover {
  background: rgba(10, 132, 255, 0.2);
  color: #0A84FF;
}

.dark-mode .balance-arrow:active {
  background: rgba(10, 132, 255, 0.3);
}

/* Alert Badge - Dark Mode */
.dark-mode .alert-badge {
  background: #FF3B30;
  color: #F7F7F7;
}

/* Scrollbars - Dark Mode */
.dark-mode *::-webkit-scrollbar {
  background: rgba(255, 255, 255, 0.05);
}

.dark-mode *::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.2);
}

.dark-mode *::-webkit-scrollbar-thumb:hover {
  background: rgba(255, 255, 255, 0.3);
}

/* Text Colors - Dark Mode */
.dark-mode .profile-name {
  color: #F7F7F7;
}

.dark-mode .profile-email {
  color: var(--bk-text-3);
}

.dark-mode .profile-avatar-section {
  background: transparent;
  border-bottom: 1px solid #242424;
}

.dark-mode .profile-avatar-large {
  border: none;
  box-shadow: none;
}

.dark-mode .profile-section {
  border-bottom: 1px solid #242424;
}

.dark-mode .profile-info-item {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid #242424;
}

.dark-mode .profile-info-label {
  color: var(--bk-text-2);
}

.dark-mode .profile-info-value {
  color: #F7F7F7;
}

.dark-mode .profile-action-btn {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid #242424;
  color: #F7F7F7;
}

.dark-mode .profile-action-btn:hover {
  background: rgba(255, 255, 255, 0.06);
}

.dark-mode .profile-action-btn svg {
  color: var(--bk-text-2);
}

.dark-mode .profile-licence-link {
  color: var(--bk-text-2);
}

.dark-mode .profile-licence-link:hover {
  color: #F7F7F7;
}

.dark-mode .profile-back-btn {
  color: #F7F7F7;
}

.dark-mode .profile-back-btn:hover {
  background: rgba(255, 255, 255, 0.06);
}

.dark-mode .profile-licence-intro,
.dark-mode .profile-licence-line,
.dark-mode .profile-licence-arrow {
  color: var(--bk-text-2);
}

.dark-mode .profile-licence {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid #242424;
}

.dark-mode .profile-licence:hover {
  background: rgba(255, 255, 255, 0.06);
}

.dark-mode .profile-licence-name {
  color: #F7F7F7;
}

.dark-mode .logout-btn {
  color: #FF3B30;
  border: 1px solid rgba(255, 59, 48, 0.3);
}

.dark-mode .logout-btn:hover {
  background: rgba(255, 59, 48, 0.1);
}

/* ======================================== */
/*        CUSTOM COLOR PICKER MODAL        */
/* ======================================== */

.color-picker-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10001;
}

.color-picker-modal {
  /* The custom-colour spectrum is absolute and covers its menu; without this it would
     measure itself against the full-screen overlay instead. */
  position: relative;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(40px);
  -webkit-backdrop-filter: blur(40px);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 10px;
  padding: 14px;
  width: 322px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
}

.color-picker-modal.dark-mode {
  background: #101010;
  border: 1px solid #242424;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.8);
}

.color-picker-grid {
  display: grid;
  grid-template-columns: repeat(10, 1fr);
  gap: 6px;
  margin-bottom: 14px;
  margin-left: -14px;
  margin-right: -14px;
  padding-left: 14px;
  padding-right: 14px;
}

.color-swatch {
  width: 24px;
  height: 24px;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.12s ease;
  border: none;
  position: relative;
}

.color-swatch::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 8px;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15);
  pointer-events: none;
}

.color-swatch:hover {
  ;
  z-index: 1;
}

/* The saved-colour row carries the settings menus' classes so it inherits their remove
   button and arming, but their swatch is 20px against this modal's 24px. Only the sizes are
   restated here; the behaviour is the shared one. */
.color-picker-modal .custom-colors-row {
  align-items: center;
  margin-top: 0;
  margin-bottom: 14px;
  padding-top: 12px;
  border-top: 1px solid rgba(0, 0, 0, 0.1);
}

.color-picker-modal.dark-mode .custom-colors-row {
  border-top-color: #242424;
}

.color-picker-modal .custom-colors-row .color-swatch {
  display: block;
}

/* .color-swatch lifts itself a layer on hover, and the pointer is always over the swatch it
   is about to click - without this the colour would sit above the remove button covering it
   and swallow the click that was meant to remove it. */
.color-picker-modal .custom-colors-row .custom-color-delete {
  z-index: 2;
}

.color-picker-modal .color-picker-add-btn {
  width: 24px;
  height: 24px;
  font-size: 19px;
  border-radius: 8px;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15);
}

/* Its colour and hover already come from the app's dark rule for this button; only the
   outline that matches this modal's swatches needs restating. */
.color-picker-modal.dark-mode .color-picker-add-btn {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.16);
}

.color-picker-opacity {
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  padding-top: 14px;
}

.opacity-label {
  color: #999;
  font-size: 12px;
  margin-bottom: 10px;
  font-family: var(--font-ui);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.color-picker-modal.dark-mode .opacity-label {
  color: #999;
}

.opacity-controls {
  display: flex;
  align-items: center;
  gap: 12px;
}

.opacity-slider {
  flex: 1;
  height: 6px;
  border-radius: 3px;
  outline: none;
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
}

.opacity-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: white;
  cursor: pointer;
  border: 2px solid rgba(0, 0, 0, 0.2);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

.opacity-slider::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: white;
  cursor: pointer;
  border: 2px solid rgba(0, 0, 0, 0.2);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

.color-picker-modal.dark-mode .opacity-slider::-webkit-slider-thumb {
  border: 2px solid var(--bk-border);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}

.color-picker-modal.dark-mode .opacity-slider::-moz-range-thumb {
  border: 2px solid var(--bk-border);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}

.opacity-value {
  color: #000;
  font-size: 13px;
  font-family: var(--font-ui);
  font-weight: 500;
  min-width: 42px;
  text-align: right;
  background: rgba(0, 0, 0, 0.05);
  padding: 4px 10px;
  border-radius: 6px;
}

.color-picker-modal.dark-mode .opacity-value {
  color: #F7F7F7;
  background: rgba(255, 255, 255, 0.08);
}

.color-picker-buttons {
  display: flex;
  gap: 10px;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.color-picker-cancel,
.color-picker-apply {
  flex: 1;
  padding: 10px;
  border-radius: 8px;
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s ease;
  border: none;
  outline: none;
}

.color-picker-cancel {
  background: rgba(0, 0, 0, 0.05);
  color: #000;
}

.color-picker-cancel:hover {
  background: rgba(0, 0, 0, 0.08);
}

.color-picker-modal.dark-mode .color-picker-cancel {
  background: rgba(255, 255, 255, 0.08);
  color: #F7F7F7;
}

.color-picker-modal.dark-mode .color-picker-cancel:hover {
  background: rgba(255, 255, 255, 0.12);
}

.color-picker-apply {
  background: #4CD964;
  color: #000;
}

.color-picker-apply:hover {
  background: #5EE374;
}

/* Chart Settings Modal - Dark Mode */
/* Speed Dropdown - Dark Mode */
.dark-mode .speed-dropdown-menu {
  background: #101010;
  border: 1px solid #242424;
}

.dark-mode .speed-dropdown-item {
  color: #fafafa;
}

.dark-mode .speed-dropdown-item:hover {
  background: rgba(255, 255, 255, 0.1);
  color: #F7F7F7;
}

.dark-mode .speed-dropdown-item.active {
  background: rgba(255, 255, 255, 0.15);
  color: #F7F7F7;
}

.dark-mode .speed-option {
  background: transparent;
  color: #F7F7F7;
}

.dark-mode .speed-option:hover {
  background: rgba(255, 255, 255, 0.1);
}

.dark-mode .speed-option.active {
  background: rgba(255, 255, 255, 0.15);
}

/* Logo Styling - Dark Mode */
/* Crypto logos are colored and should not be inverted */

/* Backtest Results - Dark Mode */
.dark-mode .backtest-card {
  background: rgba(26, 26, 26, 0.95);
  border: 1px solid #242424;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
}

.dark-mode .backtest-title {
  color: var(--bk-text-2);
}

.dark-mode .stat-row.highlight {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid #242424;
}

.dark-mode .stat-label {
  color: var(--bk-text-2);
}

.dark-mode .stat-value,
.dark-mode .stat-value-large {
  color: #F7F7F7;
}

.dark-mode .apply-best-btn {
  background: rgba(255, 255, 255, 0.05);
  color: var(--bk-text-2);
  border: 1px solid #242424;
}

.dark-mode .apply-best-btn:hover {
  background: rgba(255, 255, 255, 0.08);
  border-color: #303030;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
}

/* ========================================
   TREND TABLE
   ======================================== */
/* ========================================
   SPARKLINE CARD (Trend Analysis Widget)
   ======================================== */

:root {
  --sparkline-up: #1fa463;
  --sparkline-up-dark: #128a4f;
  --sparkline-up-bg: #e8f6ee;
  --sparkline-down: #e34b4b;
  --sparkline-down-dark: #c23232;
  --sparkline-down-bg: #fdecec;
  --sparkline-med: #d99b1f;
  --sparkline-med-dark: #b5800a;
  --sparkline-text: #0f172a;
  --sparkline-text-muted: #6b7280;
  --sparkline-text-faint: #9aa3b2;
  --sparkline-border: #e8eaf0;
  --sparkline-border-soft: #eef0f4;
  --sparkline-surface: #fafbfc;
}

.sparkline-card {
  position: absolute;
  top: 100px;
  right: 10px;
  width: fit-content;
  /* Same surface as the backtest dashboard - see the note on .trade-checker-btn. */
  background: var(--bk-elevated);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-radius: 16px;
  border: 1px solid var(--sparkline-border);
  box-shadow: 0 6px 20px rgba(15, 23, 42, 0.05);
  padding: 22px 20px 20px;
  z-index: 50;
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  color: var(--sparkline-text);
  cursor: move;
  user-select: none;
}

/* Header */
.sparkline-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
  position: relative;
}

.sparkline-title {
  font-size: 15px;
  font-weight: 700;
  margin: 0;
  color: var(--sparkline-text);
  pointer-events: none;
}

.sparkline-live-indicator {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
  margin-right: 8px;
}

.live-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--sparkline-up);
  box-shadow: 0 0 0 3px #e8f6ee;
}

.live-text {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 600;
  color: var(--sparkline-up-dark);
}

.sparkline-close-btn {
  width: 28px;
  height: 28px;
  border: none;
  background: transparent;
  color: var(--sparkline-text-muted);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  transition: all 0.2s ease;
  padding: 0;
  flex-shrink: 0;
}

.sparkline-close-btn:hover {
  background: var(--sparkline-down-bg);
  color: var(--sparkline-down);
}

/* Column Headers */
.sparkline-column-headers {
  display: grid;
  grid-template-columns: 45px 85px 95px 55px;
  gap: 10px;
  padding: 12px 0 10px;
  border-bottom: 1px solid var(--sparkline-border-soft);
  margin-bottom: 4px;
}

.sparkline-column-headers > div {
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--sparkline-text-faint);
}

.sparkline-column-headers > div:last-child {
  text-align: center;
}

/* Data Rows */
.sparkline-rows {
  display: flex;
  flex-direction: column;
}

.sparkline-row {
  display: grid;
  grid-template-columns: 45px 85px 95px 55px;
  gap: 10px;
  padding: 12px 0;
  border-bottom: 1px solid var(--sparkline-border-soft);
  align-items: center;
}

.sparkline-row:last-child {
  border-bottom: none;
}

/* TF Cell */
.sparkline-cell-tf {
  font-family: 'JetBrains Mono', monospace;
  font-size: 13px;
  font-weight: 600;
  color: var(--sparkline-text);
}

/* Trend Pill */
.sparkline-cell-trend {
  display: flex;
  align-items: center;
}

.trend-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  border-radius: 8px;
  font-size: 11px;
  font-weight: 600;
}

.trend-pill.up {
  background: var(--sparkline-up-bg);
  color: var(--sparkline-up-dark);
}

.trend-pill.down {
  background: var(--sparkline-down-bg);
  color: var(--sparkline-down-dark);
}

.trend-pill svg {
  flex-shrink: 0;
}

/* Signal Sparkline */
.sparkline-cell-signal {
  display: flex;
  align-items: center;
  justify-content: flex-start;
}

/* Strength Meter */
.sparkline-cell-strength {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 10px;
}

.strength-bar-container {
  width: 45px;
  height: 5px;
  background: var(--sparkline-border-soft);
  border-radius: 3px;
  overflow: hidden;
}

.strength-bar-fill {
  height: 100%;
  border-radius: 3px;
  transition: width 0.3s ease;
}

.strength-bar-fill.high {
  width: 95%;
  background: var(--sparkline-up);
}

.strength-bar-fill.medium {
  width: 60%;
  background: var(--sparkline-med);
}

.strength-bar-fill.low {
  width: 30%;
  background: var(--sparkline-down);
}

.strength-label {
  font-size: 10px;
  color: var(--sparkline-text-muted);
  text-transform: capitalize;
  white-space: nowrap;
}

/* Range Dot */
.sparkline-cell-range {
  display: flex;
  justify-content: center;
  align-items: center;
}

.range-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
}

.range-dot.ranging {
  background: var(--sparkline-down);
}

.range-dot.trending {
  background: var(--sparkline-up);
}

/* Footer Summary */
.sparkline-footer {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  margin-top: 14px;
}

.footer-stat {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px 12px;
  background: var(--sparkline-surface);
  border: 1px solid var(--sparkline-border-soft);
  border-radius: 10px;
}

.footer-label {
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--sparkline-text-faint);
}

.footer-value {
  font-family: 'JetBrains Mono', monospace;
  font-size: 15px;
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: 4px;
}

.value-up,
.value-trending {
  color: var(--sparkline-up);
}

.value-down,
.value-ranging {
  color: var(--sparkline-down);
}

.value-high {
  color: var(--sparkline-up);
}

.value-med {
  color: var(--sparkline-med);
}

.value-low {
  color: var(--sparkline-down);
}

.value-sep {
  color: var(--sparkline-text-faint);
  font-weight: 400;
}

/* Small Version Styles */
.sparkline-card-small {
  padding: 14px 16px 12px;
  font-size: 11px;
}

.sparkline-card-small .sparkline-title {
  font-size: 13px;
}

.sparkline-card-small .sparkline-column-headers {
  grid-template-columns: 35px 70px 75px 45px;
  gap: 8px;
  padding: 8px 0 6px;
  font-size: 9px;
}

.sparkline-card-small .sparkline-row {
  grid-template-columns: 35px 70px 75px 45px;
  gap: 8px;
  padding: 8px 0;
}

.sparkline-card-small .sparkline-cell-tf {
  font-size: 11px;
}

.sparkline-card-small .trend-pill {
  padding: 2px 7px;
  font-size: 10px;
}

.sparkline-card-small .trend-pill svg {
  width: 9px;
  height: 9px;
}

.sparkline-card-small .strength-bar-container {
  width: 35px;
  height: 4px;
}

.sparkline-card-small .strength-label {
  font-size: 9px;
}

.sparkline-card-small .range-dot {
  width: 6px;
  height: 6px;
}

.sparkline-card-small .sparkline-footer {
  gap: 8px;
  margin-top: 10px;
}

.sparkline-card-small .footer-stat {
  padding: 8px 10px;
  gap: 3px;
}

.sparkline-card-small .footer-label {
  font-size: 8px;
}

.sparkline-card-small .footer-value {
  font-size: 12px;
}

.sparkline-card-small .sparkline-live-indicator {
  font-size: 9px;
}

.sparkline-card-small .live-dot {
  width: 5px;
  height: 5px;
}

/* Tiny Version Styles - one step down again from small */
.sparkline-card-tiny {
  padding: 10px 12px 9px;
  font-size: 10px;
  border-radius: 12px;
}

.sparkline-card-tiny .sparkline-header {
  margin-bottom: 8px;
}

.sparkline-card-tiny .sparkline-title {
  font-size: 11px;
}

.sparkline-card-tiny .sparkline-live-indicator {
  font-size: 8px;
  gap: 4px;
  margin-right: 5px;
}

.sparkline-card-tiny .live-dot {
  width: 4px;
  height: 4px;
  box-shadow: 0 0 0 2px #e8f6ee;
}

/* Needed because the rule above matches .dark-mode .live-dot's specificity but comes
   later in the file, so without this the tiny dot keeps the light-theme halo in dark
   mode. Same halo colour as dark mode's, just scaled to the smaller dot. */
.dark-mode .sparkline-card-tiny .live-dot {
  box-shadow: 0 0 0 2px rgba(16, 185, 129, 0.15);
}

.sparkline-card-tiny .live-text {
  font-size: 8px;
}

.sparkline-card-tiny .sparkline-close-btn {
  width: 28px;
  height: 28px;
  font-size: 20px;
  border-radius: 8px;
}

.sparkline-card-tiny .sparkline-column-headers {
  grid-template-columns: 28px 54px 60px 34px;
  gap: 6px;
  padding: 6px 0 4px;
}

.sparkline-card-tiny .sparkline-column-headers > div {
  font-size: 8px;
  letter-spacing: 0.08em;
}

.sparkline-card-tiny .sparkline-row {
  grid-template-columns: 28px 54px 60px 34px;
  gap: 6px;
  padding: 5px 0;
}

.sparkline-card-tiny .sparkline-cell-tf {
  font-size: 10px;
}

.sparkline-card-tiny .trend-pill {
  padding: 1px 5px;
  font-size: 9px;
  gap: 3px;
  border-radius: 8px;
}

/* Overrides the width/height attributes on the inline <svg> arrow */
.sparkline-card-tiny .trend-pill svg {
  width: 8px;
  height: 8px;
}

.sparkline-card-tiny .sparkline-cell-strength {
  gap: 4px;
}

.sparkline-card-tiny .strength-bar-container {
  width: 26px;
  height: 3px;
}

.sparkline-card-tiny .strength-label {
  font-size: 8px;
}

.sparkline-card-tiny .range-dot {
  width: 5px;
  height: 5px;
}

.sparkline-card-tiny .sparkline-footer {
  gap: 6px;
  margin-top: 8px;
}

.sparkline-card-tiny .footer-stat {
  padding: 5px 7px;
  gap: 2px;
  border-radius: 7px;
}

.sparkline-card-tiny .footer-label {
  font-size: 7px;
  letter-spacing: 0.06em;
}

.sparkline-card-tiny .footer-value {
  font-size: 11px;
  gap: 3px;
}

/* ========================================
   REPLAY PANEL (Draggable)
   ======================================== */
.replay-panel {
  position: absolute;
  background: rgba(255, 255, 255, 0.98);
  backdrop-filter: blur(40px);
  -webkit-backdrop-filter: blur(40px);
  border: 1px solid rgba(142, 142, 147, 0.12);
  border-radius: 12px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.12), 0 4px 16px rgba(0, 0, 0, 0.06);
  padding: 10px 16px;
  min-width: 420px;
  z-index: 1000;
  user-select: none;
}

.replay-panel-drag-handle {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2px 0 8px 0;
  cursor: move;
  color: #8E8E93;
  opacity: 0.5;
  transition: opacity 0.2s ease;
}

.replay-panel-drag-handle:hover {
  opacity: 0.8;
}

/* Minimal Playback Controls */
.pb-controls {
  position: fixed;
  left: 50%;
  bottom: 35px;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  gap: 2px;
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  z-index: 1000;
  user-select: none;
  padding: 6px 8px;
  border: 1px solid rgba(0, 0, 0, 0.12);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.pb-btn {
  height: 28px;
  width: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  border-radius: 8px;
  color: var(--bk-text-3);
  cursor: pointer;
  padding: 0;
  font-size: 11px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  transition: background 120ms, color 120ms;
}

.pb-btn--wide {
  width: auto;
  padding: 0 10px;
}

.pb-btn:hover:not(:disabled) {
  background: rgba(0, 0, 0, 0.06);
  color: #18181b;
}

.pb-btn:focus-visible {
  outline: 2px solid #a1a1aa;
  outline-offset: 2px;
}

.pb-btn:active:not(:disabled) {
  background: rgba(0, 0, 0, 0.1);
}

.pb-btn:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

/* Held down while the candle picker is waiting for a click. Without it the toolbar looks
   untouched while the chart is in a mode it will not leave until something is clicked or
   Escape is pressed, and the only other sign of that mode is the dimming veil. */
.pb-btn--active,
.pb-btn--active:hover:not(:disabled) {
  background: rgba(59, 130, 246, 0.16);
  color: #2563eb;
}

.pb-controls.dark-mode .pb-btn--active,
.pb-controls.dark-mode .pb-btn--active:hover:not(:disabled) {
  background: rgba(96, 165, 250, 0.22);
  color: #93c5fd;
}

.pb-btn--danger:hover:not(:disabled) {
  background: rgba(248, 113, 113, 0.12);
  color: #dc2626;
}

.pb-btn--danger:active:not(:disabled) {
  background: rgba(248, 113, 113, 0.18);
  color: #dc2626;
}

.pb-btn svg {
  display: block;
}

.pb-divider {
  display: inline-block;
  width: 1px;
  height: 16px;
  background: rgba(0, 0, 0, 0.1);
  margin: 0 6px;
}

.replay-speed-compact {
  position: relative;
  display: inline-flex;
}

/* Playback Controls - Dark Mode */
.pb-controls.dark-mode {
  border-color: #27272a;
  background: rgba(0, 0, 0, 0.4);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

.pb-controls.dark-mode .pb-btn {
  color: #fafafa;
}

.pb-controls.dark-mode .pb-btn:hover:not(:disabled) {
  background: #1f1f22;
  color: #F7F7F7;
}

.pb-controls.dark-mode .pb-btn:active:not(:disabled) {
  background: #18181b;
  color: #F7F7F7;
}

.pb-controls.dark-mode .pb-btn:focus-visible {
  outline-color: #3f3f46;
}

.pb-controls.dark-mode .pb-btn--danger:hover:not(:disabled) {
  background: rgba(248, 113, 113, 0.12);
  color: #f87171;
}

.pb-controls.dark-mode .pb-btn--danger:active:not(:disabled) {
  background: rgba(248, 113, 113, 0.18);
  color: #f87171;
}

.pb-controls.dark-mode .pb-divider {
  background: #27272a;
}

/* Trade Buttons Panel - Bottom Left */
.trade-buttons-panel {
  position: absolute;
  top: 44px;
  left: 12px;
  display: flex;
  gap: 6px;
  z-index: 60;
  padding: 0;
  background: transparent;
  backdrop-filter: none;
  border: none;
  border-radius: 8px;
  box-shadow: none;
}

.trade-buttons-panel.dark-mode {
  background: transparent;
  border: none;
  box-shadow: none;
}

.trade-buttons-panel .order-btn {
  min-width: 50px;
  margin: 0;
  padding: 4px 10px;
  font-size: 10px;
  border-radius: 8px;
}

/* Quantity Selector */
.quantity-selector {
  position: relative;
  display: flex;
  align-items: center;
}

.quantity-btn {
  display: flex;
  align-items: center;
  gap: 4px;
  min-width: 50px;
  height: 28px;
  padding: 0 8px;
  background: rgba(142, 142, 147, 0.12);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 8px;
  color: #1D1D1F;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s ease;
}

.quantity-btn:hover {
  background: rgba(142, 142, 147, 0.18);
  border-color: rgba(0, 0, 0, 0.12);
}

.dark-mode .quantity-btn {
  background: rgba(255, 255, 255, 0.08);
  border-color: var(--bk-border);
  color: #F5F5F7;
}

.dark-mode .quantity-btn:hover {
  background: rgba(255, 255, 255, 0.12);
  border-color: rgba(255, 255, 255, 0.18);
}

.quantity-menu {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px;
  min-width: 80px;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 6px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
  z-index: 1001;
  /* Eighteen fixed sizes come to 772px of options, hung from a button roughly 140px down
     the chart. That fits a tall desktop window and nothing else: at 812px it ran 168px
     past the bottom edge, so the selected $10K sat half off the screen and everything
     below it was unreachable - the menu had no scroll of its own to get there. Capping
     against the viewport turns the overflow into a scroll. The cap only engages when the
     list would actually overrun, so a window tall enough to show all eighteen is
     unchanged. dvh repeats the value for mobile browsers, where the visible height
     shrinks as the address bar returns and vh would keep promising the taller figure. */
  max-height: calc(100vh - 160px);
  max-height: calc(100dvh - 160px);
  overflow-y: auto;
  /* Without this, flicking past the end of the list scrolls the chart behind it. */
  overscroll-behavior: contain;
}

.quantity-menu.dark-mode {
  background: rgba(39, 39, 42, 0.95);
  border-color: var(--bk-border);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
}

.quantity-option {
  padding: 6px 10px;
  background: transparent;
  border: none;
  border-radius: 8px;
  color: #1D1D1F;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.15s ease;
  text-align: left;
}

.quantity-option:hover {
  background: rgba(142, 142, 147, 0.12);
}

.quantity-option.active {
  background: rgba(59, 130, 246, 0.15);
  color: #007AFF;
}

.dark-mode .quantity-option {
  color: #F5F5F7;
}

.dark-mode .quantity-option:hover {
  background: rgba(255, 255, 255, 0.08);
}

.dark-mode .quantity-option.active {
  background: rgba(59, 130, 246, 0.2);
  color: var(--bk-text);
}

.quantity-option.custom-option {
  border-top: 1px solid rgba(0, 0, 0, 0.08);
  margin-top: 4px;
  padding-top: 10px;
  font-style: italic;
}

.dark-mode .quantity-option.custom-option {
  border-top-color: var(--bk-border);
}

/* Custom Amount Input */
.custom-input-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.3);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2000;
  animation: fadeIn 0.15s ease;
}

.custom-input-box {
  background: #ffffff;
  border: 1px solid #e5e5e5;
  border-radius: 16px;
  padding: 24px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 320px;
  animation: slideUp 0.2s ease;
}

@keyframes slideUp {
  from {
    transform: translateY(20px);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

.custom-input-overlay.dark-mode .custom-input-box {
  background: #101010;
  border-color: #303030;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
}

.custom-amount-input {
  padding: 14px 16px;
  border: 2px solid #e5e5e5;
  border-radius: 10px;
  background: #f9f9f9;
  color: #1D1D1F;
  font-family: var(--font-mono);
  font-size: 16px;
  font-weight: 600;
  outline: none;
  transition: all 0.2s ease;
  text-align: center;
}

/* Remove number input arrows */
.custom-amount-input::-webkit-outer-spin-button,
.custom-amount-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.custom-amount-input[type=number] {
  -moz-appearance: textfield;
}

.custom-amount-input:focus {
  border-color: #007AFF;
  background: #ffffff;
  box-shadow: 0 0 0 4px rgba(0, 122, 255, 0.12);
}

.custom-input-overlay.dark-mode .custom-amount-input {
  background: #202020;
  border-color: #303030;
  color: #F5F5F7;
}

.custom-input-overlay.dark-mode .custom-amount-input:focus {
  border-color: #007AFF;
  background: #101010;
  box-shadow: 0 0 0 4px rgba(0, 122, 255, 0.2);
}

.custom-input-buttons {
  display: flex;
  gap: 10px;
}

.custom-btn {
  flex: 1;
  padding: 12px 16px;
  border: none;
  border-radius: 10px;
  font-family: var(--font-ui);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s ease;
  display: flex;
  align-items: center;
  justify-content: center;
}

.custom-btn.confirm {
  background: #007AFF;
  color: white;
  box-shadow: 0 2px 8px rgba(0, 122, 255, 0.3);
}

.custom-btn.confirm:hover {
  background: #0051D5;
  ;
  box-shadow: 0 4px 12px rgba(0, 122, 255, 0.4);
}

.custom-btn.confirm:active {
  transform: translateY(0);
}

.custom-btn.cancel {
  background: #f0f0f0;
  color: var(--bk-text-3);
}

.custom-btn.cancel:hover {
  background: #e5e5e5;
  color: #52525b;
}

.custom-input-overlay.dark-mode .custom-btn.cancel {
  background: #202020;
  color: var(--bk-text-3);
}

.custom-input-overlay.dark-mode .custom-btn.cancel:hover {
  background: #3a3a3c;
  color: #d4d4d8;
}

/* Pending Order Overlay */
.pending-order-overlay {
  position: absolute;
  right: 250px;
  z-index: 1000;
  pointer-events: all;
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}

.pending-order-overlay.dark-mode {
  background: transparent !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  box-shadow: none !important;
}

.pending-order-controls {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 0;
  background: transparent;
  backdrop-filter: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  font-family: var(--font-ui);
}

.pending-order-overlay.dark-mode .pending-order-controls {
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}

.po-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  height: 28px;
  padding: 0 10px;
  font-size: 11px;
  font-weight: 600;
  font-family: var(--font-ui);
  border: 1.5px dashed rgba(113, 113, 122, 0.4);
  border-radius: 8px;
  background: #fff;
  color: #a1a1aa;
  cursor: pointer;
  transition: all 0.15s ease;
  user-select: none;
}

.po-btn-pnl {
  font-size: 10px;
  font-weight: 700;
  opacity: 0.9;
  font-variant-numeric: tabular-nums;
}

.pending-order-overlay.dark-mode .po-btn {
  background: #000;
  border-color: rgba(113, 113, 122, 0.4);
  color: var(--bk-text-3);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}

.po-btn:hover {
  background: #fff;
  color: #e4e4e7;
  border-color: rgba(161, 161, 170, 0.6);
}

.pending-order-overlay.dark-mode .po-btn:hover {
  background: #000;
  color: #e4e4e7;
  border-color: rgba(161, 161, 170, 0.6);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}

.po-btn.tp-btn {
  border-color: rgba(20, 184, 166, 0.4);
  color: #14b8a6;
}

.po-btn.tp-btn:hover {
  border-color: #14b8a6;
  background: #fff;
}

.po-btn.tp-btn.active {
  background: #fff;
  color: #14b8a6;
  border: 1.5px solid #14b8a6;
  border-style: solid;
}

.po-btn.sl-btn {
  border-color: rgba(245, 158, 11, 0.4);
  color: #f59e0b;
}

.po-btn.sl-btn:hover {
  border-color: #f59e0b;
  background: #fff;
}

.po-btn.sl-btn.active {
  background: #fff;
  color: #f59e0b;
  border: 1.5px solid #f59e0b;
  border-style: solid;
}

.pending-order-overlay.dark-mode .po-btn.tp-btn {
  border-color: rgba(20, 184, 166, 0.4);
  color: #14b8a6;
}

.pending-order-overlay.dark-mode .po-btn.tp-btn:hover {
  border-color: #14b8a6;
  background: #000;
}

.pending-order-overlay.dark-mode .po-btn.tp-btn.active {
  background: #000;
  color: #14b8a6;
  border: 1.5px solid #14b8a6;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}

.pending-order-overlay.dark-mode .po-btn.sl-btn {
  border-color: rgba(245, 158, 11, 0.4);
  color: #f59e0b;
}

.pending-order-overlay.dark-mode .po-btn.sl-btn:hover {
  border-color: #f59e0b;
  background: #000;
}

.pending-order-overlay.dark-mode .po-btn.sl-btn.active {
  background: #000;
  color: #f59e0b;
  border: 1.5px solid #f59e0b;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}

.po-btn.po-confirm {
  background: #007AFF;
  color: white;
  border: 1.5px solid #007AFF;
  border-style: solid;
  font-size: 11px;
  font-weight: 600;
  height: 28px;
  padding: 0 12px;
}

.po-btn.po-confirm:hover {
  background: #0051D5;
  border-color: #0051D5;
  color: white;
}

.pending-order-overlay.dark-mode .po-btn.po-confirm {
  background: #007AFF;
  color: white;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}

.pending-order-overlay.dark-mode .po-btn.po-confirm:hover {
  background: #0051D5;
  color: white;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}

.po-btn.po-close {
  background: transparent;
  color: var(--bk-text-3);
  border: none;
  font-size: 16px;
  height: 28px;
  padding: 0 6px;
  min-width: auto;
}

.po-pnl .po-btn.po-close {
  padding: 0;
  padding-left: 8px;
  margin-left: 8px;
  width: 18px;
  height: 18px;
  color: inherit;
  border-left: 1px solid currentColor;
  border-radius: 0;
}

.pending-order-overlay.dark-mode .po-btn.po-close {
  color: var(--bk-text-3);
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.po-btn.po-close:hover {
  background: transparent;
  color: #EF4444;
  ;
}

.pending-order-overlay.dark-mode .po-btn.po-close:hover {
  background: transparent;
  color: #EF4444;
  ;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.po-balance {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 28px;
  padding: 0 10px;
  font-size: 11px;
  font-weight: 600;
  color: #a1a1aa;
  background: transparent;
  border-radius: 4px;
  font-variant-numeric: tabular-nums;
}

.pending-order-overlay.dark-mode .po-balance {
  color: var(--bk-text-3);
  background: transparent;
}

.po-pnl {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 28px;
  padding: 6px 12px;
  font-size: 11px;
  font-weight: 600;
  border-radius: 4px;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  gap: 4px;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: 1px solid;
  box-shadow: none;
}

.po-pnl.profit {
  color: var(--bk-pos);
  background: #fff;
  border-color: var(--bk-pos);
}

.po-pnl.loss {
  color: var(--bk-neg);
  background: #fff;
  border-color: var(--bk-neg);
}

.pending-order-overlay.dark-mode .po-pnl {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  box-shadow: none !important;
}

.pending-order-overlay.dark-mode .po-pnl.profit {
  background: #000 !important;
  border: 1px solid #22C55E;
  color: var(--bk-pos);
  box-shadow: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}

.pending-order-overlay.dark-mode .po-pnl.loss {
  background: #000 !important;
  border: 1px solid #EF4444;
  color: var(--bk-neg);
  box-shadow: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}

.po-pnl-percent {
  font-size: 11px;
  font-weight: 600;
  opacity: 1;
}

.po-size-input {
  display: flex;
  align-items: center;
  gap: 0;
  height: 28px;
  padding: 0;
  background: transparent;
  border-radius: 4px;
}

.pending-order-overlay.dark-mode .po-size-input {
  background: transparent;
}

.po-size-input input {
  width: 30px;
  height: 28px;
  padding: 0 8px;
  font-size: 11px;
  font-weight: 600;
  font-family: var(--font-ui);
  font-variant-numeric: tabular-nums;
  border: 1.5px solid rgba(113, 113, 122, 0.4);
  border-radius: 4px;
  background: transparent;
  color: #e4e4e7;
  outline: none;
  transition: all 0.15s ease;
  text-align: center;
}

.pending-order-overlay.dark-mode .po-size-input input {
  background: transparent;
  color: #e4e4e7;
  border-color: rgba(113, 113, 122, 0.4);
}

.po-size-input input:focus {
  border-color: #0A84FF;
  border-style: solid;
}

.po-size-input input:hover {
  border-color: rgba(161, 161, 170, 0.6);
}

.po-size-label {
  font-size: 11px;
  font-weight: 600;
  color: #a1a1aa;
  white-space: nowrap;
  margin-left: 2px;
}

.pending-order-overlay.dark-mode .po-size-label {
  color: var(--bk-text-3);
}

/* ========================================
   TP/SL FLOATING BOXES
   ======================================== */
.tp-sl-box {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border-radius: 4px;
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  cursor: ns-resize;
  user-select: none;
  pointer-events: all;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  /* Colours only, never top. These badges ride their TP and SL lines, and top is written
     fresh on every chart frame - under `all` the browser eased each of those writes over
     150ms, so the badge was always chasing a line that had already moved on and wobbled
     the whole way. Nothing here animates position; the hover is a border-colour change. */
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
  position: relative;
}

.tp-box {
  background: #fff;
  border: 1.5px solid #14b8a6;
  color: #14b8a6;
}

.tp-box:hover {
  background: #fff;
  border-color: #0d9488;
}

.sl-box {
  background: #fff;
  border: 1.5px solid #f59e0b;
  color: #f59e0b;
}

.sl-box:hover {
  background: #fff;
  border-color: #d97706;
}

.tp-sl-label {
  font-weight: 700;
  letter-spacing: 0.5px;
}

.tp-sl-value {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* What the level is worth, next to what it costs. The number was already being worked out
   for both boxes and then dropped on the floor - only the price ever reached the screen.
   Coloured by its own sign rather than by which box it is in, because dragging a TP through
   the entry turns it into a loss and the badge should say so. */
.tp-sl-pnl {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  padding-left: 8px;
  border-left: 1px solid currentColor;
}

.tp-sl-pnl.profit {
  color: var(--bk-pos);
}

.tp-sl-pnl.loss {
  color: var(--bk-neg);
}

.tp-sl-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  padding: 0;
  padding-left: 8px;
  margin-left: 8px;
  background: transparent;
  border: none;
  border-left: 1px solid currentColor;
  border-radius: 0;
  color: inherit;
  font-size: 16px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  transition: all 0.15s ease;
  flex-shrink: 0;
}

.tp-sl-close:hover {
  background: transparent;
  ;
  color: #EF4444;
}

.tp-sl-close:active {
  ;
}

/* Dark Mode TP/SL Boxes */
.dark-mode .tp-box {
  background: #000;
  border: 1.5px solid #14b8a6;
  color: #14b8a6;
}

.dark-mode .tp-box:hover {
  background: #000;
  border-color: #0d9488;
}

.dark-mode .sl-box {
  background: #000;
  border: 1.5px solid #f59e0b;
  color: #f59e0b;
}

.dark-mode .sl-box:hover {
  background: #000;
  border-color: #d97706;
}

/* Trading Info Row */
.replay-panel-trading-info {
  display: flex;
  gap: 12px;
  padding: 8px 12px;
  background: rgba(0, 0, 0, 0.02);
  border-radius: 8px;
  margin-bottom: 8px;
}

.trading-info-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.trading-info-label {
  font-family: var(--font-ui);
  font-size: 9px;
  font-weight: 500;
  color: #8E8E93;
  text-transform: uppercase;
  letter-spacing: 0.3px;
}

.trading-info-value {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  color: #1D1D1F;
}

.trading-info-value.profit {
  color: var(--bk-pos);
}

.trading-info-value.loss {
  color: var(--bk-neg);
}

/* SL/TP Controls */
.sl-tp-controls {
  display: flex;
  gap: 8px;
  padding: 8px 12px;
  background: rgba(0, 0, 0, 0.02);
  border-radius: 8px;
  margin-bottom: 8px;
}

.sl-tp-item {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 6px;
}

.sl-tp-label {
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 600;
  color: #8E8E93;
  white-space: nowrap;
}

.sl-tp-input {
  flex: 1;
  padding: 6px 8px;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: #1D1D1F;
  outline: none;
  transition: all 0.15s ease;
}

.sl-tp-input:focus {
  background: white;
  border-color: #007AFF;
}

/* Order Buttons */
.replay-panel-order-buttons {
  display: flex;
  gap: 8px;
  margin-bottom: 8px;
}

.order-btn {
  flex: 1;
  padding: 8px 16px;
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 600;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.2s ease;
  text-transform: uppercase;
  letter-spacing: 0.3px;
}

/* Ohne farbigen Schlagschatten. Beide Knoepfe warfen einen Schatten in ihrer eigenen
   Farbe - gruen unter Buy, rot unter Sell, im Ruhezustand bei 30% und im Hover bei 40%
   Deckung - was als Leuchten um den Knopf herum gelesen wurde statt als Hoehe.

   Der Hover war vorher NUR dieses staerkere Leuchten (die Regeln enthielten sonst nichts
   ausser einem verwaisten Semikolon, dort stand einmal ein translateY). Ersatzlos
   gestrichen waeren die Knoepfe auf Hover voellig reglos, deshalb hebt jetzt die
   Helligkeit an - dieselbe Rueckmeldung, ohne Schein nach aussen. */
.order-btn.buy-btn {
  background: linear-gradient(135deg, #28A745 0%, #20C997 100%);
  color: white;
}

.order-btn.buy-btn:hover:not(:disabled) {
  filter: brightness(1.08);
}

.order-btn.sell-btn {
  background: linear-gradient(135deg, #EF4444 0%, #DC2626 100%);
  color: white;
}

.order-btn.sell-btn:hover:not(:disabled) {
  filter: brightness(1.08);
}

.order-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  transform: none !important;
}

/* Replay Controls in Panel */
.replay-panel-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 8px;
  background: rgba(0, 0, 0, 0.02);
  border-radius: 8px;
  margin-bottom: 8px;
}

.replay-panel-btn {
  padding: 6px 10px;
  min-height: 30px;
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 8px;
  color: #1D1D1F;
  font-family: var(--font-ui);
  font-weight: 500;
  font-size: 11px;
  cursor: pointer;
  transition: all 0.15s ease;
  white-space: nowrap;
}

.replay-panel-btn:hover:not(:disabled) {
  background: rgba(0, 0, 0, 0.05);
  border-color: rgba(0, 0, 0, 0.15);
}

.replay-panel-btn:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

.replay-panel-btn.replay-play-btn {
  font-size: 12px;
  min-width: 36px;
}

.replay-panel-exit-btn {
  padding: 6px 10px;
  min-height: 30px;
  background: rgba(239, 68, 68, 0.1);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(239, 68, 68, 0.2);
  border-radius: 8px;
  color: #EF4444;
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 13px;
  cursor: pointer;
  transition: all 0.15s ease;
  white-space: nowrap;
}

.replay-panel-exit-btn:hover {
  background: rgba(239, 68, 68, 0.15);
  border-color: rgba(239, 68, 68, 0.3);
}

.replay-panel-expand-btn {
  padding: 6px 8px;
  min-height: 30px;
  background: rgba(0, 122, 255, 0.1);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(0, 122, 255, 0.2);
  border-radius: 8px;
  color: #007AFF;
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 11px;
  cursor: pointer;
  transition: all 0.15s ease;
  display: flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
}

.replay-panel-expand-btn:hover {
  background: rgba(0, 122, 255, 0.15);
  border-color: rgba(0, 122, 255, 0.3);
}

/* Collapsible Trading Section */
.replay-panel-trading-section {
  animation: slideDown 0.2s ease-out;
  overflow: hidden;
  margin-top: 8px;
}

.replay-panel-trading-section .replay-panel-trading-info {
  margin-bottom: 8px;
}

.replay-panel-trading-section .replay-panel-order-buttons {
  margin-bottom: 0;
}

@keyframes slideDown {
  from {
    opacity: 0;
    max-height: 0;
  }
  to {
    opacity: 1;
    max-height: 500px;
  }
}

/* Balance Selector */
.replay-panel-balance-selector {
  padding: 8px 12px;
  background: rgba(0, 0, 0, 0.02);
  border-radius: 8px;
  margin-bottom: 8px;
}

.balance-selector-label {
  display: block;
  font-family: var(--font-ui);
  font-size: 9px;
  font-weight: 600;
  color: #8E8E93;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  margin-bottom: 6px;
}

.balance-selector-controls {
  display: flex;
  gap: 6px;
  align-items: center;
}

.balance-input-wrapper {
  flex: 1;
  position: relative;
  display: flex;
  align-items: center;
}

.balance-input {
  flex: 1;
  padding: 6px 32px 6px 8px;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  color: #1D1D1F;
  outline: none;
  transition: all 0.15s ease;
}

.balance-input:focus {
  border-color: #007AFF;
  background: white;
}

.balance-input::-webkit-inner-spin-button,
.balance-input::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.balance-arrows {
  position: absolute;
  right: 4px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.balance-arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 14px;
  background: rgba(0, 0, 0, 0.04);
  border: none;
  border-radius: 4px;
  color: #8E8E93;
  cursor: pointer;
  transition: all 0.15s ease;
  padding: 0;
}

.balance-arrow:hover {
  background: rgba(0, 122, 255, 0.1);
  color: #007AFF;
}

.balance-arrow:active {
  background: rgba(0, 122, 255, 0.15);
  ;
}

.balance-reset-btn {
  padding: 6px 12px;
  background: rgba(0, 122, 255, 0.1);
  border: 1px solid rgba(0, 122, 255, 0.2);
  border-radius: 8px;
  color: #007AFF;
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.15s ease;
  white-space: nowrap;
}

.balance-reset-btn:hover {
  background: rgba(0, 122, 255, 0.15);
  border-color: rgba(0, 122, 255, 0.3);
}

/* Open Orders List */
.replay-panel-orders {
  padding: 8px 12px;
  background: rgba(0, 0, 0, 0.02);
  border-radius: 8px;
  max-height: 150px;
  overflow-y: auto;
}

.orders-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: var(--font-ui);
  font-size: 9px;
  font-weight: 600;
  color: #8E8E93;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  margin-bottom: 6px;
}

.order-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 8px;
  background: white;
  border-radius: 6px;
  margin-bottom: 6px;
  border-left: 2px solid;
}

.order-item.buy {
  border-left-color: #28A745;
}

.order-item.sell {
  border-left-color: #EF4444;
}

.order-info {
  display: flex;
  gap: 10px;
  align-items: center;
}

.order-type {
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.2px;
  min-width: 35px;
}

.order-item.buy .order-type {
  color: #28A745;
}

.order-item.sell .order-type {
  color: #EF4444;
}

.order-price {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  color: #1D1D1F;
}

.order-pnl {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
}

.order-pnl.profit {
  color: var(--bk-pos);
}

.order-pnl.loss {
  color: var(--bk-neg);
}

.close-order-btn {
  padding: 4px 10px;
  background: rgba(239, 68, 68, 0.1);
  border: 1px solid rgba(239, 68, 68, 0.2);
  border-radius: 8px;
  color: #EF4444;
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.15s ease;
}

.close-order-btn:hover {
  background: rgba(239, 68, 68, 0.15);
  border-color: rgba(239, 68, 68, 0.3);
}

.close-all-btn {
  padding: 3px 8px;
  background: rgba(239, 68, 68, 0.08);
  border: 1px solid rgba(239, 68, 68, 0.15);
  border-radius: 8px;
  color: #EF4444;
  font-family: var(--font-ui);
  font-size: 9px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  cursor: pointer;
  transition: all 0.15s ease;
}

.close-all-btn:hover {
  background: rgba(239, 68, 68, 0.12);
  border-color: rgba(239, 68, 68, 0.25);
}

/* Dark Mode Styles for Replay Panel */
.replay-panel.dark-mode {
  background: rgba(28, 28, 30, 0.98);
  border-color: var(--bk-border);
}

.replay-panel.dark-mode .replay-panel-trading-info,
.replay-panel.dark-mode .replay-panel-controls,
.replay-panel.dark-mode .replay-panel-orders,
.replay-panel.dark-mode .replay-panel-trading-section,
.replay-panel.dark-mode .replay-panel-balance-selector,
.replay-panel.dark-mode .sl-tp-controls {
  background: rgba(255, 255, 255, 0.05);
}

.replay-panel.dark-mode .trading-info-value {
  color: #F5F5F7;
}

.replay-panel.dark-mode .replay-panel-btn {
  background: rgba(255, 255, 255, 0.08);
  border-color: var(--bk-border);
  color: #F5F5F7;
}

.replay-panel.dark-mode .replay-panel-btn:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.12);
  border-color: rgba(255, 255, 255, 0.2);
}

.replay-panel.dark-mode .order-item {
  background: rgba(255, 255, 255, 0.06);
}

.replay-panel.dark-mode .order-price {
  color: #F5F5F7;
}

.replay-panel.dark-mode .balance-input {
  background: rgba(255, 255, 255, 0.08);
  border-color: var(--bk-border);
  color: #F5F5F7;
}

.replay-panel.dark-mode .balance-input:focus {
  background: rgba(255, 255, 255, 0.12);
  border-color: #007AFF;
}

.replay-panel.dark-mode .sl-tp-input {
  background: rgba(255, 255, 255, 0.08);
  border-color: var(--bk-border);
  color: #F5F5F7;
}

.replay-panel.dark-mode .sl-tp-input:focus {
  background: rgba(255, 255, 255, 0.12);
  border-color: #007AFF;
}
}

/* ===== ORDER PANEL STYLES ===== */
/* Order Panel (Top Center - Trading Controls) */
.order-panel {
  position: absolute;
  background: rgba(255, 255, 255, 0.98);
  backdrop-filter: blur(40px);
  -webkit-backdrop-filter: blur(40px);
  border: 1px solid rgba(142, 142, 147, 0.12);
  border-radius: 12px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.12), 0 4px 16px rgba(0, 0, 0, 0.06);
  padding: 10px 16px;
  min-width: 420px;
  max-width: 500px;
  z-index: 1001;
  user-select: none;
}

.order-panel-drag-handle {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2px 0 8px 0;
  cursor: move;
  color: #8E8E93;
  opacity: 0.5;
  transition: opacity 0.2s ease;
}

.order-panel-drag-handle:hover {
  opacity: 0.8;
}

.order-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 0;
  margin-bottom: 8px;
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  color: #1D1D1F;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.order-panel-toggle-btn {
  padding: 4px;
  background: rgba(0, 0, 0, 0.04);
  border: none;
  border-radius: 8px;
  color: #8E8E93;
  cursor: pointer;
  transition: all 0.15s ease;
  display: flex;
  align-items: center;
  justify-content: center;
}

.order-panel-toggle-btn:hover {
  background: rgba(0, 0, 0, 0.08);
  color: #1D1D1F;
}

.order-panel-trading-section {
  display: flex;
  flex-direction: column;
}

.order-panel-balance-selector {
  padding: 10px 12px;
  background: rgba(0, 0, 0, 0.02);
  border-radius: 8px;
  margin-bottom: 8px;
}

.order-panel-trading-info {
  display: flex;
  gap: 12px;
  padding: 8px 12px;
  background: rgba(0, 0, 0, 0.02);
  border-radius: 8px;
  margin-bottom: 8px;
}

.order-panel-order-buttons {
  display: flex;
  gap: 8px;
  margin-bottom: 8px;
}

.order-panel-orders {
  padding: 10px 12px;
  background: rgba(0, 0, 0, 0.02);
  border-radius: 8px;
  margin-top: 8px;
}

/* Dark Mode Styles for Order Panel */
.order-panel.dark-mode {
  background: rgba(28, 28, 30, 0.98);
  border-color: var(--bk-border);
}

.order-panel.dark-mode .order-panel-header {
  color: #F5F5F7;
}

.order-panel.dark-mode .order-panel-toggle-btn {
  background: rgba(255, 255, 255, 0.08);
  color: var(--bk-text-2);
}

.order-panel.dark-mode .order-panel-toggle-btn:hover {
  background: rgba(255, 255, 255, 0.12);
  color: #F5F5F7;
}

.order-panel.dark-mode .order-panel-trading-info,
.order-panel.dark-mode .order-panel-trading-section,
.order-panel.dark-mode .order-panel-balance-selector,
.order-panel.dark-mode .order-panel-orders {
  background: rgba(255, 255, 255, 0.05);
}

.order-panel.dark-mode .trading-info-value {
  color: #F5F5F7;
}

.order-panel.dark-mode .order-item {
  background: rgba(255, 255, 255, 0.06);
}

.order-panel.dark-mode .order-price {
  color: #F5F5F7;
}

.order-panel.dark-mode .balance-input {
  background: rgba(255, 255, 255, 0.08);
  border-color: var(--bk-border);
  color: #F5F5F7;
}

.order-panel.dark-mode .balance-input:focus {
  background: rgba(255, 255, 255, 0.12);
  border-color: #007AFF;
}

.order-panel.dark-mode .sl-tp-input {
  background: rgba(255, 255, 255, 0.08);
  border-color: var(--bk-border);
  color: #F5F5F7;
}

.order-panel.dark-mode .sl-tp-input:focus {
  background: rgba(255, 255, 255, 0.12);
  border-color: #007AFF;
}

.trend-table-container.small .trend-separator {
  font-size: 7px;
}

/* Dark Mode */
.trend-table-container.dark-mode {
  background: rgba(28, 28, 30, 0.95);
}

.trend-table-container.dark-mode .trend-table-title {
  color: var(--bk-text-2);
  border-bottom: 1px solid rgba(58, 58, 60, 0.5);
}

.trend-table-container.dark-mode .trend-header-cell {
  color: var(--bk-text-2);
}

.trend-table-container.dark-mode .close-btn {
  color: var(--bk-text-2);
}

.trend-table-container.dark-mode .close-btn:hover {
  background: rgba(255, 69, 58, 0.15);
  color: #FF453A;
}

.trend-table-container.dark-mode .trend-table-row {
  background: rgba(58, 58, 60, 0.5);
}

.trend-table-container.dark-mode .trend-table-row:hover {
  background: rgba(58, 58, 60, 0.7);
}

.trend-table-container.dark-mode .trend-table-row.overall-row {
  background: rgba(16, 185, 129, 0.2);
  border: 1px solid rgba(16, 185, 129, 0.4);
}

.trend-table-container.dark-mode .trend-table-row.overall-row:hover {
  background: rgba(16, 185, 129, 0.25);
}

.trend-table-container.dark-mode .trend-table-cell {
  color: var(--bk-text-2);
}

.trend-table-container.dark-mode .strength-text {
  color: var(--bk-text-2);
}

.trend-table-container.dark-mode .strength-text.mid {
  color: #FF9F0A;
}

/* ========================================
   CHART SCALE LABELS - DARK MODE
   ======================================== */
/* Ensure timescale and price scale text is fully white with no shadow in dark mode */
.dark-mode div[class*="tv-lightweight-charts"] table tr td,
.dark-mode .tv-lightweight-charts table tr td,
.dark-mode div[class*="tv-lightweight-charts"] div,
.dark-mode .tv-lightweight-charts div {
  color: #F7F7F7 !important;
  text-shadow: none !important;
}

/* Target all possible scale label elements */
.dark-mode [class*="tv-lightweight-charts"] td[style*="color"],
.dark-mode [class*="tv-lightweight-charts"] div[style*="color"] {
  color: #F7F7F7 !important;
}

/* ========================================
   TRADE CHECKER BUTTON
   ======================================== */
.trade-checker-btn {
  position: absolute;
  top: 3px;
  right: 74px;
  z-index: 90;
  /* Same surface as the backtest dashboard. The dashboard's own scoped rule is dead:
     it sits in the "schwebende Paneele" group further down, which comes later and
     puts every floating panel on --bk-elevated with no backdrop blur. */
  background: var(--bk-elevated);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 8px;
  padding: 8px 14px;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 500;
  color: #1D1D1F;
  cursor: pointer;
  transition: all 0.2s ease;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.trade-checker-btn:hover {
  background: #F2F2F7;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
  ;
}

.trade-checker-btn svg {
  color: #10b981;
}

/* While the checker fetches the trend rows itself (trend table off), which takes a
   couple of seconds - long enough that a click with no response gets clicked again. */
.trade-checker-btn.checking {
  opacity: 0.6;
  cursor: progress;
}

.trade-checker-btn.checking svg {
  animation: trade-checker-pulse 0.9s ease-in-out infinite alternate;
}

@keyframes trade-checker-pulse {
  from { opacity: 1; }
  to { opacity: 0.3; }
}

.dark-mode .trade-checker-btn {
  border-color: var(--bk-border);
  color: #F7F7F7;
}

.dark-mode .trade-checker-btn:hover {
  background: #1F2023;
}

/* ========================================
   PRICE ALERTS PANEL
   ======================================== */

/* The panel itself is in the "schwebende Paneele" group further down now, so its surface,
   border, radius and lift arrive from there like every other dialog in the app. What lives
   here is the inside, which was forty inline `currentTheme === 'dark' ? a : b` ternaries
   over hardcoded #1e1e1e, #2a2a2a, #1a1a1a and a pile of rgba(255,255,255,x). None of
   those answered to a theme token, so the panel drifted every time the tokens moved and
   was the one dialog that did not match the rest in dark mode. */

.price-alerts-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

.price-alerts-modal {
  width: 90%;
  max-width: 600px;
  max-height: 80vh;
  padding: 24px;
  overflow-y: auto;
  pointer-events: all;
  font-family: var(--font-ui);
  color: var(--bk-text);
}

.alerts-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 24px;
}

.alerts-title {
  margin: 0;
  font-size: 20px;
  font-weight: 700;
  color: var(--bk-text);
}

.alerts-close {
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 8px;
  color: var(--bk-text-3);
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease;
}

.alerts-close:hover { background: var(--bk-hover); color: var(--bk-text); }

/* The strip that says which market the next alert will be attached to. */
.alerts-context {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 12px 16px;
  margin-bottom: 20px;
  background: var(--bk-card);
  border-radius: 10px;
}

.alerts-context-label { font-size: 13px; color: var(--bk-text-2); }
.alerts-context-symbol { font-size: 15px; font-weight: 600; color: var(--bk-text); }
.alerts-context-price {
  margin-left: auto;
  font-size: 13px;
  font-weight: 600;
  color: var(--bk-pos);
  font-variant-numeric: tabular-nums;
}

.alerts-section {
  padding: 20px;
  margin-bottom: 20px;
  background: var(--bk-card);
  border-radius: 12px;
}

.alerts-section-title {
  margin: 0 0 16px;
  font-size: 15px;
  font-weight: 600;
  color: var(--bk-text);
}

.alerts-fields {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-bottom: 12px;
}

.alerts-field { min-width: 0; }
.alerts-field--wide { grid-column: 1 / -1; }

.alerts-label {
  display: block;
  margin-bottom: 6px;
  font-size: 13px;
  color: var(--bk-text-2);
}

.alerts-input {
  width: 100%;
  padding: 10px;
  background: var(--bk-input);
  border: 1px solid var(--bk-border);
  border-radius: 8px;
  color: var(--bk-text);
  font-family: var(--font-ui);
  font-size: 14px;
}

.alerts-input::placeholder { color: var(--bk-text-3); }
.alerts-input:focus { outline: none; border-color: var(--bk-border-strong, var(--bk-text-3)); }
select.alerts-input { cursor: pointer; }

.alerts-submit {
  width: 100%;
  padding: 12px;
  background: linear-gradient(135deg, var(--brand) 0%, var(--brand-hover) 100%);
  color: #FFFFFF;
  border: none;
  border-radius: 8px;
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: box-shadow 140ms ease, transform 140ms ease;
}

.alerts-submit:hover { box-shadow: 0 4px 14px rgba(76, 41, 233, 0.35); }
.alerts-submit:active { transform: translateY(1px); }

.alerts-empty {
  padding: 20px;
  text-align: center;
  font-size: 13px;
  color: var(--bk-text-3);
}

.alerts-list { display: flex; flex-direction: column; gap: 8px; }

.alert-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px;
  background: var(--bk-card);
  border-radius: 10px;
}

.alert-row-main { flex: 1; min-width: 0; }

.alert-row-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 4px;
}

.alert-price {
  font-size: 16px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.alert-price--up { color: var(--bk-pos); }
.alert-price--down { color: var(--bk-neg); }

/* The direction pill. The arrow stays - it is the reading, not decoration. */
.alert-badge {
  padding: 2px 8px;
  border-radius: 5px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

.alert-badge--up { background: rgba(16, 185, 129, 0.15); color: var(--bk-pos); }
.alert-badge--down { background: rgba(239, 68, 68, 0.15); color: var(--bk-neg); }

.alert-meta { font-size: 12px; color: var(--bk-text-3); }
.alert-note { font-size: 12px; color: var(--bk-text-2); }

.alert-row-actions { display: flex; gap: 6px; flex-shrink: 0; }

.alerts-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 6px 12px;
  background: var(--bk-hover);
  border: 1px solid var(--bk-border);
  border-radius: 6px;
  color: var(--bk-text-2);
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease, color 140ms ease;
}

.alerts-btn:hover { color: var(--bk-text); }

/* On = the alert's line is drawn on the chart. Reads as a state, not another action. */
.alerts-btn--on {
  background: rgba(16, 185, 129, 0.15);
  border-color: var(--bk-pos);
  color: var(--bk-pos);
}

.alerts-btn--danger {
  background: rgba(239, 68, 68, 0.1);
  border-color: rgba(239, 68, 68, 0.2);
  color: var(--bk-neg);
}

.dark-mode .alerts-btn--danger { border-color: rgba(239, 68, 68, 0.3); }
.alerts-btn--danger:hover { background: rgba(239, 68, 68, 0.18); border-color: rgba(239, 68, 68, 0.45); color: var(--bk-neg); }

.alerts-history {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid var(--bk-border);
}

.alerts-history-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

/* Spent alerts: same row, dimmed, with the direction carried on the edge so the list can
   be read down the side without going word by word. */
.alert-row--triggered {
  display: block;
  padding: 12px;
  opacity: 0.7;
  border-left: 3px solid var(--bk-border);
}

.alert-row--triggered.alert-row--up { border-left-color: var(--bk-pos); }
.alert-row--triggered.alert-row--down { border-left-color: var(--bk-neg); }

.alert-row--triggered .alert-price { font-size: 14px; font-weight: 600; color: var(--bk-text); }
.alert-row--triggered .alert-badge { padding: 2px 6px; font-size: 10px; }

.alert-flag {
  margin-left: auto;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--bk-pos);
}

.alert-triggered-at {
  font-size: 11px;
  color: var(--bk-text-3);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 640px) {
  .alerts-fields { grid-template-columns: 1fr; }
  .alert-row { flex-direction: column; align-items: stretch; }
  .alert-row-actions { justify-content: flex-end; }
}

@media (prefers-reduced-motion: reduce) {
  .alerts-close, .alerts-submit, .alerts-btn { transition: none; }
  .alerts-submit:active { transform: none; }
}

/* ========================================
   JOURNAL - RECENT TRADES ACTIONS
   ======================================== */

/* Clear All and Add Trade are a pair, so they are built as one: same height, radius, type
   and press behaviour, and the only thing separating them is the job - a tinted outline
   for the destructive one, a solid brand fill for the one meant to be reached for.
   Both colours are the ones they already had.
   The icons are gone rather than redrawn: a trash emoji renders at a different size,
   weight and colour on every platform, and a bare "+" typed as text sat on the baseline
   instead of centred against the label. Neither earned the space next to a word that
   already says what the button does. */
.journal-action-btn {
  height: 30px;
  padding: 0 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid transparent;
  border-radius: 8px;
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
  cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease, box-shadow 140ms ease, transform 140ms ease;
}

.journal-action-btn:active {
  transform: translateY(1px);
}

.journal-action-btn:focus-visible {
  outline: 2px solid var(--bk-text-3);
  outline-offset: 2px;
}

/* Destructive, and it stays an outline on purpose. Filled solid next to the brand button
   it would read as an equal offer, and emptying the journal is not something to invite. */
.journal-action-btn--danger {
  background: rgba(239, 68, 68, 0.1);
  border-color: rgba(239, 68, 68, 0.2);
  color: var(--bk-neg);
}

.dark-mode .journal-action-btn--danger {
  border-color: rgba(239, 68, 68, 0.3);
}

.journal-action-btn--danger:hover {
  background: rgba(239, 68, 68, 0.18);
  border-color: rgba(239, 68, 68, 0.45);
}

.journal-action-btn--primary {
  background: linear-gradient(135deg, var(--brand) 0%, var(--brand-hover) 100%);
  color: #FFFFFF;
}

.journal-action-btn--primary:hover {
  box-shadow: 0 4px 14px rgba(76, 41, 233, 0.35);
}

@media (prefers-reduced-motion: reduce) {
  .journal-action-btn { transition: none; }
  .journal-action-btn:active { transform: none; }
}

/* ========================================
   JOURNAL CALENDAR MONTH STEPPER
   ======================================== */

/* The two arrows are ONE control, not two buttons that happen to sit next to each other:
   a single recessed pill with a hairline dividing the halves. Two separate bordered boxes
   read as two unrelated actions, and at this size a lone bordered box reads as an input
   field rather than something to press. */
.journal-month-nav {
  display: inline-flex;
  align-items: stretch;
  background: var(--bk-hover);
  border: 1px solid var(--bk-border);
  border-radius: 10px;
  /* Keeps the halves' hover fill inside the rounded corners. */
  overflow: hidden;
}

.journal-month-btn {
  width: 32px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: transparent;
  border: none;
  color: var(--bk-text-2);
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease;
}

/* A real border rather than an inset box-shadow: the pill keeps one outer border, the
   divider belongs to the second half only, and there is no inset shadow for anything
   downstream to render badly. */
.journal-month-btn + .journal-month-btn {
  border-left: 1px solid var(--bk-border);
}

.journal-month-btn:hover {
  background: var(--bk-card);
  color: var(--bk-text);
}

.journal-month-btn:active {
  background: var(--bk-border);
}

.journal-month-btn:focus-visible {
  outline: 2px solid var(--bk-pos);
  outline-offset: -2px;
}

/* The chevron leans the way it travels, but only on the half under the cursor. Two pixels
   - enough to register as the control answering, not as something sliding about. */
.journal-month-btn svg {
  display: block;
  transition: transform 140ms ease;
}

.journal-month-btn--prev:hover svg { transform: translateX(-2px); }
.journal-month-btn--next:hover svg { transform: translateX(2px); }

@media (prefers-reduced-motion: reduce) {
  .journal-month-btn svg { transition: none; }
  .journal-month-btn--prev:hover svg,
  .journal-month-btn--next:hover svg { transform: none; }
}

/* ========================================
   SCROLL TO MOST RECENT BAR
   ======================================== */

/* Sits in the bottom-right corner of the plot, the corner it travels towards. The 74px
   is the same inset .trade-checker-btn uses to clear the price axis; the bottom clears
   the time axis. Only mounted while the newest bar is off screen - see showScrollToRecent. */
.scroll-to-recent-btn {
  position: absolute;
  right: 74px;
  bottom: 44px;
  z-index: 90;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: 50%;
  /* --bk-card, NOT --bk-elevated, and the difference matters here: --bk-elevated is
     #151619 in dark, which is the exact colour the chart canvas paints behind this button.
     The panels that use it sit on the app shell; this one sits on the chart, and there it
     was a #151619 circle on a #151619 ground - present, hit-testable and invisible.
     --bk-card is a step off the chart on both themes, and the border strengthens it. */
  background: var(--bk-card);
  border: 1px solid var(--bk-border-strong, var(--bk-border));
  color: var(--bk-text);
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
  transition: background 0.15s ease, transform 0.15s ease;
}

/* No entrance animation here, and that is deliberate rather than an omission.
   A fade-in from opacity 0 was the obvious thing and it is a trap: a CSS animation can sit
   in the pending state - playState "running", startTime null - when the document timeline
   is not advancing, which happens whenever the page is not being painted. While pending it
   still applies its first keyframe, so the button held opacity 0 and stayed invisible and
   unclickable for as long as the tab was in that state. Nothing about the resting
   appearance of a control should depend on an animation having been scheduled. */

.scroll-to-recent-btn:hover {
  transform: scale(1.08);
}

/* Zoom / scroll bar at the bottom of the chart (ChartNavBar.jsx), after TradingView's:
   22px buttons in pairs (a touch under TradingView's 24), shown only while the mouse is near. Placed by the component
   (left is the centre, top the buttons' top), so only the look lives here. The wrapper
   never takes a click itself - only the buttons do - so the chart under the gaps still
   pans. Faded rather than animated in, for the reason given on .scroll-to-recent-btn. */
.chart-nav-bar {
  position: absolute;
  z-index: 90;
  display: flex;
  transform: translateX(-50%);
  pointer-events: none;
  opacity: 1;
  visibility: visible;
  transition: opacity 0.3s, visibility 0.3s;
}
.chart-nav-bar.hidden { opacity: 0; visibility: hidden; }
.chart-nav-bar.hidden .chart-nav-btn { visibility: hidden; }

.chart-nav-group {
  display: flex;
  align-items: center;
  margin: 0 4px;
}

.chart-nav-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  /* mobile.css sets a minimum on every button by window width - 44px on a phone, 40px up
     to 1024px, 36px in a short landscape window - so a desktop window dragged narrow blew
     these up to touch-target size. They only exist for a mouse; the minimum is undone here,
     where the class outranks mobile.css's bare `button` at every width. */
  min-width: 0;
  min-height: 0;
  margin: 0 3px;
  padding: 0;
  border: 1px solid var(--bk-border);
  border-radius: 4px;
  background: var(--bk-card);
  color: var(--bk-text);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  cursor: pointer;
  pointer-events: auto;
  user-select: none;
  transition: background 0.15s ease, opacity 0.4s, visibility 0.4s;
}
.chart-nav-btn svg { pointer-events: none; }
.chart-nav-btn-left svg { transform: rotate(180deg); }
.chart-nav-btn:hover { background: #E6E6E6; }
.chart-nav-btn:active { background: #D9D9D9; transition: none; }
.dark-mode .chart-nav-btn { border-color: var(--bk-border-strong, var(--bk-border)); }
.dark-mode .chart-nav-btn:hover { background: #2C2D31; }
.dark-mode .chart-nav-btn:active { background: #36373C; }
/* The reset keeps its place in the row while there is nothing to reset, as TradingView's
   does, so the other four never shift when it appears. */
.chart-nav-btn-hidden { opacity: 0; visibility: hidden; }

/* A mouse affordance: a touch screen pinches and drags instead. */
@media (hover: none) {
  .chart-nav-bar { display: none; }
}

.dark-mode .scroll-to-recent-btn:hover {
  background: #1F2023;
}

.scroll-to-recent-btn:active {
  transform: scale(0.96);
}

/* The phone pulls the button in, because the price axis is narrower there and the replay
   bar owns the bottom centre.
   Size is left alone on purpose: the app sets a 44px min-width/min-height on every button
   under 768px as a touch target, and that beats anything set here. The button is meant to
   grow on a phone, so this rule moves it rather than fighting over how big it is. */
@media (max-width: 640px) {
  .scroll-to-recent-btn {
    right: 58px;
    bottom: 38px;
  }
}

/* ========================================
   TRADE CHECKER MODAL
   ======================================== */
.trade-checker-modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10000;
}

.trade-checker-modal {
  background: #FFFFFF;
  border-radius: 16px;
  width: 480px;
  max-width: 90vw;
  max-height: 80vh;
  overflow-y: auto;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
}

.trade-checker-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 24px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}

.trade-checker-header h3 {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: #1D1D1F;
}

.trade-checker-header .close-btn {
  background: none;
  border: none;
  font-size: 20px;
  color: #86868B;
  cursor: pointer;
  padding: 0;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  transition: all 0.2s ease;
}

.trade-checker-header .close-btn:hover {
  background: rgba(0, 0, 0, 0.05);
  color: #1D1D1F;
}

.trade-checker-score {
  padding: 32px 24px;
  text-align: center;
}

.score-circle {
  width: 140px;
  height: 140px;
  border-radius: 50%;
  border: 8px solid;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin: 0 auto 16px;
}

.score-percentage {
  font-size: 36px;
  font-weight: 700;
  color: #1D1D1F;
}

.score-rating {
  font-size: 14px;
  font-weight: 600;
  color: #86868B;
  margin-top: 4px;
}

.score-details {
  margin-top: 12px;
}

.score-fraction {
  font-size: 14px;
  color: #86868B;
}

.trade-checker-breakdown {
  padding: 0 24px 24px;
}

.trade-checker-breakdown h4 {
  margin: 0 0 12px 0;
  font-size: 14px;
  font-weight: 600;
  color: #1D1D1F;
}

.breakdown-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.breakdown-item {
  font-size: 13px;
  color: #1D1D1F;
  padding: 8px 12px;
  background: rgba(0, 0, 0, 0.03);
  border-radius: 6px;
}

.trade-checker-footer {
  padding: 16px 24px;
  background: rgba(0, 0, 0, 0.03);
  border-top: 1px solid rgba(0, 0, 0, 0.1);
}

.trade-checker-footer p {
  margin: 0;
  font-size: 13px;
  color: #1D1D1F;
  line-height: 1.5;
}

.trade-checker-disclaimer {
  background: rgba(255, 193, 7, 0.08);
  border-top: 1px solid rgba(255, 193, 7, 0.3);
  border-radius: 0 0 16px 16px;
}

.disclaimer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 24px;
  cursor: pointer;
  transition: background 0.2s ease;
}

.disclaimer-header:hover {
  background: rgba(255, 193, 7, 0.12);
}

.disclaimer-title {
  display: flex;
  align-items: center;
  font-size: 12px;
  color: #666;
}

.disclaimer-title strong {
  color: #1D1D1F;
  font-weight: 600;
}

.disclaimer-header svg {
  color: #666;
  flex-shrink: 0;
}

.disclaimer-content {
  padding: 0 24px 16px 24px;
}

.disclaimer-content p {
  margin: 0;
  font-size: 11px;
  color: #666;
  line-height: 1.6;
}

/* Dark mode */
.dark-mode .trade-checker-modal {
  background: #1E1E1E;
}

.dark-mode .trade-checker-header {
  border-bottom-color: var(--bk-border);
}

.dark-mode .trade-checker-header h3,
.dark-mode .score-percentage,
.dark-mode .trade-checker-breakdown h4,
.dark-mode .breakdown-item,
.dark-mode .trade-checker-footer p {
  color: #F7F7F7;
}

.dark-mode .trade-checker-header .close-btn {
  color: var(--bk-text-3);
}

.dark-mode .trade-checker-header .close-btn:hover {
  background: rgba(255, 255, 255, 0.1);
  color: #F7F7F7;
}

.dark-mode .breakdown-item {
  background: rgba(255, 255, 255, 0.05);
}

.dark-mode .trade-checker-footer {
  background: rgba(255, 255, 255, 0.03);
  border-top-color: var(--bk-border);
}

.dark-mode .trade-checker-disclaimer {
  background: rgba(255, 193, 7, 0.12);
  border-top-color: rgba(255, 193, 7, 0.3);
}

.dark-mode .disclaimer-header:hover {
  background: rgba(255, 193, 7, 0.18);
}

.dark-mode .disclaimer-title {
  color: #AAA;
}

.dark-mode .disclaimer-title strong {
  color: #F7F7F7;
}

.dark-mode .disclaimer-header svg {
  color: #AAA;
}

.dark-mode .disclaimer-content p {
  color: #AAA;
}

.trend-table-container.dark-mode .trend-separator {
  color: var(--bk-text-2);
  border: 1px solid #242424;
}

.dark-mode .backtest-results-header {
  border-bottom: 1px solid #242424;
}

.dark-mode .backtest-results-title {
  color: var(--bk-text-2);
}

.dark-mode .backtest-result-item {
  background: rgba(58, 58, 60, 0.5);
}

.dark-mode .backtest-result-item.best {
  background: rgba(16, 185, 129, 0.15);
  border: 1px solid rgba(16, 185, 129, 0.3);
}

.dark-mode .backtest-result-label {
  color: var(--bk-text-2);
}

.dark-mode .backtest-result-value {
  color: #F7F7F7;
}

.dark-mode .backtest-result-value.highlight {
  color: #10B981;
}

.dark-mode .apply-backtest-btn {
  background: rgba(16, 185, 129, 0.2);
  color: #10B981;
  border: 1px solid rgba(16, 185, 129, 0.4);
}

.dark-mode .apply-backtest-btn:hover {
  background: rgba(16, 185, 129, 0.3);
  border-color: rgba(16, 185, 129, 0.6);
  box-shadow: 0 2px 12px rgba(16, 185, 129, 0.4);
}

.dark-mode .backtest-overlay {
  background: #101010;
  border: 1px solid #242424;
  color: #F7F7F7;
}

.dark-mode .backtest-close-btn {
  color: var(--bk-text-2);
}

.dark-mode .backtest-close-btn:hover {
  color: #F7F7F7;
  background: rgba(255, 255, 255, 0.1);
}

/* Watchlist - Dark Mode */
.dark-mode .watchlist-drawer {
  background: var(--bk-elevated);
  border: 1px solid #242424;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.55);
}

/* Position size calculator - dark mode */
.dark-mode .position-calc-drawer {
  background: var(--bk-elevated);
  border: 1px solid #242424;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
}

.dark-mode .position-calc-drawer .drawer-header {
  border-bottom: 1px solid #242424;
}

.dark-mode .calc-field-grid {
  border-bottom-color: #242424;
}

.dark-mode .calc-field-label {
  color: var(--bk-text-2);
}

.dark-mode .calc-input {
  background: var(--bk-input);
  border-color: #242424;
  color: #F7F7F7;
}

.dark-mode .calc-input:focus {
  border-color: #303030;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.05);
}

.dark-mode .calc-result {
  background: rgba(255, 255, 255, 0.04);
  border-color: var(--bk-border);
}

.dark-mode .calc-result-label {
  color: var(--bk-text-3);
}

.dark-mode .calc-result-value,
.dark-mode .calc-row-value {
  color: #F7F7F7;
}

.dark-mode .calc-row {
  color: var(--bk-text-3);
}

.dark-mode .calc-direction.long {
  background: rgba(52, 199, 89, 0.18);
  color: #4ADE80;
}

.dark-mode .calc-direction.short {
  background: rgba(255, 59, 48, 0.18);
  color: #FF7A70;
}

.dark-mode .calc-risk {
  color: #FF7A70;
}

.dark-mode .calc-reward {
  color: #4ADE80;
}

.dark-mode .calc-note {
  background: rgba(255, 149, 0, 0.12);
  border-color: rgba(255, 149, 0, 0.28);
  color: #F0A94B;
}

.dark-mode .calc-empty {
  color: var(--bk-text-3);
}

.dark-mode .calc-error {
  color: #FF7A70;
}

.dark-mode .watchlist-drawer .drawer-header {
  border-bottom: none;
}

.dark-mode .wl-create {
  border-bottom: 1px solid #242424;
}

.dark-mode .wl-create-input,
.dark-mode .wl-add-input {
  background: rgba(255, 255, 255, 0.06);
  border-color: var(--bk-border);
  color: #F5F5F7;
}

.dark-mode .wl-create-input:focus,
.dark-mode .wl-add-input:focus {
  border-color: #0A84FF;
}

.dark-mode .wl-group-count {
  background: rgba(255, 255, 255, 0.08);
}

.dark-mode .wl-icon-btn {
  color: var(--bk-text-off);
}

.dark-mode .wl-icon-btn:hover {
  background: rgba(255, 255, 255, 0.07);
  color: #F5F5F7;
}

.dark-mode .wl-icon-btn.active {
  color: var(--bk-text);
  background: rgba(10, 132, 255, 0.16);
}

.dark-mode .wl-icon-btn.danger:hover {
  background: rgba(255, 59, 48, 0.16);
  color: #FF6B6B;
}

.dark-mode .wl-row {
  border-bottom: 1px solid var(--bk-border);
}

.dark-mode .wl-row:hover {
  background: rgba(255, 255, 255, 0.045);
}

.dark-mode .wl-row-ticker {
  color: #F5F5F7;
}

.dark-mode .wl-row-remove {
  color: var(--bk-text-off);
}

.dark-mode .wl-row-remove:hover {
  background: rgba(255, 59, 48, 0.16);
  color: #FF6B6B;
}

.dark-mode .wl-none {
  color: #48484A;
}

.dark-mode .wl-none-title {
  color: #F5F5F7;
}

/* Timeframe Dropdown - Dark Mode */
.dark-mode .timeframe-dropdown-item {
  color: var(--bk-text-2);
}

.dark-mode .timeframe-dropdown-item:hover {
  background: rgba(255, 255, 255, 0.08);
  color: #F7F7F7;
}

.dark-mode .timeframe-dropdown-item.active {
  background: rgba(255, 255, 255, 0.12);
  color: #F7F7F7;
}

.dark-mode .timeframe-group-header {
  color: var(--bk-text-2);
}

/* ========================================
   FIBONACCI LEVELS MODAL
   ======================================== */
.fib-levels-modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 500px;
  max-height: 80vh;
  background: rgba(255, 255, 255, 0.98);
  backdrop-filter: blur(40px);
  border-radius: 14px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
  /* Above the .drawer-overlay this modal opens with. At 1001 the overlay's 1500 covered
     the modal itself: it greyed the panel out and swallowed every click on it, so the
     colour pickers, the checkboxes and even Cancel were dead. 1501 is what .symbol-modal
     and .indicator-modal already use over the same overlay. */
  z-index: 1501;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.fib-levels-content {
  padding: 20px;
  overflow-y: auto;
  flex: 1;
}

.fib-levels-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin-bottom: 20px;
}

.fib-levels-column {
  display: flex;
  flex-direction: column;
  gap: 8px;
  /* Grid items default to min-width: auto, so a column could not shrink below the intrinsic
     width of the text input inside it. Two columns then measured wider than the modal and
     .fib-levels-content (overflow-y:auto, so overflow-x computes to auto) grew a horizontal
     scrollbar - the second column had to be scrolled into view. */
  min-width: 0;
}

.fib-level-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px;
  background: rgba(142, 142, 147, 0.08);
  border-radius: 8px;
  transition: background 0.2s;
}

.fib-level-row:hover {
  background: rgba(142, 142, 147, 0.12);
}

.fib-level-checkbox {
  width: 18px;
  height: 18px;
  cursor: pointer;
  accent-color: #007AFF;
}

.fib-level-input {
  flex: 1;
  /* Same reason as the column: a flex item will not go below its intrinsic input width
     without this, which is what pushed the row past the modal edge. */
  min-width: 0;
  padding: 6px 10px;
  background: rgba(142, 142, 147, 0.08);
  border: 1px solid rgba(142, 142, 147, 0.12);
  border-radius: 6px;
  font-size: 13px;
  color: #1D1D1F;
  font-family: 'SF Mono', 'Monaco', 'Courier New', monospace;
  text-align: center;
}

.fib-color-btn {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  border: 2px solid rgba(142, 142, 147, 0.2);
  cursor: pointer;
  transition: transform 0.2s, border-color 0.2s;
}

.fib-color-btn:hover {
  ;
  border-color: rgba(142, 142, 147, 0.4);
}

.fib-levels-actions {
  display: flex;
  gap: 12px;
  justify-content: flex-end;
  padding: 16px 20px;
  border-top: 1px solid rgba(142, 142, 147, 0.12);
  /* A row of the modal's own flex column, sitting after the scrolling content rather than
     inside it. Sticky-positioning it within the scroller was the wrong fix: it stuck to the
     scrollport's padding edge, so level rows stayed visible in the 20px below the bar.
     As a sibling it is simply the last thing in the modal and nothing can render past it. */
  flex-shrink: 0;
  background: rgba(255, 255, 255, 0.98);
  border-bottom-left-radius: 14px;
  border-bottom-right-radius: 14px;
}

.fib-btn-secondary {
  padding: 8px 16px;
  background: transparent;
  border: 1px solid rgba(142, 142, 147, 0.2);
  border-radius: 8px;
  color: #1D1D1F;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s;
}

.fib-btn-secondary:hover {
  background: rgba(142, 142, 147, 0.08);
  border-color: rgba(142, 142, 147, 0.3);
}

.fib-btn-primary {
  padding: 8px 20px;
  background: #007AFF;
  border: none;
  border-radius: 8px;
  color: #FFFFFF;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.2s;
}

.fib-btn-primary:hover {
  background: #0051D5;
}

/* Dark Mode */
.dark-mode .fib-levels-modal {
  background: rgba(28, 28, 30, 0.98);
}

.dark-mode .fib-level-row {
  background: rgba(255, 255, 255, 0.05);
}

.dark-mode .fib-level-row:hover {
  background: rgba(255, 255, 255, 0.08);
}

.dark-mode .fib-level-input {
  background: rgba(255, 255, 255, 0.05);
  border-color: var(--bk-border);
  color: var(--bk-text-2);
}

.dark-mode .fib-color-btn {
  border-color: var(--bk-border);
}

.dark-mode .fib-color-btn:hover {
  border-color: rgba(255, 255, 255, 0.4);
}

.dark-mode .fib-levels-actions {
  border-top-color: var(--bk-border);
  background: rgba(28, 28, 30, 0.98);
}

.dark-mode .fib-btn-secondary {
  border-color: var(--bk-border);
  color: var(--bk-text-2);
}

.dark-mode .fib-btn-secondary:hover {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.3);
}

/* ========================================
   FIBONACCI CUSTOMIZE BUTTON IN DROPDOWN
   ======================================== */
.fib-customize-btn {
  width: 100%;
  padding: 10px;
  margin-top: 8px;
  background: rgba(142, 142, 147, 0.08);
  border: 1px solid rgba(142, 142, 147, 0.12);
  border-radius: 8px;
  color: #1D1D1F;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  transition: all 0.2s;
}

.fib-customize-btn:hover {
  background: rgba(142, 142, 147, 0.12);
  border-color: rgba(142, 142, 147, 0.2);
}

.fib-customize-btn svg {
  width: 14px;
  height: 14px;
  opacity: 0.7;
}

/* Dark Mode */
.dark-mode .fib-customize-btn {
  background: rgba(255, 255, 255, 0.05);
  border-color: var(--bk-border);
  color: var(--bk-text-2);
}

.dark-mode .fib-customize-btn:hover {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.15);
}

/* ========================================
   POSITION COLOR DROPDOWN
   ======================================== */
.position-color-dropdown {
  min-width: 280px !important;
  max-width: 320px !important;
}

.position-color-section {
  margin-bottom: 16px;
}

.position-color-section:last-child {
  margin-bottom: 0;
}

.position-color-label {
  font-size: 12px;
  font-weight: 600;
  color: #1D1D1F;
  margin-bottom: 8px;
  padding: 0 4px;
}

.dark-mode .position-color-label {
  color: var(--bk-text-2);
}
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
  border: 1px solid rgba(52, 211, 153, 0.4);
  backdrop-filter: blur(10px);
  overflow: hidden;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  z-index: 1000;
  display: flex;
  flex-direction: column;
}

.swift-algo-trend-table-container.size-big {
  width: 240px;
  height: 240px;
  padding: 8px;
}

.swift-algo-trend-table-container.size-small {
  width: 200px;
  height: 200px;
  padding: 6px;
}

.swift-algo-trend-table-header {
  padding: 6px;
  background: rgba(31, 41, 55, 0.8);
  border-bottom: 1px solid rgba(52, 211, 153, 0.3);
  font-weight: 700;
  font-size: 9px;
  color: #34D399;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  text-align: center;
  cursor: grab;
  user-select: none;
  flex-shrink: 0;
}

/* New Grid Layout */
.swift-algo-trend-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  gap: 4px;
  flex: 1;
  padding: 4px;
}

.trend-grid-cell {
  background: rgba(31, 41, 55, 0.6);
  border: 1px solid rgba(52, 211, 153, 0.2);
  border-radius: 4px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 4px;
  transition: all 0.2s ease;
  min-height: 0;
}

.trend-grid-cell:hover {
  background: rgba(31, 41, 55, 0.8);
  border-color: rgba(52, 211, 153, 0.4);
  ;
}

.trend-grid-cell.overall-cell {
  background: rgba(52, 211, 153, 0.15);
  border-color: rgba(52, 211, 153, 0.4);
  font-weight: 700;
  grid-column: 2;
}

.cell-timeframe {
  font-size: 10px;
  font-weight: 700;
  color: #34D399;
  margin-bottom: 4px;
  text-align: center;
  white-space: nowrap;
}

.cell-indicators {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.cell-trend {
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
}

.cell-trend.bullish {
  color: #10B981;
}

.cell-trend.bearish {
  color: #EF4444;
}

.cell-strength {
  font-size: 10px;
  line-height: 1;
}

.cell-strength.strength-high {
  color: #10B981;
}

.cell-strength.strength-medium {
  color: #F59E0B;
}

.cell-strength.strength-low {
  color: #EF4444;
}

.cell-status {
  font-size: 10px;
  line-height: 1;
}

.cell-status.trending {
  color: #10B981;
}

.cell-status.ranging {
  color: #EF4444;
}

.swift-algo-trend-table-container .swift-trend-grid-row:last-child {
  border-bottom: none;
}

.swift-algo-trend-table-container .swift-trend-grid-cell {
  font-size: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  flex-shrink: 0;
}

.swift-algo-trend-table-container .swift-trend-grid-cell.timeframe-cell {
  font-weight: 700;
  color: #000000;
  font-size: 9px;
  justify-content: flex-start;
  min-width: 30px;
  flex-shrink: 0;
}

.swift-algo-trend-table-container .swift-trend-grid-cell.trend-cell,
.swift-algo-trend-table-container .swift-trend-grid-cell.strength-cell,
.swift-algo-trend-table-container .swift-trend-grid-cell.status-cell {
  flex: 1;
  min-width: 0;
}

/* Strength Indicator (Dot + Text) */
.strength-indicator {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  font-size: 7px;
  font-weight: 600;
}

.strength-dot {
  font-size: 8px;
  line-height: 1;
}

.strength-text {
  font-size: 7px;
  display: none;
}

.strength-indicator.strength-high .strength-dot {
  color: #10B981;
}

.strength-indicator.strength-high .strength-text {
  color: #10B981;
}

.strength-indicator.strength-medium .strength-dot {
  color: #F59E0B;
}

.strength-indicator.strength-medium .strength-text {
  color: #F59E0B;
}

.strength-indicator.strength-low .strength-dot {
  color: #EF4444;
}

.strength-indicator.strength-low .strength-text {
  color: #EF4444;
}

/* Status Indicator (Just Dot) */
.status-indicator {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 8px;
  line-height: 1;
}

.status-indicator.trending {
  color: #10B981;
}

.status-indicator.ranging {
  color: #EF4444;
}

/* Overall Row */
.swift-trend-grid-row.overall-row {
  background: #f5f5f5;
  border-top: 1px solid #e0e0e0;
  font-weight: 700;
  padding: 4px;
}

.swift-trend-grid-row.overall-row .timeframe-cell {
  color: #000000;
  font-weight: 800;
}

.trend-summary,
.strength-summary,
.status-summary {
  font-size: 8px;
  font-weight: 600;
  color: #000000;
}

/* Dark mode for Swift Algo Trend Table */
.dark-mode .swift-algo-trend-table-container {
  background: rgba(17, 24, 39, 0.95);
  border: 1px solid rgba(52, 211, 153, 0.5);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.6);
}

.dark-mode .swift-algo-trend-table-header {
  background: rgba(31, 41, 55, 0.9);
  border-bottom: 1px solid rgba(52, 211, 153, 0.4);
  color: #34D399;
}

.dark-mode .trend-grid-cell {
  background: rgba(31, 41, 55, 0.7);
  border-color: rgba(52, 211, 153, 0.3);
}

.dark-mode .trend-grid-cell:hover {
  background: rgba(31, 41, 55, 0.9);
  border-color: rgba(52, 211, 153, 0.5);
}

.dark-mode .trend-grid-cell.overall-cell {
  background: rgba(52, 211, 153, 0.2);
  border-color: rgba(52, 211, 153, 0.5);
}

.dark-mode .cell-timeframe {
  color: #34D399;
}

/* Dark mode trend icons - same colors, good contrast */
.dark-mode .trend-icon.bullish {
  color: #10B981;
}

/* Dark mode strength indicators */
.dark-mode .strength-indicator.strength-high .strength-dot,
.dark-mode .strength-indicator.strength-high .strength-text {
  color: #10B981;
}

.dark-mode .strength-indicator.strength-medium .strength-dot,
.dark-mode .strength-indicator.strength-medium .strength-text {
  color: #F59E0B;
}

.dark-mode .strength-indicator.strength-low .strength-dot,
.dark-mode .strength-indicator.strength-low .strength-text {
  color: #EF4444;
}

/* Dark mode status indicators */
.dark-mode .status-indicator.trending {
  color: #10B981;
}

.dark-mode .status-indicator.ranging {
  color: #EF4444;
}

/* Dark mode overall row */
.dark-mode .swift-trend-grid-row.overall-row {
  background: #202020;
  border-top: 2px solid #303030;
}

.dark-mode .swift-trend-grid-row.overall-row .timeframe-cell {
  color: #F7F7F7;
}

.dark-mode .trend-summary,
.dark-mode .strength-summary,
.dark-mode .status-summary {
  color: #F7F7F7;
}

.dark-mode .swift-algo-trend-table-container .swift-trend-grid-row:hover {
  background: rgba(255, 255, 255, 0.04);
}

/* Small Size Styles */
.swift-algo-trend-table-container.size-small .swift-algo-trend-table-header {
  padding: 4px;
  font-size: 8px;
}

.swift-algo-trend-table-container.size-small .swift-algo-trend-grid {
  gap: 3px;
  padding: 3px;
}

.swift-algo-trend-table-container.size-small .trend-grid-cell {
  padding: 3px;
}

.swift-algo-trend-table-container.size-small .cell-timeframe {
  font-size: 8px;
  margin-bottom: 2px;
}

.swift-algo-trend-table-container.size-small .cell-indicators {
  gap: 4px;
}

.swift-algo-trend-table-container.size-small .cell-trend {
  font-size: 12px;
}

.swift-algo-trend-table-container.size-small .cell-strength {
  font-size: 8px;
}

.swift-algo-trend-table-container.size-small .cell-status {
  font-size: 8px;
}

.swift-algo-trend-table-container-old-small .strength-indicator {
  gap: 4px;
  font-size: 8px;
}

.swift-algo-trend-table-container.size-small .strength-dot {
  font-size: 9px;
}

.swift-algo-trend-table-container.size-small .strength-text {
  font-size: 8px;
}

.swift-algo-trend-table-container.size-small .status-indicator {
  font-size: 12px;
}

.swift-algo-trend-table-container.size-small .trend-summary,
.swift-algo-trend-table-container.size-small .strength-summary,
.swift-algo-trend-table-container.size-small .status-summary {
  font-size: 7px;
}

/* Old styles for modal - keep for compatibility */
.swift-algo-trend-table {
  width: 100%;
  font-family: var(--font-ui);
  padding: 16px;
  background: transparent;
}

.swift-trend-table-row {
  display: grid;
  grid-template-columns: 70px 60px 90px 60px;
  gap: 8px;
  padding: 10px 8px;
  background: transparent;
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
  align-items: center;
  transition: background 0.2s ease;
}

.swift-trend-table-row:hover {
  background: rgba(0, 0, 0, 0.02);
}

.swift-trend-table-header-row {
  font-weight: 600;
  font-size: 9px;
  color: #48484A;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  border-bottom: 2px solid rgba(0, 0, 0, 0.1);
  padding: 6px 8px 10px;
  margin-bottom: 4px;
}

.swift-trend-table-header-row:hover {
  background: transparent;
}

.swift-trend-table-cell {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 6px;
  font-size: 12px;
  color: #1D1D1F;
  font-weight: 500;
}

.swift-timeframe-cell {
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.3px;
}

.swift-strength-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}

.swift-strength-text {
  font-size: 11px;
  font-weight: 600;
  text-transform: capitalize;
}

.swift-ranging-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  flex-shrink: 0;
}

.swift-overall-row {
  background: rgba(0, 0, 0, 0.03);
  font-weight: 600;
  border-top: 2px solid rgba(0, 0, 0, 0.1);
  margin-top: 4px;
}

.swift-overall-row:hover {
  background: rgba(0, 0, 0, 0.05);
}

.swift-overall-indicator {
  font-size: 16px;
}

/* Dark mode styles for Swift Algo Trend Table */
.dark-mode .swift-trend-table-row {
  border-bottom: 1px solid var(--bk-border);
}

.dark-mode .swift-trend-table-row:hover {
  background: rgba(255, 255, 255, 0.04);
}

.dark-mode .swift-trend-table-header-row {
  color: var(--bk-text-2);
  border-bottom: 2px solid var(--bk-border);
}

.dark-mode .swift-trend-table-cell {
  color: #F5F5F7;
}

.dark-mode .swift-overall-row {
  background: rgba(255, 255, 255, 0.03);
  border-top: 2px solid var(--bk-border);
}

.dark-mode .swift-overall-row:hover {
  background: rgba(255, 255, 255, 0.05);
}

/* ========================================
   TRADING PANEL BUTTON
   ======================================== */
/* This carried a blue fill, a blue border and blue text, which made it the one lit
   button in a row of plain ones. It only ever showed in light mode: .dark-mode
   .indicators-btn is two classes deep and quietly won in dark, so the button looked
   normal there and highlighted on white - the same button, two different designs.
   The colours are gone and it takes the row's own, from .indicators-btn. The geometry
   stays: it is deliberately shorter than its neighbours, and the navbar's narrow
   breakpoint sizes it from this rule. */
.trading-panel-btn {
  height: 28px;
  padding: 0 12px;
  border: none;
  border-radius: 8px;
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  display: flex;
  align-items: center;
  gap: 6px;
}

.trading-panel-btn:active {
  transform: translateY(0);
}

/* ========================================
   CHATBOT MODAL
   ======================================== */
/* ========================================
   AI ASSISTANT SIDE PANEL
   ========================================
   The dock is a flex child of .chart-layout, so the width set on it is taken out of the
   chart rather than laid over it. The panel inside keeps the .chatbot-modal class so all
   the existing message, input and dark-mode styling still applies - only the positioning
   is overridden below. .chatbot-modal is shared with the AI Chart Painter, which is why
   none of its own rules are touched. */
.ai-panel-dock {
  position: relative;
  flex: 0 0 auto;
  display: flex;
  align-items: stretch;
  min-width: 0;
  height: 100%;
  /* No padding: the panel meets the bar above it, the strip below it and the window's
     right edge with nothing between. The 8px this held showed as a gap on three sides. */
  padding: 0;
  /* The ground behind the panel, which slides in over 0.24s - left unpainted the dock
     showed as a black column for the length of that animation. The panel's own colour,
     so there is nothing to see either way. */
  background: var(--bk-shell);
  box-sizing: border-box;
}

/* Outranks the plain `.dark-mode { background: #000 }`, which the dock picks up from its
   own class. */
.ai-panel-dock.dark-mode {
  background: #151619;
}

/* Grab strip on the panel's left edge. Positioned over the gap rather than taking flex
   space of its own, so the chart sits the same 8px from the panel as it does from the
   drawing toolbar - taking space here made that side visibly wider than the other. */
/* Centred on the 8px gap, not hung off the panel's edge: left is -(width/2 + gap/2), so
   the visible line lands exactly between the chart and the panel. Wider than the gap so
   there is still something to grab, overhanging by 2px on each side. */
.ai-panel-resizer {
  position: absolute;
  left: -10px;
  top: 8px;
  bottom: 8px;
  width: 12px;
  cursor: col-resize;
  z-index: 2;
  border-radius: 3px;
  transition: background 0.15s ease;
}

/* This handle belongs to the assistant, so it carries the assistant's colour -
   the purple of the logo mark at the top of the panel - rather than the system
   blue every other control uses. --brand rather than --ai-accent because the
   resizer sits in the dock, outside .chatbot-modal where that alias is defined. */
.ai-panel-resizer::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 3px;
  height: 44px;
  border-radius: 2px;
  background: rgba(var(--brand-rgb), 0.45);
  transition: background 0.15s ease, height 0.15s ease;
}

.ai-panel-resizer:hover::after,
.ai-panel-resizer.dragging::after {
  background: var(--brand);
  height: 72px;
}

.dark-mode .ai-panel-resizer::after {
  background: rgba(var(--brand-rgb), 0.6);
}

.dark-mode .ai-panel-resizer:hover::after,
.dark-mode .ai-panel-resizer.dragging::after {
  background: var(--brand);
}

/* Turns the floating popup into a full-height column filling the dock.
   The surface treatment is deliberately the chart wrapper's, not the popup's: the same
   border, the same soft shadow, the same radius. The popup's 0 20px 60px shadow exists to
   lift a floating box off the page, and docked beside the chart that reads as the panel
   hovering above the layout rather than sitting beside it. The heavy backdrop blur goes
   too - the panel is effectively opaque, so it was only costing paint work. */
.chatbot-modal.ai-side-panel {
  /* Aus dem Popup-Band heraus. .chatbot-modal traegt z-index: 10000, weil es als
     schwebendes Fenster ueber allem liegen muss - angedockt ist es aber ein Flex-Nachbar
     des Charts und muss ueber gar nichts liegen. Mit 10000 stand es auch ueber jedem
     .modal-overlay (1500), und wenn der Chart Scan aufging, wurde alles abgedunkelt
     ausser dem Assistenten. Im Dunkelmodus faellt das kaum auf, im Hellmodus steht das
     ungedimmte weisse Panel neben dem abgedunkelten Rest.

     20 statt eines groesseren Werts: der Chart liegt auf 1, die Werkzeugschiene auf 10,
     die Navbar auf 100 - und alles davon ist ohnehin daneben, nicht darunter. Was zaehlt,
     ist der Abstand nach oben zu 1500.

     Auf dem Telefon gilt das nicht: dort ist der Assistent eine schwebende Karte mit
     eigenem Overlay und braucht den hohen Wert zurueck - siehe den Telefonblock. */
  z-index: 20;
  position: relative;
  left: auto;
  bottom: auto;
  width: auto;
  flex: 1 1 auto;
  min-width: 0;
  height: 100%;
  max-height: none;
  /* Enters from the right. The dock takes its width at once, so the chart resizes once
     rather than on every frame of this, and the panel travels across the space already
     made for it. */
  animation: aiPanelIn 0.24s cubic-bezier(0.33, 1, 0.68, 1);
  /* The shell colour rather than a surface of its own: the panel closes the frame that the
     navbar, the tool rail and the strip open, so it stands on the same ground they do.
     The shell colour itself, not --shell-surface: the assistant is deliberately outside
     the Design elements setting, so it holds this ground whatever the bars are painted. */
  background: var(--bk-shell);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  /* Square, and edged only where it meets the chart. The other three sides sit against
     the navbar, the strip and the window, each of which draws its own edge - a border or
     a rounded corner there would be a second line over a straight one. */
  border: 0;
  border-left: 1px solid rgba(142, 142, 147, 0.1);
  border-radius: 0;
  box-shadow: none;
}

/* Matches .dark-mode .chart-wrapper, which drops the shadow entirely and relies on a
   border against the near-black background. */
.chatbot-modal.ai-side-panel.dark-mode {
  /* #151619: the ground the three bars sit on in dark mode - see the shell group near
     the end of this file. Written out here for the reason it is written out there, that
     --bk-shell also colours journal and panel surfaces which stay down at #050505. */
  background: #151619;
  border: 0;
  border-left: 1px solid var(--bk-border);
  box-shadow: none;
}

/* The dark-panel group near the end of this file lists `.dark-mode .chatbot-modal`, which
   matches this at the same specificity but comes later - so it was putting the radius back
   and drawing a 1px ring on all four sides through an inset shadow, over three edges that
   are already drawn by the navbar, the strip and the window. Stated here at a specificity
   it cannot outrank. */
.dark-mode .chatbot-modal.ai-side-panel {
  border-radius: 0;
  box-shadow: none;
  border: 0;
  border-left: 1px solid var(--bk-border);
}

.chatbot-modal.ai-side-panel .chatbot-messages {
  flex: 1 1 auto;
  min-height: 0;
  /* The popup capped this at 450px; in a full-height column it should just fill, or the
     input floats in the middle with dead space beneath it. */
  max-height: none;
  padding: 18px 16px;
  gap: 18px;
  scrollbar-width: thin;
}

/* ---- header ---------------------------------------------------------------- */
.ai-side-panel .chatbot-header {
  padding: 12px 12px 12px 14px;
  align-items: center;
}

.ai-side-panel .chatbot-title {
  gap: 10px;
  align-items: center;
}

/* The box the brand mark sits in: geometry only, no fill of its own. It was plain white
   here and plain black in the dark theme - invisible while the panel was #FBFBFD/#050505,
   and a square drawn around the logo the moment the panel moved up to the shell colour.
   Transparent rather than restating that colour, so there is no third value to keep in step
   the next time the panel moves. The mark still paints itself from the logo's gradient, so
   nothing it is nested inside can tint it either. */
.ai-side-panel .ai-avatar {
  width: 26px;
  height: 26px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  flex: 0 0 auto;
}

.ai-side-panel .ai-title-text {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
  min-width: 0;
}

.ai-side-panel .chatbot-title h3 {
  font-size: 14px;
  font-weight: 600;
  margin: 0;
}

.ai-side-panel .ai-subtitle {
  font-size: 11px;
  color: #86868B;
  font-family: var(--font-mono);
  letter-spacing: 0.2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ai-side-panel .ai-header-actions {
  display: flex;
  align-items: center;
  gap: 2px;
}

.ai-side-panel .ai-icon-btn {
  width: 28px;
  height: 28px;
  border: none;
  background: transparent;
  color: #86868B;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.ai-side-panel .ai-icon-btn:hover {
  background: rgba(0, 0, 0, 0.06);
  color: #1D1D1F;
}

.ai-side-panel.dark-mode .ai-icon-btn:hover {
  background: rgba(255, 255, 255, 0.1);
  color: #F5F5F7;
}

/* ---- empty state ----------------------------------------------------------- */
/* ── saved conversations ──────────────────────────────────────────────────
   The list stands in for the transcript in the same scroll area, so it inherits its
   padding and scrolling and only has to describe the rows. */
.ai-side-panel .ai-history {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.ai-side-panel .ai-history-empty {
  margin: 0;
  padding: 8px 2px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--bk-text-2);
}

.ai-side-panel .ai-history-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 10px;
  border-radius: 10px;
  cursor: pointer;
  transition: background 0.12s ease;
}

.ai-side-panel .ai-history-row:hover {
  background: rgba(120, 120, 128, 0.10);
}

.chatbot-modal.ai-side-panel.dark-mode .ai-history-row:hover {
  background: rgba(255, 255, 255, 0.06);
}

/* The thread currently in the panel, so returning to the list shows where you are. */
.ai-side-panel .ai-history-row.current {
  background: rgba(var(--ai-accent-rgb), 0.10);
}

.ai-side-panel .ai-history-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  flex: 1 1 auto;
}

/* One line only. A title is the first thing the user asked, which can be a paragraph. */
.ai-side-panel .ai-history-title {
  font-size: 13px;
  font-weight: 500;
  color: var(--bk-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ai-side-panel .ai-history-meta {
  font-size: 11px;
  color: var(--bk-text-3);
  font-family: var(--font-mono);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Only on the row it belongs to, so a long list is not a wall of bins. */
.ai-side-panel .ai-history-delete {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 7px;
  background: transparent;
  color: var(--bk-text-3);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s ease, color 0.12s ease, background 0.12s ease;
}

.ai-side-panel .ai-history-row:hover .ai-history-delete,
.ai-side-panel .ai-history-delete:focus-visible {
  opacity: 1;
}

.ai-side-panel .ai-history-delete:hover {
  color: var(--bk-neg);
  background: rgba(217, 58, 68, 0.12);
}

/* A pointer is not the only way in - on a touch screen there is no hover to reveal it. */
@media (hover: none) {
  .ai-side-panel .ai-history-delete {
    opacity: 1;
  }
}

.ai-side-panel .ai-welcome {
  text-align: left;
  padding: 8px 2px;
  margin-top: auto;
  margin-bottom: auto;
}

.ai-side-panel .ai-welcome h4 {
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -0.015em;
  margin: 0 0 6px 0;
}

.ai-side-panel .ai-welcome p {
  font-size: 13px;
  line-height: 1.55;
  margin: 0 0 18px 0;
  color: var(--bk-text-2);
}

.ai-side-panel .ai-suggestions {
  display: flex;
  flex-direction: column;
  gap: 7px;
}

/* A starter is a job the assistant will go and do, so it carries a name and a
   line saying what that job is. The icon sits in its own tinted tile: at 15px a
   bare glyph beside two lines of text has no weight and the row reads as a
   paragraph with a decoration rather than as a control. */
.ai-side-panel .ai-suggestion {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 10px 11px;
  border-radius: var(--bk-r-control);
  border: 1px solid var(--bk-border);
  background: var(--bk-panel);
  color: var(--bk-text);
  font-family: var(--font-ui);
  text-align: left;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease, transform 0.12s ease;
}

.ai-side-panel .ai-suggestion-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  border-radius: var(--bk-r-icon);
  background: rgba(var(--ai-accent-rgb), 0.1);
  color: var(--ai-accent);
  transition: background 0.15s ease;
}

/* The glyph was sitting flush to the top of the tile with all of the slack
   below it, despite the tile computing as a centred flex box. auto margins
   centre a flex item on both axes on their own, so this holds whatever the
   alignment resolves to. */
.ai-side-panel .ai-suggestion-icon svg {
  display: block;
  margin: auto;
}

.ai-side-panel .ai-suggestion-text {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  flex: 1 1 auto;
}

.ai-side-panel .ai-suggestion-label {
  font-size: 13px;
  font-weight: 550;
  line-height: 1.3;
  letter-spacing: -0.005em;
}

/* The hint explains, so it must not compete with the name it explains. One step
   down in size and two in colour is enough; it wraps rather than truncating,
   because a clipped explanation explains nothing. */
.ai-side-panel .ai-suggestion-hint {
  font-size: 11.5px;
  line-height: 1.35;
  color: var(--bk-text-3);
}

/* Present but quiet until the row is under the pointer - the affordance should
   not add four arrows of noise to a panel at rest. */
.ai-side-panel .ai-suggestion-go {
  flex: 0 0 auto;
  color: var(--bk-text-3);
  opacity: 0;
  transform: translateX(-3px);
  transition: opacity 0.15s ease, transform 0.15s ease;
}

.ai-side-panel .ai-suggestion:hover:not(:disabled) {
  border-color: rgba(var(--ai-accent-rgb), 0.45);
  background: rgba(var(--ai-accent-rgb), 0.05);
}

.ai-side-panel .ai-suggestion:hover:not(:disabled) .ai-suggestion-icon {
  background: rgba(var(--ai-accent-rgb), 0.17);
}

.ai-side-panel .ai-suggestion:hover:not(:disabled) .ai-suggestion-go {
  opacity: 1;
  transform: none;
  color: var(--ai-accent);
}

.ai-side-panel .ai-suggestion:active:not(:disabled) {
  transform: scale(0.99);
}

.ai-side-panel .ai-suggestion:focus-visible {
  outline: none;
  border-color: var(--ai-accent);
  box-shadow: 0 0 0 3px rgba(var(--ai-accent-rgb), 0.22);
}

.ai-side-panel .ai-suggestion:disabled {
  opacity: 0.5;
  cursor: default;
}

/* The starters are cards on the panel, and they have to read as sitting ON it. They were
   --bk-elevated, #101010, which was a step above the #050505 the panel used to be - and
   then the panel moved up to #151619 and left them underneath it. At 1.05 against their own
   ground, in the wrong direction, they read as four holes punched in the surface rather
   than as four things to press.

   #202124 is one clear step above the panel, 1.12, and it carries the same cool cast: the
   panel is R21 G22 B25, this is R32 G33 B36, the same +1/+3 tilt rather than a flat grey
   that would look borrowed from somewhere else. The label holds 15:1 on it.

   Written out rather than taken from a token for the same reason the panel is: the card
   tokens also colour journal surfaces, which are still on the old scale and should stay
   there. The border is lifted with it - var(--bk-border) measured 1.04 against this fill,
   which is no edge at all. */
.ai-side-panel.dark-mode .ai-suggestion {
  border-color: #2A2C31;
  background: #202124;
  color: var(--bk-text);
}

/* The glyph was the brand violet on an 18% wash of the same violet - #4C29E9 on what
   composites to #282247 - which measures 1.99:1. That was never an icon too small or too
   thin; it was an icon almost exactly the colour of the thing behind it.

   Both ends moved, and they are independent of each other. The chip carries the accent at
   42% rather than the 18% it started on, which composites to #322477 - purple you can
   actually name, 1.27 against the card. The glyph is plain #FFFFFF: not --bk-text, which
   is the #F7F7F7 the labels use, but the real thing, so the mark is the brightest object
   on the tile rather than merely as bright as the words.

   White holds 12.69:1 on that chip. Raising the wash costs a little of it - the chip is
   lighter than it was, so there is less room above it - and that trade is the point: the
   badge should read as violet, and white is the one glyph colour that survives the wash
   getting there. */
.ai-side-panel.dark-mode .ai-suggestion-icon {
  background: rgba(var(--ai-accent-rgb), 0.42);
  color: #FFFFFF;
}

.ai-side-panel.dark-mode .ai-suggestion:hover:not(:disabled) {
  border-color: rgba(var(--ai-accent-rgb), 0.55);
  background: rgba(var(--ai-accent-rgb), 0.11);
}

/* Hover deepens the wash and leaves the glyph alone: it is already pure white, so there is
   nowhere left for it to go. */
.ai-side-panel.dark-mode .ai-suggestion:hover:not(:disabled) .ai-suggestion-icon {
  background: rgba(var(--ai-accent-rgb), 0.55);
}

/* No hover on a touch screen, so the arrow would never arrive. Show it. */
@media (hover: none) {
  .ai-side-panel .ai-suggestion-go {
    opacity: 1;
    transform: none;
  }
}

/* ---- messages -------------------------------------------------------------- */
/* The assistant reads as plain prose rather than a bubble - long analysis in a
   bubble is hard to scan - while the user's own turn keeps one so the thread is
   still easy to follow. */
.ai-side-panel .chat-message.assistant .message-content {
  background: transparent;
  padding: 0;
  font-size: 13.5px;
  line-height: 1.6;
}

/* The dark theme gives assistant replies a grey bubble. That rule carries more classes
   than the one above and sits later in this file, so undoing it needs .chatbot-modal in
   the selector too. */
.chatbot-modal.ai-side-panel.dark-mode .chat-message.assistant .message-content {
  background: transparent;
  padding: 0;
}

.ai-side-panel .chat-message.user {
  justify-content: flex-end;
}

.ai-side-panel .chat-message.user .message-content {
  background: var(--ai-accent);
  color: #fff;
  border-radius: 14px 14px 4px 14px;
  padding: 9px 13px;
  font-size: 13.5px;
  line-height: 1.5;
  max-width: 85%;
}

/* Same specificity problem as the assistant bubble above. */
.chatbot-modal.ai-side-panel.dark-mode .chat-message.user .message-content {
  background: var(--ai-accent);
  color: #F7F7F7;
}

/* ---- composer -------------------------------------------------------------- */
.ai-side-panel .chatbot-input {
  flex-direction: column;
  gap: 6px;
  padding: 12px 14px 14px;
}

.ai-side-panel .ai-composer {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  width: 100%;
  padding: 8px 8px 8px 12px;
  border-radius: 14px;
  border: 1px solid rgba(0, 0, 0, 0.1);
  background: rgba(0, 0, 0, 0.02);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.ai-side-panel .ai-composer:focus-within {
  border-color: rgba(var(--ai-accent-rgb), 0.55);
  box-shadow: 0 0 0 3px rgba(var(--ai-accent-rgb), 0.12);
}

.ai-side-panel .ai-composer textarea {
  flex: 1 1 auto;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  resize: none;
  font-family: var(--font-ui);
  font-size: 13.5px;
  line-height: 1.5;
  color: #1D1D1F;
  padding: 4px 0;
  max-height: 160px;
}

.ai-side-panel .ai-composer textarea::placeholder {
  color: #A1A1A6;
}

.ai-side-panel .ai-send-btn {
  width: 30px;
  height: 30px;
  flex: 0 0 auto;
  border: none;
  border-radius: 8px;
  background: var(--ai-accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.15s ease, opacity 0.15s ease;
}

.ai-side-panel .ai-send-btn:hover:not(:disabled) {
  background: var(--ai-accent-hover);
}

.ai-side-panel .ai-send-btn:disabled {
  opacity: 0.4;
  cursor: default;
}

.ai-side-panel .ai-composer-hint {
  font-size: 10.5px;
  color: #A1A1A6;
  padding-left: 4px;
}

.ai-side-panel.dark-mode .ai-composer {
  border-color: var(--bk-border);
  background: rgba(255, 255, 255, 0.04);
}

.ai-side-panel.dark-mode .ai-composer textarea {
  color: #F5F5F7;
}

.ai-side-panel.dark-mode .ai-send-btn {
  background: var(--ai-accent);
}

.ai-side-panel.dark-mode .ai-send-btn:hover:not(:disabled) {
  background: var(--ai-accent);
}

.chatbot-modal {
  /* The assistant's accent, taken from the logo rather than the system blue the rest of
     the app uses. --ai-accent is the midpoint of the gradient in public/logo.svg, standing
     in for it wherever a flat colour is needed; --ai-accent-hover is that gradient's dark
     stop, for pressed and hover states. The rgb triple exists because the washes here are
     rgba() and a hex cannot be given an alpha inside one. */
  --ai-accent: var(--brand);
  --ai-accent-hover: var(--brand-hover);
  --ai-accent-rgb: var(--brand-rgb);
  position: absolute;
  left: 52px;
  bottom: 54px;
  width: 400px;
  max-height: 600px;
  background: rgba(255, 255, 255, 0.98);
  backdrop-filter: blur(80px) saturate(200%);
  -webkit-backdrop-filter: blur(80px) saturate(200%);
  border-radius: 16px;
  border: 1px solid rgba(0, 0, 0, 0.08);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15), 0 0 1px rgba(0, 0, 0, 0.2);
  display: flex;
  flex-direction: column;
  z-index: 10000;
  overflow: hidden;
  animation: slideInLeft 0.3s ease-out;
}

@keyframes slideInLeft {
  from {
    opacity: 0;
    transform: translateX(-20px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

.chatbot-modal.dark-mode {
  background: rgba(30, 30, 30, 0.98);
  border-color: var(--bk-border);
}

.chatbot-header {
  padding: 16px 20px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
}

.chatbot-modal.dark-mode .chatbot-header {
  border-bottom-color: var(--bk-border);
}

.chatbot-title {
  display: flex;
  align-items: center;
  gap: 10px;
}

.chatbot-title svg {
  color: var(--ai-accent);
}

.chatbot-modal.dark-mode .chatbot-title svg {
  color: var(--ai-accent);
}

.chatbot-title h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: #1D1D1F;
}

.chatbot-modal.dark-mode .chatbot-title h3 {
  color: #F5F5F7;
}

.chatbot-header .close-btn {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  border: none;
  background: rgba(0, 0, 0, 0.05);
  color: #86868B;
  font-size: 20px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s ease;
}

.chatbot-header .close-btn:hover {
  background: rgba(0, 0, 0, 0.1);
  color: #1D1D1F;
}

.chatbot-modal.dark-mode .chatbot-header .close-btn {
  background: rgba(255, 255, 255, 0.1);
  color: var(--bk-text-2);
}

.chatbot-modal.dark-mode .chatbot-header .close-btn:hover {
  background: rgba(255, 255, 255, 0.15);
  color: #F5F5F7;
}

.chatbot-messages {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-height: 300px;
  max-height: 450px;
}

.chatbot-welcome {
  text-align: center;
  padding: 40px 20px;
  color: #86868B;
}

.chatbot-welcome svg {
  opacity: 0.3;
  margin-bottom: 16px;
}

.chatbot-welcome h4 {
  font-size: 18px;
  font-weight: 600;
  color: #1D1D1F;
  margin: 0 0 12px 0;
}

.chatbot-modal.dark-mode .chatbot-welcome h4 {
  color: #F5F5F7;
}

.chatbot-welcome p {
  margin: 8px 0;
  font-size: 14px;
  line-height: 1.5;
}

.chatbot-hint {
  font-size: 13px !important;
  opacity: 0.7;
  margin-top: 16px !important;
}

.chat-message {
  display: flex;
  gap: 10px;
  animation: fadeIn 0.3s ease-out;
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.chat-message.user {
  flex-direction: row-reverse;
}

.message-content {
  max-width: 75%;
  padding: 10px 14px;
  border-radius: 14px;
  font-size: 14px;
  line-height: 1.5;
  word-wrap: break-word;
}

.chat-message.user .message-content {
  background: #007AFF;
  color: white;
  border-bottom-right-radius: 4px;
}

.chatbot-modal.dark-mode .chat-message.user .message-content {
  background: var(--ai-accent);
}

.chat-message.assistant .message-content {
  background: rgba(0, 0, 0, 0.05);
  color: #1D1D1F;
  border-bottom-left-radius: 4px;
}

.chatbot-modal.dark-mode .chat-message.assistant .message-content {
  background: rgba(255, 255, 255, 0.1);
  color: #F5F5F7;
}

.typing-indicator {
  display: flex;
  gap: 4px;
  padding: 12px 14px;
}

.typing-indicator span {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #86868B;
  animation: typingBounce 1.4s infinite;
}

.typing-indicator span:nth-child(2) {
  animation-delay: 0.2s;
}

.typing-indicator span:nth-child(3) {
  animation-delay: 0.4s;
}

@keyframes typingBounce {
  0%, 60%, 100% {
    transform: translateY(0);
    opacity: 0.7;
  }
  30% {
    transform: translateY(-10px);
    opacity: 1;
  }
}

.chatbot-input {
  padding: 16px 20px;
  border-top: 1px solid rgba(0, 0, 0, 0.08);
  display: flex;
  gap: 12px;
  flex-shrink: 0;
}

.chatbot-modal.dark-mode .chatbot-input {
  border-top-color: var(--bk-border);
}

.chatbot-input input {
  flex: 1;
  padding: 10px 14px;
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 20px;
  font-size: 14px;
  outline: none;
  background: rgba(0, 0, 0, 0.02);
  color: #1D1D1F;
  transition: all 0.2s ease;
}

.chatbot-input input:focus {
  border-color: var(--ai-accent);
  background: white;
}

.chatbot-modal.dark-mode .chatbot-input input {
  background: rgba(255, 255, 255, 0.05);
  border-color: var(--bk-border);
  color: #F5F5F7;
}

.chatbot-modal.dark-mode .chatbot-input input:focus {
  border-color: var(--ai-accent);
  background: rgba(255, 255, 255, 0.08);
}

.chatbot-input input::placeholder {
  color: #86868B;
}

.chatbot-input button {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: none;
  background: var(--ai-accent);
  color: white;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s ease;
  flex-shrink: 0;
}

.chatbot-input button:hover:not(:disabled) {
  background: var(--ai-accent-hover);
  ;
}

.chatbot-input button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.chatbot-modal.dark-mode .chatbot-input button {
  background: var(--ai-accent);
}

.chatbot-modal.dark-mode .chatbot-input button:hover:not(:disabled) {
  background: var(--ai-accent-hover);
}

/* ========================================
   AI PAINTER
   A tool panel rather than a form: a preset rail across the top, a grid of layer tiles
   that each show a miniature of the mark they draw, and a fixed action bar. The panel is
   a flex column so only the grid scrolls - the presets and the paint button stay put no
   matter how far down the list you are.
   Everything below reads its colours from the token block, so the dark theme is a token
   swap and not a second stylesheet.

   The token block is shared with the AI Chart Scanner. The two panels do different jobs -
   one is a set of controls, the other a readout - so their layouts differ, but they are
   the same surface, the same inks and the same chrome, and there is one place to change
   that rather than two drifting copies.
   ======================================== */
.chart-painter-modal,
.chart-scanner-modal {
  --pnt-surface: #FFFFFF;
  --pnt-raise: #F4F5F7;
  --pnt-screen: #FAFBFC;
  --pnt-line: rgba(0, 0, 0, 0.08);
  --pnt-line-soft: rgba(0, 0, 0, 0.05);
  --pnt-ink: #0B0B0F;
  /* Both muted inks are set from the tile fill they sit on rather than from the panel: the blurb is 11.5px, so it needs the 4.5:1 floor against #F4F5F7, not against white. */
  --pnt-ink-2: #55555F;
  --pnt-ink-3: #6B6B76;
  --pnt-grid: rgba(0, 0, 0, 0.045);
  --pnt-up: #34C759;
  --pnt-down: #FF3B30;
  /* The logo's purple, not the system blue. Both panels carry the brand: they are the
     two AI features, and the accent is the only colour in them that is not either a
     surface or a direction. Everything that moves - the scanner's pulse and sweep, the
     painter's armed tiles and its apply button - is drawn from these two, so the
     animations are untouched and only the hue changes.
     Not restated per theme: the brand is one colour in both (see --brand in index.css). */
  --pnt-accent: var(--brand);
  --pnt-accent-2: var(--brand-hover);
  /* A gold star is all but invisible on a light tile - the state that is supposed to
     stand out reads weakest. Light mode takes a deep amber instead. It is set against an
     armed tile, not a resting one: arming tints the tile with the layer's own colour and
     lifts the background, and measured across all ten tints that is the worst case.
     Dark mode keeps the brighter gold, which already sits above 8:1. */
  --pnt-star: #B06800;
}

.chart-painter-modal {
  width: 460px !important;
  max-height: 700px !important;
  background: var(--pnt-surface);
  border: 1px solid var(--pnt-line);
  border-radius: 20px;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.18), 0 2px 6px rgba(0, 0, 0, 0.06);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: pnt-rise 0.34s cubic-bezier(0.22, 1, 0.36, 1);
}

.chart-painter-modal.dark-mode,
.chart-scanner-modal.dark-mode {
  --pnt-surface: #131318;
  --pnt-raise: #1C1C23;
  --pnt-screen: #0F0F14;
  /* Edges carried too little weight at 0.09 - a resting tile had no discernible
     outline, so the grid read as flat rather than as ten cards. */
  --pnt-line: rgba(255, 255, 255, 0.13);
  --pnt-line-soft: rgba(255, 255, 255, 0.08);
  --pnt-ink: #F5F5F7;
  --pnt-ink-2: #9A9AA6;
  --pnt-ink-3: #8E8E9A;
  --pnt-grid: rgba(255, 255, 255, 0.05);
  --pnt-star: #FFB800;
}

/* .chatbot-modal.dark-mode carries two classes and so out-specifies the single-class
   block above, which is why the panel kept the shared dialog's #1E1E1E instead of its
   own surface. Restated here at matching specificity. */
.chart-painter-modal.dark-mode {
  background: var(--pnt-surface);
  border-color: var(--pnt-line);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.04);
}

/* Animates the individual translate/scale properties rather than `transform`, because a
   keyframe on `transform` replaces the whole property - and the scanner centres itself
   with transform: translate(-50%, -50%). Animating `transform` therefore dropped that
   centring for the length of the animation, so the panel opened with its top-left corner
   at the middle of the screen and snapped into place when the animation ended.
   translate/scale compose with transform instead of overriding it, so the centring holds
   the whole way through. It also means the painter animates on a phone, where the
   responsive rule pins it with transform: ... !important and !important beats a
   keyframe. */
@keyframes pnt-rise {
  from { opacity: 0; translate: 0 10px; scale: 0.97; }
  to   { opacity: 1; translate: 0 0; scale: 1; }
}

/* ---- Title bar ---------------------------------------------------------- */
.pnt-top {
  position: relative;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 16px 14px;
  border-bottom: 1px solid var(--pnt-line-soft);
  overflow: hidden;
}

.pnt-brand {
  display: flex;
  align-items: center;
  gap: 11px;
  min-width: 0;
}

.pnt-brand-mark {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  border-radius: 11px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #FFFFFF;
  background: linear-gradient(140deg, var(--pnt-accent), var(--pnt-accent-2));
}

.pnt-brand-text {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.pnt-brand-text h3 {
  margin: 0;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--pnt-ink);
}

.pnt-brand-sub {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--pnt-ink-2);
}

.pnt-close {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border: none;
  border-radius: 50%;
  background: var(--pnt-raise);
  color: var(--pnt-ink-2);
  font-size: 19px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.18s ease, color 0.18s ease, transform 0.18s ease;
}

.pnt-close:hover {
  background: var(--pnt-down);
  color: #FFFFFF;
  ;
}

/* ---- Preset rail -------------------------------------------------------- */
/* Four taps that cover what people actually paint. Kept above the scroll area on
   purpose: it is the fast path, and it should never scroll out of reach. */
.pnt-presets {
  flex-shrink: 0;
  display: flex;
  gap: 7px;
  padding: 12px 16px;
  overflow-x: auto;
  scrollbar-width: none;
  border-bottom: 1px solid var(--pnt-line-soft);
}

.pnt-presets::-webkit-scrollbar { display: none; }

.pnt-preset {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 12px 7px 9px;
  border: 1px solid var(--pnt-line);
  border-radius: 999px;
  background: var(--pnt-raise);
  color: var(--pnt-ink);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}

.pnt-preset:hover {
  border-color: color-mix(in srgb, var(--pnt-accent) 45%, transparent);
  ;
}

.pnt-preset.is-on {
  background: linear-gradient(135deg, var(--pnt-accent), var(--pnt-accent-2));
  border-color: transparent;
  color: #FFFFFF;
}

/* The star carries the chip's identity, the dots preview the tints behind it. */
.pnt-preset-star {
  width: 11px;
  height: 11px;
  flex-shrink: 0;
  margin-right: -1px;
  fill: var(--pnt-star);
}

.pnt-preset.is-on .pnt-preset-star {
  fill: #FFFFFF;
}

.pnt-preset-dots {
  display: inline-flex;
  align-items: center;
}

.pnt-preset-dots i {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: -3px;
  border: 1.5px solid var(--pnt-raise);
  transition: border-color 0.2s ease;
}

.pnt-preset.is-on .pnt-preset-dots i {
  border-color: rgba(255, 255, 255, 0.9);
}

/* ---- Scrolling body ----------------------------------------------------- */
.chart-painter-content {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.pnt-group-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
  padding-left: 2px;
}

.pnt-group-head h4 {
  margin: 0;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--pnt-ink);
}

.pnt-group-head span {
  font-size: 11.5px;
  font-weight: 500;
  color: var(--pnt-ink-3);
  letter-spacing: -0.01em;
}

.pnt-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  align-items: start;
}

/* ---- Layer tile --------------------------------------------------------- */
.pnt-tile {
  --pnt-tint: var(--pnt-accent);
  position: relative;
  border: 1.5px solid var(--pnt-line);
  border-radius: 15px;
  background: var(--pnt-raise);
  overflow: hidden;
  transition: border-color 0.22s ease, box-shadow 0.22s ease, transform 0.22s ease;
}

.pnt-tile:hover {
  ;
  border-color: color-mix(in srgb, var(--pnt-tint) 45%, transparent);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
}

/* Dark mode lifts the tile off the panel with a highlight along its top edge rather than
   a lighter fill: the fill is what every contrast figure in this panel is measured
   against, and it fades out well above the name and blurb. */
/* Der Farbknopf einer Ebene, seit die Zahlenregler ins Zahnrad gewandert sind der einzige
   Regler auf der Kachel. Hoehe und Radius bleiben trotzdem die der Stepper-Felder (24px,
   Radius 7): dieselben Felder stehen jetzt in der Einstellungsansicht, und ein Knopf, der
   dort anders aussieht als hier, laesst die beiden Ansichten auseinanderfallen.
   Der Rahmen ist noetig, weil eine dunkle gewaehlte Farbe sonst mit der Kachel verschmilzt
   und der Knopf verschwindet. */
.pnt-swatch {
  width: 44px;
  height: 24px;
  border-radius: 7px;
  border: 1px solid var(--pnt-line);
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  transition: transform 0.12s ease, border-color 0.12s ease;
}

.pnt-swatch:hover {
  transform: translateY(-1px);
  border-color: var(--pnt-accent);
}

.chart-painter-modal.dark-mode .pnt-tile {
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.045), transparent 46%);
}

.pnt-tile.is-on {
  border-color: var(--pnt-tint);
  background: color-mix(in srgb, var(--pnt-tint) 8%, var(--pnt-raise));
  /* A tight ring only. The soft halo that used to sit behind it read as a glow rather
     than as a state, and at ten tiles wide the panel was lit from every corner. */
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--pnt-tint) 18%, transparent);
}

.pnt-tile-hit {
  display: block;
  width: 100%;
  padding: 9px 9px 11px;
  border: none;
  background: none;
  text-align: left;
  cursor: pointer;
  font: inherit;
}

/* The miniature sits on its own inset screen with a faint chart grid, which is what
   makes ten different marks read as ten views of the same chart. */
.pnt-tile-screen {
  position: relative;
  display: block;
  border-radius: 9px;
  background-color: var(--pnt-screen);
  background-image: linear-gradient(var(--pnt-grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--pnt-grid) 1px, transparent 1px);
  background-size: 14px 11px, 14px 11px;
  border: 1px solid var(--pnt-line-soft);
  overflow: hidden;
  margin-bottom: 9px;
}

.pnt-mini {
  display: block;
  width: 100%;
  height: auto;
  /* Off, the mark is held back rather than switched off. It used to be drained twice -
     this filter multiplied with the bar opacity below - which left a resting miniature at
     roughly a fifth of full strength and made the whole tile read as disabled. The active
     state is already unmistakable from the tinted border, the ring and the check, so the
     miniature does not have to carry that distinction on its own. */
  filter: saturate(0.62) opacity(0.78);
  transition: filter 0.25s ease;
}

.pnt-tile.is-on .pnt-mini,
.pnt-tile:hover .pnt-mini {
  filter: none;
}

.pnt-mini-bar.up line,
.pnt-mini-bar.up rect { stroke: var(--pnt-up); fill: var(--pnt-up); }

.pnt-mini-bar.down line,
.pnt-mini-bar.down rect { stroke: var(--pnt-down); fill: var(--pnt-down); }

/* The shared backdrop is held back so the mark on top of it reads first. Where a layer
   brings its own candles they are the subject - the gap is between them, the breakout is
   one of them closing through - so those come forward instead. */
.pnt-mini-bar { opacity: 0.55; }

.pnt-mini--story .pnt-mini-bar { opacity: 1; }

/* The chart labels its structure breaks on the canvas, so the miniature does too. */
.pnt-mini-tag {
  font-size: 7px;
  font-weight: 700;
  letter-spacing: 0.01em;
  text-anchor: middle;
}

/* Inside a zone rather than above a line: the gap it names is only eight units tall, so the
   word is set smaller and centred on the zone's middle instead of sitting on a baseline. */
.pnt-mini-tag--inset {
  font-size: 5.5px;
  dominant-baseline: central;
}

.pnt-tile-check {
  position: absolute;
  top: 5px;
  right: 5px;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--pnt-tint);
  color: #FFFFFF;
  transform: scale(0);
  opacity: 0;
  transition: transform 0.24s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.15s ease;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.28);
}

.pnt-tile-check svg { width: 10px; height: 10px; }

.pnt-tile.is-on .pnt-tile-check {
  transform: scale(1);
  opacity: 1;
}

.pnt-tile-name {
  display: block;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: -0.015em;
  color: var(--pnt-ink);
  line-height: 1.25;
}

.pnt-tile-blurb {
  display: block;
  margin-top: 2px;
  /* Clears the star in the corner: without it the last line of the blurb runs underneath
     the icon. Reserved on the blurb alone, since the name above it sits clear of the
     corner already. */
  padding-right: 22px;
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1.35;
  color: var(--pnt-ink-3);
}

/* ---- Favourite star ----------------------------------------------------- */
/* A sibling of the tile's hit button rather than a child of it - a button inside a button
   is invalid, and the star has to stay independently clickable so starring a layer never
   arms it by accident. It sits in the card's bottom-right corner, diagonally opposite the
   check badge, and off the miniature entirely so it never covers chart ink. */
.pnt-tile-main {
  position: relative;
}

.pnt-star {
  position: absolute;
  right: 6px;
  bottom: 6px;
  z-index: 2;
  width: 22px;
  height: 22px;
  padding: 0;
  border: none;
  border-radius: 7px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  background: none;
  color: var(--pnt-ink-3);
  transition: color 0.18s ease, background 0.18s ease, transform 0.18s ease;
}

.pnt-star svg {
  width: 13px;
  height: 13px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linejoin: round;
}

.pnt-star:hover {
  color: var(--pnt-star);
  background: color-mix(in srgb, var(--pnt-star) 14%, transparent);
  ;
}

.pnt-star.is-on {
  color: var(--pnt-star);
}

/* Filled once starred, so on and off differ in weight and not only in colour. */
.pnt-star.is-on svg {
  fill: currentColor;
  stroke: currentColor;
}

/* The starred section gets the same star at heading size, so the two read as one idea. */
.pnt-group-star {
  width: 11px;
  height: 11px;
  flex-shrink: 0;
  fill: var(--pnt-star);
}

/* ---- Per-tile settings -------------------------------------------------- */
/* Only rendered once a tile is on. A layer you have not picked has no settings worth
   reading, and hiding them is what keeps a ten-layer panel down to one screen. */
.pnt-tile-controls {
  border-top: 1px solid color-mix(in srgb, var(--pnt-tint) 22%, transparent);
  background: color-mix(in srgb, var(--pnt-tint) 6%, transparent);
  padding: 8px 9px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  animation: pnt-unfold 0.22s ease-out;
}

@keyframes pnt-unfold {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.pnt-ctl {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.pnt-ctl-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--pnt-ink-2);
}

.pnt-stepper {
  display: inline-flex;
  align-items: center;
  background: var(--pnt-surface);
  border: 1px solid var(--pnt-line);
  border-radius: 8px;
  overflow: hidden;
}

.pnt-stepper button {
  width: 22px;
  height: 24px;
  border: none;
  background: none;
  color: var(--pnt-ink-2);
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.pnt-stepper button:hover:not(:disabled) {
  background: var(--pnt-tint);
  color: #FFFFFF;
}

.pnt-stepper button:disabled {
  opacity: 0.3;
  cursor: default;
}

.pnt-stepper input[type="number"] {
  width: 46px;
  height: 24px;
  border: none;
  border-left: 1px solid var(--pnt-line);
  border-right: 1px solid var(--pnt-line);
  background: none;
  color: var(--pnt-ink);
  font-size: 12px;
  font-weight: 600;
  text-align: center;
  outline: none;
  -moz-appearance: textfield;
  appearance: textfield;
}

.pnt-stepper input[type="number"]::-webkit-outer-spin-button,
.pnt-stepper input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* ---- Action bar --------------------------------------------------------- */
.pnt-footer {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 12px 16px;
  border-top: 1px solid var(--pnt-line);
  background: var(--pnt-surface);
}

.pnt-clear {
  flex-shrink: 0;
  padding: 12px 15px;
  border: 1px solid var(--pnt-line);
  border-radius: 12px;
  background: var(--pnt-raise);
  color: var(--pnt-ink-2);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.18s ease;
}

.pnt-clear:hover:not(:disabled) {
  color: var(--pnt-down);
  border-color: color-mix(in srgb, var(--pnt-down) 45%, transparent);
}

.pnt-clear:disabled {
  opacity: 0.4;
  cursor: default;
}

/* Das Zahnrad links neben Clear. Auf demselben Kasten wie .pnt-clear aufgebaut, und das
   ist der Punkt: jede Farbe hier ist ein --pnt-*-Token, und die tauscht das Panel selbst
   pro Theme. Eine eigene dark-mode-Regel braucht es damit nicht.

   flex-shrink: 0, weil .painter-apply-btn flex: 1 ist und das Zahnrad auf dem Telefon
   sonst als erstes zusammengedrueckt wird. */
.pnt-gear {
  flex-shrink: 0;
  width: 42px;
  height: 42px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--pnt-line);
  border-radius: 12px;
  background: var(--pnt-raise);
  color: var(--pnt-ink-2);
  cursor: pointer;
  transition: all 0.18s ease;
}

.pnt-gear:hover {
  color: var(--pnt-ink);
  border-color: color-mix(in srgb, var(--pnt-accent) 45%, transparent);
}

.pnt-gear.is-on {
  background: var(--pnt-accent);
  border-color: var(--pnt-accent);
  color: #FFFFFF;
}

/* ---- Layer settings ------------------------------------------------------ */
/* Die Zeilen stehen auf --pnt-raise, nicht auf der Panelflaeche selbst. .pnt-stepper malt
   sich mit --pnt-surface (es war fuer die getoente Flaeche einer Kachel gebaut), und auf
   dem blanken Panel - derselbe Token - bliebe vom Regler nur sein 1px-Rahmen uebrig. */
.pnt-settings {
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.pnt-set-intro {
  margin: 0 0 2px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--pnt-ink-3);
}

.pnt-set-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 11px 12px;
  border: 1px solid var(--pnt-line);
  border-radius: 12px;
  background: var(--pnt-raise);
}

.pnt-set-name {
  font-size: 12.5px;
  font-weight: 650;
  letter-spacing: -0.01em;
  color: var(--pnt-ink);
}

.painter-apply-btn {
  position: relative;
  flex: 1;
  padding: 12px 18px;
  border: none;
  border-radius: 12px;
  background: linear-gradient(135deg, var(--pnt-accent), var(--pnt-accent-2));
  color: #FFFFFF;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -0.015em;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.16);
  transition: transform 0.18s ease, box-shadow 0.18s ease, filter 0.18s ease;
}

.painter-apply-btn::before {
  content: '';
  position: absolute;
  inset: 0 auto 0 -60%;
  width: 45%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.32), transparent);
  transform: skewX(-18deg);
  transition: left 0.55s ease;
}

.painter-apply-btn:hover:not(:disabled)::before { left: 130%; }

.painter-apply-btn:hover:not(:disabled) {
  ;
  box-shadow: 0 8px 18px rgba(0, 0, 0, 0.22);
}

.painter-apply-btn:active:not(:disabled) { transform: translateY(0); }

/* Disabled rather than hidden: the button is the thing you are aiming for, and it
   should stay where it is while it tells you it has nothing to paint yet. */
.painter-apply-btn:disabled {
  cursor: default;
  filter: grayscale(0.85);
  opacity: 0.45;
  box-shadow: none;
}

.painter-apply-btn svg { flex-shrink: 0; }

.pnt-apply-count {
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.24);
  font-size: 11.5px;
  font-weight: 700;
  line-height: 20px;
  text-align: center;
}

/* ---- Phones ------------------------------------------------------------- */
/* The width cap for this panel is set with the other dialogs in the responsive block
   further down; what changes here is only the internal density. */
@media (max-width: 768px), (max-height: 500px) and (orientation: landscape) {
  .pnt-presets { padding: 10px 12px; }
  .chart-painter-content { padding: 12px; gap: 16px; }
  .pnt-grid { gap: 8px; }
  /* At ~142px a tile the longer names and blurbs wrap and the shorter ones do not, which
     left the row ragged. Reserving the wrapped height keeps the grid even; on a desktop
     every label already fits on one line, so this is not needed there. */
  .pnt-tile-name { min-height: 2.5em; }
  .pnt-tile-blurb { min-height: 2.7em; }
  .pnt-footer { padding: 10px 12px; }
}

/* A 375px phone still gives each tile ~150px, which holds the miniature and a name over
   two lines, so it keeps both columns - dropping to one there would double the scrolling
   for no gain. Only genuinely narrow screens fall back to a single column. */
@media (max-width: 340px) {
  .pnt-grid { grid-template-columns: minmax(0, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
  .chart-painter-modal,
  .pnt-tile-controls { animation: none; }
  .painter-apply-btn::before { transition: none; }
}

/* ========================================
   CHART SCANNER ANIMATIONS
   ======================================== */
@keyframes scan-pulse {
  0%, 100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.6;
    transform: scale(1.05);
  }
}

@keyframes scan-line {
  0% {
    top: 0;
  }
  100% {
    top: 100%;
  }
}

/* ========================================
   CHART SCANNER MODAL
   ======================================== */
/* ---- Scanner shell ------------------------------------------------------
   Same surface, radius, border and shadow as the painter, and the same flex column so
   only the readout scrolls while the title bar stays put. It keeps its own width because
   it is a report rather than a control panel - three timeframes have to sit side by side
   without wrapping. */
.chart-scanner-modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 600px;
  max-height: 80vh;
  background: var(--pnt-surface);
  border: 1px solid var(--pnt-line);
  border-radius: 20px;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.18), 0 2px 6px rgba(0, 0, 0, 0.06);
  z-index: 10001;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: pnt-rise 0.34s cubic-bezier(0.22, 1, 0.36, 1);
}

.chart-scanner-modal.dark-mode {
  /* Dieselbe Flaeche wie der Painter. Der trug sie nur zufaellig richtig: er fuehrt
     zusaetzlich .chatbot-modal, und `.dark-mode .chatbot-modal` aus der Gruppe der
     schwebenden Paneele sticht mit zwei Klassen das blanke `.dark-mode { background }`
     aus. Der Scanner hat diese zweite Klasse nicht - bei ihm gewann also das blanke
     `.dark-mode`, gleich spezifisch wie `.chart-scanner-modal`, aber weiter unten in der
     Datei. Das Panel stand dadurch auf --bk-app, also auf reinem Schwarz, waehrend der
     Painter auf #101010 stand, und sein eigenes `background: var(--pnt-surface)` weiter
     oben kam nie zum Zug.

     Hier mit zwei Klassen festgeschrieben, damit es nicht wieder von einer allgemeinen
     Regel eingesammelt wird. */
  background: var(--bk-elevated);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.04);
}

/* The header is the painter's .pnt-top, reused wholesale - see that block for the aurora
   wash and the brand mark. Only the close button needs a disabled state here, because the
   scanner can be mid-scan while the painter never is. */
.chart-scanner-modal .pnt-close:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
}

.chart-scanner-modal .pnt-close:disabled:hover {
  background: var(--pnt-raise);
  color: var(--pnt-ink-2);
  transform: none;
}

.chart-scanner-content {
  flex: 1;
  min-height: 0;
  padding: 16px;
  overflow-y: auto;
  /* Without this the panel inherits the app's pale text colour, which left every value
     that doesn't set its own - prices, percentages - near-invisible. */
  color: var(--pnt-ink);
  background: var(--pnt-surface);
  scrollbar-width: thin;
  scrollbar-color: var(--pnt-line) transparent;
}

.chart-scanner-content::-webkit-scrollbar {
  width: 8px;
}

.chart-scanner-content::-webkit-scrollbar-track {
  background: transparent;
}

.chart-scanner-content::-webkit-scrollbar-thumb {
  background: var(--pnt-line);
  border-radius: 4px;
}

/* ---- Scanning state -----------------------------------------------------
   The scan mark borrows the painter's brand mark: same 140deg accent gradient, same
   rounded square, just larger and pulsing while it works. */
.scan-run {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 52px 20px 44px;
}

.scan-run-mark {
  position: relative;
  width: 68px;
  height: 68px;
  border-radius: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  color: #FFFFFF;
  background: linear-gradient(140deg, var(--pnt-accent), var(--pnt-accent-2));
  animation: scan-pulse 2s ease-in-out infinite;
}

.scan-run-mark svg {
  width: 32px;
  height: 32px;
}

/* The sweep line rides over the mark rather than beside it, so the whole tile reads as
   the thing being scanned. */
.scan-run-sweep {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 3px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.95), transparent);
  animation: scan-line 2s linear infinite;
}

.scan-run h3 {
  margin: 18px 0 6px;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--pnt-ink);
}

.scan-run p {
  margin: 0;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--pnt-ink-3);
}

.scan-cancel {
  margin-top: 22px;
  padding: 10px 18px;
  border: 1px solid var(--pnt-line);
  border-radius: 12px;
  background: var(--pnt-raise);
  color: var(--pnt-ink-2);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.18s ease;
}

.scan-cancel:hover {
  color: var(--pnt-down);
  border-color: color-mix(in srgb, var(--pnt-down) 45%, transparent);
}

/* ---- Failure ------------------------------------------------------------ */
.scan-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 12px;
  padding: 48px 24px;
  color: var(--pnt-down);
}

.scan-error p {
  margin: 0;
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1.5;
  max-width: 34ch;
}

@media (max-width: 768px), (max-height: 500px) and (orientation: landscape) {
  .chart-scanner-content { padding: 12px; }
  .scan-run { padding: 40px 16px 36px; }
}

/* Multi-timeframe tiles: a miniature chart that draws itself, holds, then redraws.
   The line direction carries the trend, so the motion reads as price moving rather
   than as a decorative spinner. */
@keyframes scan-spark-draw {
  0%   { stroke-dashoffset: 62; opacity: 0; }
  18%  { opacity: 1; }
  55%  { stroke-dashoffset: 0; opacity: 1; }
  86%  { stroke-dashoffset: 0; opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 0; }
}

@keyframes scan-spark-tip {
  0%, 48% { opacity: 0; transform: scale(0.2); }
  62%     { opacity: 1; transform: scale(1); }
  86%     { opacity: 1; transform: scale(1); }
  100%    { opacity: 0; transform: scale(1); }
}

.scan-spark-line {
  stroke-dasharray: 62;
  stroke-dashoffset: 0;
  animation: scan-spark-draw 2.8s ease-in-out infinite;
}

.scan-spark-tip {
  transform-origin: center;
  transform-box: fill-box;
  animation: scan-spark-tip 2.8s ease-in-out infinite;
}

/* Motion is decoration here - the direction is already in the colour and the label. */
@media (prefers-reduced-motion: reduce) {
  .scan-spark-line,
  .scan-spark-tip {
    animation: none;
    stroke-dashoffset: 0;
    opacity: 1;
  }
}

/* ========================================
   TRADING PANEL MODAL
   ======================================== */
.trading-panel-modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 500px;
  max-height: 80vh;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(80px) saturate(200%);
  -webkit-backdrop-filter: blur(80px) saturate(200%);
  border-radius: 12px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25), 0 0 1px rgba(0, 0, 0, 0.3);
  z-index: 10000;
  display: flex;
  flex-direction: column;
  border: 1px solid rgba(142, 142, 147, 0.12);
}

.trading-panel-modal.dark-mode {
  background: rgba(28, 28, 30, 0.95);
  border-color: var(--bk-border);
}

.trading-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid rgba(142, 142, 147, 0.12);
}

.trading-panel-modal.dark-mode .trading-panel-header {
  border-bottom-color: var(--bk-border);
}

.trading-panel-header h3 {
  font-family: var(--font-ui);
  font-size: 17px;
  font-weight: 600;
  color: #1D1D1F;
  margin: 0;
}

.trading-panel-modal.dark-mode .trading-panel-header h3 {
  color: #F5F5F7;
}

.clear-history-btn {
  padding: 6px 12px;
  background: rgba(255, 59, 48, 0.1);
  border: 1px solid rgba(255, 59, 48, 0.3);
  border-radius: 8px;
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  color: #ff3b30;
  cursor: pointer;
  transition: all 0.2s ease;
  margin-left: auto;
  margin-right: 8px;
}

.clear-history-btn:hover {
  background: rgba(255, 59, 48, 0.15);
  border-color: rgba(255, 59, 48, 0.5);
}

.trading-panel-modal.dark-mode .clear-history-btn {
  background: rgba(255, 69, 58, 0.12);
  border-color: rgba(255, 69, 58, 0.35);
  color: #ff453a;
}

.trading-panel-modal.dark-mode .clear-history-btn:hover {
  background: rgba(255, 69, 58, 0.18);
  border-color: rgba(255, 69, 58, 0.5);
}

.trading-panel-content {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.no-trades-message {
  text-align: center;
  padding: 40px 20px;
  font-family: var(--font-ui);
  font-size: 15px;
  color: #86868B;
}

.trades-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.trade-item {
  background: rgba(142, 142, 147, 0.08);
  border-radius: 8px;
  padding: 12px;
  border-left: 3px solid;
}

.trade-item.buy {
  border-left-color: #007AFF;
}

.trade-item.sell {
  border-left-color: #ef4444;
}

.trading-panel-modal.dark-mode .trade-item {
  background: rgba(255, 255, 255, 0.08);
}

.trade-item-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

.trade-number {
  font-family: var(--font-mono);
  font-size: 12px;
  color: #86868B;
}

.trade-type {
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 4px;
}

.trade-type.buy {
  background: rgba(59, 130, 246, 0.15);
  color: #007AFF;
}

.trade-type.sell {
  background: rgba(239, 68, 68, 0.15);
  color: #ef4444;
}

.trade-status {
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 500;
  padding: 2px 6px;
  border-radius: 3px;
  margin-left: auto;
}

.trade-status.open {
  background: rgba(52, 199, 89, 0.15);
  color: #34C759;
}

.trade-status.closed {
  background: rgba(142, 142, 147, 0.15);
  color: #86868B;
}

.trade-item-details {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.trade-detail-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-family: var(--font-ui);
  font-size: 13px;
}

.trade-label {
  color: #86868B;
  font-weight: 500;
}

.trade-value {
  color: #1D1D1F;
  font-weight: 500;
}

.trading-panel-modal.dark-mode .trade-value {
  color: #F5F5F7;
}

.pnl-row {
  margin-top: 4px;
  padding-top: 8px;
  border-top: 1px solid rgba(142, 142, 147, 0.12);
}

.trading-panel-modal.dark-mode .pnl-row {
  border-top-color: var(--bk-border);
}

.trade-pnl {
  font-weight: 600;
  font-family: var(--font-mono);
}

.trade-pnl.profit {
  color: var(--bk-pos);
}

.trade-pnl.loss {
  color: var(--bk-neg);
}

.trading-panel-summary {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
  padding: 16px;
  background: rgba(142, 142, 147, 0.08);
  border-radius: 8px;
  margin-top: auto;
}

.trading-panel-modal.dark-mode .trading-panel-summary {
  background: rgba(255, 255, 255, 0.08);
}

.summary-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.summary-label {
  font-family: var(--font-ui);
  font-size: 12px;
  color: #86868B;
  font-weight: 500;
}

.summary-value {
  font-family: var(--font-ui);
  font-size: 16px;
  color: #1D1D1F;
  font-weight: 600;
}

.trading-panel-modal.dark-mode .summary-value {
  color: #F5F5F7;
}

/* ========================================
   MOBILE  (max-width: 768px, or a phone on its side)

   Every phone media query in this file carries the same pair of conditions: the width
   test, plus a short landscape window. A phone turned sideways is 812 to 932 points WIDE,
   so width alone handed it the desktop layout in a window 375 points tall. The pair is
   mirrored in PHONE_LAYOUT_QUERY in CandlestickChart.jsx, which is what the component
   reads to make the same decision in JS - a media query cannot read a constant, so the
   two have to be kept in step by hand.
   ========================================
   Everything from here down sits inside one media query, so the desktop layout above is
   untouched by construction - no rule here can match a desktop viewport.

   It lives in this file rather than mobile.css because main.jsx imports mobile.css BEFORE
   the component styles, so its overrides lose the cascade to this file at equal
   specificity. That is why several of them never took effect.
   ======================================== */
@media (max-width: 768px), (max-height: 500px) and (orientation: landscape) {

  /* --- Centred dialogs ------------------------------------------------------
     Each of these is a fixed-width desktop dialog between 400px and 760px, so on a phone
     they ran off both edges with their controls unreachable. They stay centred; only the
     width follows the viewport, and the height is capped so tall panels scroll inside
     themselves rather than off-screen. !important is needed because
     .chart-painter-modal declares its width that way. */
  .profile-modal,
  .chart-settings-modal,
  .symbol-modal,
  .settings-drawer,
  .indicator-modal,
  .indicator-settings-modal-wrapper,
  .trade-checker-modal,
  .fib-levels-modal,
  .chatbot-modal,
  .chart-painter-modal,
  .chart-scanner-modal,
  .trading-panel-modal,
  .journal-dashboard-modal,
  .alert-modal {
    width: calc(100vw - 44px) !important;
    max-width: calc(100vw - 44px) !important;
    min-width: 0 !important;
    /* !important on the height too, not just the width: .chart-painter-modal declares
       its own max-height and was winning against the plain cap, so it stayed at 680px
       while everything around it shrank. These are caps, so raising specificity only
       ever pulls a panel down to the limit - a dialog already shorter is untouched. */
    max-height: 68vh !important;
    max-height: 68dvh !important;
  }

  /* --- Chart Settings above the tool rail -------------------------------------
     Chart Settings is drawn inside .chart-wrapper, which is its own stacking layer (z 1),
     and the drawing tool rail next to it sits at z 10 - so the panel's z-index only counted
     inside the chart, and the rail was painted over it. On a phone the centred panel
     reaches under the rail and its left edge was cut off. While it is open the chart is
     lifted above the rail; on desktop the panel never gets near the rail, so this is
     phone-only and changes nothing there. */
  .chart-wrapper:has(.chart-settings-modal) {
    z-index: 20;
  }

  /* --- Chart Settings, compact ----------------------------------------------
     This one is a list, and on a phone its desktop frame was eating the room the list
     needed. At 375x640 the panel came to 435px - the 68dvh cap just above - of which the
     header took 85, the tabs 44 and the footer 77. That left 227px for seven rows of 61,
     so three were on screen and the other four had to be found by scrolling inside a box
     already filling two thirds of the display.

     Everything below shrinks the frame rather than the cap, so the panel stays the size it
     was and the list inside it roughly doubles. Scoped to .chart-settings-modal on purpose:
     these classes are shared with the Swift Algo window, which is a different shape and is
     not what was reported. */
  .chart-settings-modal .chart-settings-header {
    padding: 10px 8px 10px 14px;
  }

  .chart-settings-modal .chart-settings-header h3 {
    font-size: 15px;
  }

  .chart-settings-modal .settings-modal-close {
    font-size: 18px;
    width: 28px;
    height: 28px;
  }

  .chart-settings-modal .indicator-settings-tabs {
    padding: 0 14px;
  }

  .chart-settings-modal .indicator-settings-tab {
    padding: 8px 10px;
    font-size: 12.5px;
  }

  .chart-settings-modal .indicator-settings-content {
    padding: 6px 14px;
  }

  /* The rows carry most of the saving: there are seven of them, so every pixel taken off
     one is taken off seven. */
  .chart-settings-modal .style-visibility-row {
    padding: 6px 0;
  }

  /* And the gap between them was the single biggest piece of slack: 16px across six gaps
     is 96px of nothing, on a list where every row already draws its own bottom border to
     separate it from the next. The border does the work the gap was doing. */
  .chart-settings-modal .indicator-settings-tab-content {
    gap: 4px;
  }

  .chart-settings-modal .indicator-settings-footer {
    padding: 10px 14px;
    gap: 8px;
  }

  .chart-settings-modal .indicator-reset-colors-btn,
  .chart-settings-modal .indicator-apply-settings-btn {
    padding: 9px 14px;
    font-size: 13px;
  }

  /* --- Chart Settings, small card ---------------------------------------------
     Even compacted, the frame filled the screen: 331 x 454 at 375 x 667, a 65px header,
     49px rows with 36px swatches and 44px buttons - a desktop dialog shrunk, not a phone
     panel. It is a short list of colours and switches, so it becomes a small card over
     the chart: narrower, lower rows, smaller swatches and buttons, the same list. */
  .chart-settings-modal.chart-settings-modal {
    width: min(300px, calc(100vw - 64px)) !important;
    max-width: min(300px, calc(100vw - 64px)) !important;
    max-height: 60vh !important;
    max-height: 60dvh !important;
    border-radius: 14px;
  }

  .chart-settings-modal .chart-settings-header {
    padding: 6px 6px 6px 14px;
  }

  .chart-settings-modal .chart-settings-header h3 {
    margin: 0;
    font-size: 14px;
    line-height: 1.2;
  }

  .chart-settings-modal .settings-modal-close {
    font-size: 15px;
    width: 30px;
    height: 30px;
    min-width: 0;
    min-height: 0;
    padding: 0;
  }

  .chart-settings-modal .indicator-settings-tab {
    padding: 7px 8px;
    font-size: 12px;
  }

  .chart-settings-modal .indicator-settings-content {
    padding: 4px 12px;
  }

  .chart-settings-modal .style-visibility-row {
    padding: 3px 0;
    min-height: 0;
  }

  .chart-settings-modal .style-visibility-left,
  .chart-settings-modal .style-visibility-left span,
  .chart-settings-modal .style-visibility-left label {
    font-size: 12.5px;
  }

  .chart-settings-modal .style-visibility-right {
    gap: 6px;
  }

  .chart-settings-modal .custom-color-picker-simple,
  .chart-settings-modal .color-preview-simple {
    width: 26px;
    height: 26px;
    min-width: 26px;
    border-radius: 7px;
  }

  .chart-settings-modal .indicator-settings-footer {
    padding: 8px 12px;
    gap: 6px;
  }

  .chart-settings-modal .indicator-reset-colors-btn,
  .chart-settings-modal .indicator-cancel-settings-btn,
  .chart-settings-modal .indicator-apply-settings-btn {
    height: 34px;
    padding: 0 12px;
    font-size: 12.5px;
    min-height: 0;
  }

  /* The indicator window is draggable on a desktop, so it positions itself absolutely from
     inline coordinates - wherever it was last dropped, or the centre of the chart area it
     was opened over. On a phone there is nowhere to drag it to, and the result was that it
     opened somewhere different from the market modal every other dialog matches. Pinned to
     the same centre those use. !important throughout because the coordinates it is
     overriding are inline, and right/bottom are cleared in case a drag left them set. */
  /* The confirm button's styling moved to the base rules: it is shown on every layout
     now, not only where a datetime-local field would otherwise have started the replay on
     its first partial value. */

  /* Two columns of level rows leave about 140px each on a phone - enough to fit only after
     the label field has been squeezed to nothing. One column per row reads properly and the
     modal scrolls vertically, which it is already set up to do. */
  .fib-levels-grid {
    grid-template-columns: 1fr;
    gap: 8px;
  }

  .indicator-modal {
    /* Above the backdrop it now gets. The base z-index is 100 - fine for a window layered
       over the chart, but the overlay sits at 1500 and would cover the window itself.
       1501 is what .symbol-modal uses over the same overlay. */
    z-index: 1501 !important;
    position: fixed !important;
    top: 50% !important;
    left: 50% !important;
    right: auto !important;
    bottom: auto !important;
    transform: translate(-50%, -50%) !important;
  }

  /* iOS Safari zooms the page in whenever a text field under 16px takes focus, and it does
     not zoom back out afterwards - tap the symbol search and you are left magnified in a
     corner of the chart with no obvious way back. 16px is the documented threshold, and
     raising the field to it is the only fix that does not involve disabling pinch zoom,
     which the viewport tag deliberately allows. The four fields this catches - symbol
     search, alert price, alert type and the trade note - are inline-styled or carry no
     class, hence the element selectors and the !important. */
  input[type="text"],
  input[type="number"],
  input[type="search"],
  input[type="email"],
  input[type="password"],
  input: not([type]),
  textarea,
  select {
    font-size: 16px !important;
  }

  /* Anchored inside the chart rather than centred, so they only need their floor removed */
  .order-panel,
  .replay-panel {
    min-width: 0;
    max-width: calc(100vw - 16px);
  }

  /* Both hang off right: 20px at a fixed desktop width. The watchlist is 360px, which on a
     375px screen put its left edge at -5 and took the first character of every row and the
     drawer's own close button with it. Capping to the viewport keeps the 20px anchor and
     gives the same margin on the left. The position calculator is 340px and already fit,
     but it is the same construction and would break on anything narrower. */
  .watchlist-drawer,
  .position-calc-drawer {
    max-width: calc(100vw - 40px);
  }

  /* The pending-order controls that appear on a BUY or SELL clear the price axis with a
     hard right: 250px, which is the axis width on a desktop. Here the axis is about 56px
     and the whole chart wrapper only 323px, so that offset put the overlay's right edge
     117px from the left of the screen and hid 49% of it - the take-profit, stop-loss and
     size controls were all off-screen to the left, leaving just the P&L box visible and
     no way to reach the rest. 64px clears the axis at this width with the full 229px of
     controls inside the chart. */
  .pending-order-overlay {
    right: 64px;
  }

  /* .chatbot-modal pins itself 52px from the left to clear the desktop tool column, which
     the width above turns into a right edge 8px off a 375px screen. Centre it on the same
     44px of total margin the other dialogs use. The docked .ai-side-panel variant sets
     left: auto at a higher specificity, so it keeps flowing in its column. */
  .chatbot-modal {
    left: 22px;
  }

  /* The settings panel reserved 300px for its scroll area on top of header, tabs and
     footer - taller than a phone in landscape. Let it shrink and scroll instead. */
  .indicator-settings-content {
    min-height: 0;
    max-height: none;
  }

  /* --- Content inside the dialogs -------------------------------------------
     The market filters are 505px of chips in a 329px row set to scroll, so Forex,
     Indices and Stocks sat past the edge with nothing to indicate they existed - the
     row reads as though the app only has three categories. Wrapping shows all six.
     They are filter chips rather than primary actions, so they give up the 44px floor
     to keep the two rows they now occupy from eating the list below. */
  .category-filters {
    flex-wrap: wrap;
    overflow-x: visible;
  }

  .category-btn {
    min-height: 30px;
    padding: 5px 10px;
    font-size: 11px;
  }

  /* Each symbol row reserved 150px that refuses to shrink for two badges needing 70,
     which left 31px for the ticker and squeezed the name to nothing - every row read
     "BTCUSD" with no "Bitcoin" after it. Letting the badges size to their content hands
     roughly 80px back to the name. */
  .symbol-item-meta {
    min-width: 0;
    flex-shrink: 1;
  }

  /* That still left names ellipsising to "Poly...". The provider badge is the cheapest
     thing on the row to give up: it repeats down the whole list and says nothing about
     the symbol being picked, unlike the asset type beside it. */
  .symbol-source {
    display: none;
  }

  /* The Trade Dashboard header put a 22px title and the auto-sync toggle side by side
     with 60px of padding around them, which needs ~360px against the 271px a phone
     leaves. Both wrapped mid-word - the toggle became eight lines of stacked text inside
     its pill and the header alone ate 130px of a 552px panel. Letting the two sit on
     separate rows keeps each on one line. !important throughout because the values it is
     overriding are inline. */
  .journal-dashboard-header {
    padding: 12px 14px !important;
  }

  .journal-dashboard-header h2 {
    font-size: 16px !important;
  }

  .journal-dashboard-title-group {
    flex-wrap: wrap;
    gap: 8px !important;
    min-width: 0;
  }

  /* --- Trade Dashboard body -------------------------------------------------
     None of these grids collapse on their own, so at 263px of content width the
     dashboard was not merely large, it was broken: the 12-column grid resolved to
     3.58px columns and squeezed its panels to 74px wide by 1296px tall, and the trades
     row laid out 326px and 860px children inside a 263px box. Each one is given a
     column count a phone can actually render. Values are inline throughout, hence
     !important on everything that overrides them. */
  .journal-dashboard-content {
    padding: 12px !important;
  }

  /* Two up rather than one: the tiles are a label and a number, so a pair per row fits
     comfortably and halves the scrolling to reach the rest. */
  /* minmax(0, 1fr) rather than a bare 1fr: 1fr means minmax(auto, 1fr), and a grid item's
     automatic minimum is its own content, so a tile with a long label ("Avg win-loss
     ratio") widened its track past the half it was given instead of wrapping - which is
     what pushed the grid 124px wider than the panel holding it. */
  .journal-stats-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    gap: 8px !important;
    margin-bottom: 12px !important;
  }

  .journal-stats-grid > div {
    padding: 10px !important;
    border-radius: 10px !important;
    min-width: 0;
  }

  /* The number line. 32px of it was most of a 114px tile's height. */
  .journal-stats-grid > div > div:last-child {
    font-size: 18px !important;
  }

  .journal-main-grid,
  .journal-trades-row {
    grid-template-columns: minmax(0, 1fr) !important;
    gap: 10px !important;
    margin-bottom: 12px !important;
  }

  /* The panels inside the 12-column grid position themselves with grid-column: span N,
     which means nothing once there is a single column - and left them overlapping. */
  .journal-main-grid > div,
  .journal-trades-row > div {
    grid-column: auto !important;
    padding: 12px !important;
    min-width: 0;
  }

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

  /* Left to size itself the week came to 812px against 275px of card - three screens of
     sideways scrolling. Most of that was the 140px weekly-summary column and day cells
     sized to their P&L text. Pinning both brings a week to roughly 380px, so it is closer
     to a nudge than a journey, while keeping seven days on one row. */
  /* Two levels: the weekday header is a direct child, but the week rows sit one deeper
     inside a flex wrapper, so a single > div rule only ever reached the header. The
     declaration is inert on the cells it also matches, which are not grids. */
  .journal-calendar > div,
  .journal-calendar > div > div {
    grid-template-columns: repeat(7, minmax(34px, 1fr)) 76px !important;
    gap: 4px !important;
  }

  .journal-calendar {
    font-size: 10px;
  }

  /* --- Touch targets --------------------------------------------------------
     mobile.css gives every <button> a 44px minimum for touch. That is right for toolbar
     buttons, but these are icon-sized controls pinned inside fixed-height rows and
     badges - a 22px info icon became 44px and broke the row it sits in. Their padded hit
     area still exceeds the icon itself. */
  .info-tip-btn,
  .sensitivity-guide-toggle,
  .indicator-badge-icon-btn,
  .symbol-favorite-btn,
  .symbol-watchlist-btn,
  .wl-icon-btn,
  .wl-row-remove {
    min-height: 0;
    min-width: 0;
  }

  /* Both row controls are revealed by :hover, which a touch screen never fires - the
     watchlist button would be unreachable on a phone and the star is only visible today
     once it is already lit. Show them outright here. */
  .symbol-favorite-btn,
  .symbol-watchlist-btn,
  .wl-row-remove,
  .dark-mode .symbol-favorite-btn,
  .dark-mode .symbol-watchlist-btn,
  .dark-mode .wl-row-remove {
    opacity: 1;
  }

  /* The indicator badge is 63x21 - under half the 44px target - and it is pinned over the
     top-left candles, so it cannot just be made bigger without covering the price action
     it labels. The hit area is pushed out past the ink instead, which costs no layout: the
     badge still draws at 63x21 but answers to a tap across roughly 87x39. */
  .indicator-badge-header {
    position: relative;
  }

  .indicator-badge-header::before {
    content: '';
    position: absolute;
    inset: -9px -12px;
  }

  /* The extension above is positioned, so in this stacking context it would paint - and
     hit-test - over the in-flow icon buttons and swallow the taps meant for them. Giving
     the buttons a position too puts DOM order back in charge, and they come after it. */
  .indicator-badge-icon-btn {
    position: relative;
    padding: 4px;
  }

  /* --- Buy / Sell / size overlay --------------------------------------------
     These three float over the chart rather than sitting in a bar, so the 44px floor
     was spending 168x44 - 45% of a 375px viewport - on controls whose own type is
     10px and which only need ~26px to render. They also sit directly over the top-left
     of the price action, which is the part of the chart worth seeing on a phone.

     Deliberately below the 44px touch guideline: these are pinned over content on the
     smallest screens, where the space they were taking cost more than the extra few
     pixels of target bought. Scoped to .trade-buttons-panel so the full-size BUY/SELL
     inside the trading panel modal are untouched. */
  .trade-buttons-panel {
    gap: 4px;
  }

  .trade-buttons-panel .order-btn {
    min-height: 26px;
    height: 26px;
    min-width: 36px;
    padding: 0 8px;
    font-size: 9px;
    letter-spacing: 0.2px;
  }

  .trade-buttons-panel .quantity-btn {
    min-height: 26px;
    height: 26px;
    min-width: 0;
    padding: 0 6px;
    gap: 2px;
    font-size: 9px;
  }

  .trade-buttons-panel .quantity-btn svg {
    width: 8px;
    height: 8px;
  }

  /* The size menu behind that button was 101x652 - 29% of the chart, and deeper than the
     plot area, so reaching $100K meant scrolling a list that was already covering the
     candles. Almost all of it was the 44px button floor applied eighteen times over: the
     values are four characters of 10px type and need nothing like that. Two columns as
     well as shorter rows, because a single column was spending 101px of width on "$100"
     and paying for it in height. The whole list now opens at once with no scrolling. */
  .quantity-menu {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 2px;
    padding: 4px;
    min-width: 104px;
  }

  /* "Custom..." is half again as long as any value in the list, and as a grid item it was
     setting the width of both columns from one cell - which dragged the menu wider than
     the single column it replaced. Given the full row it stops competing, and the columns
     size to "$100K" instead. */
  .quantity-option:last-child {
    grid-column: 1 / -1;
  }

  /* --- TP/SL drag badge ------------------------------------------------------
     This rides the price axis while a level is being dragged, so it sits on the candles for
     the whole gesture. 11px type with 12px of side padding, an 8px gap and an 18px close
     button carrying another 16px of its own spacing is a desktop badge - here it covered a
     good part of the plot it is being positioned against.

     It also inherits the same mistake the order controls had: an inline right: 250px, which
     is the width of the desktop price axis. The axis is about 56px here, so the badge was
     pushed far left of the line it belongs to. !important because that value is inline. */
  .tp-sl-box {
    right: 64px !important;
    gap: 4px;
    padding: 3px 6px;
    font-size: 9px;
    border-radius: 3px;
  }

  /* mobile.css floors every button at 44px, which inflated the close control to 44x44 and
     took the whole badge to 130x52 - larger than the desktop one it was meant to shrink.
     The badge is a drag handle sitting on the candles, not a control to hunt for. */
  .tp-sl-close {
    width: 13px;
    height: 13px;
    min-width: 0;
    min-height: 0;
    padding-left: 4px;
    margin-left: 4px;
  }

  /* Same reasoning as the badge itself: this sits on top of the candles, so the amount is
     kept to the digits and the divider is thinned to match the tighter gap. */
  .tp-sl-pnl {
    padding-left: 4px;
  }

  /* The unit goes, the number stays. With it the badge took 42% of a 375px screen; the
     price beside it already carries a $, so USD was only ever restating that. */
  .tp-sl-pnl-unit {
    display: none;
  }

  /* The controls that appear on a BUY or SELL sit on the price line itself, so their height
     is taken straight out of the candles they are pointing at. TP, SL and the confirm were
     44x44 each - the touch floor again - around 11px labels, and the P&L box spent 107px on
     nine characters. These are the same numbers .trade-buttons-panel above was cut to, and
     for the same reason: pinned over the plot area on the smallest screens, where the space
     costs more than the target. Scoped to .pending-order-overlay, so the equivalents inside
     the trading panel modal keep their full size. */
  /* 6px top and bottom on the row was 12px of pure height added to controls that already
     size themselves, and it sits on the price line, so it read as the overlay being deeper
     than it needed to be rather than as breathing room. */
  .pending-order-controls {
    gap: 4px;
    padding: 0;
  }

  .pending-order-overlay .po-btn {
    min-height: 24px;
    height: 24px;
    min-width: 28px;
    padding: 0 6px;
    font-size: 9px;
  }

  .pending-order-overlay .po-pnl {
    font-size: 9px;
    padding: 3px 7px;
  }

  .pending-order-overlay .po-btn.po-close {
    min-width: 0;
    padding-left: 6px;
    font-size: 13px;
  }

  /* Below the 44px guideline on purpose, as with the context menu: these are full-width
     cells in a list rather than icon squares, and the menu is pinned over the price
     action, where the height cost more than the target gained. */
  .quantity-option {
    min-height: 24px;
    height: auto;
    padding: 3px 6px;
    font-size: 10px;
    text-align: center;
  }

  /* --- Other chart overlays -------------------------------------------------
     Everything pinned over the chart competes with the candles for the same 248px of
     plot area. Trade Checker was the worst of them at 137x44 - 36% of the width - for
     a label whose own type is 13px; the rest of its height was the touch floor again.
     The ticker and indicator legend are read rather than tapped, so they only need to
     stay legible. */
  /* Price Alerts moved out of the bottom strip and into the ticker legend, which is where
     it belongs but also where the room ran out: the legend needs 196px and the badge 98px,
     into 274px of plot width, and the badge is pinned to the price scale, so the third icon
     landed entirely underneath it - drawn, and impossible to tap. The label is what goes:
     it costs 68px to repeat what the tick already says, the same trade the navbar makes
     when it strips its action buttons back to icons. The text node stays in the DOM, so
     the button keeps its accessible name, and its title still spells it out on long-press. */
  /* In the corner, on the ticker's own line: top 12px puts the button's 26px exactly over
     the ticker row (68-94px on a 375px window, the chart starting at 56), so it reads as
     part of that row rather than floating above it.

     The full "Trade Checker" again, with its tick (Luc, 2026-10-06). It used to be cut to
     "Checker" when the ticker's icons reached 250px; they end at 172 now, so the button -
     about 94px with 6px side padding - spans roughly 217-311 and still clears them by 45px.
     right: 64px keeps it inside the plot, a little clear of the price scale. */
  .trade-checker-btn {
    top: 12px;
    right: 64px;
    min-height: 26px;
    padding: 4px 6px;
    font-size: 10px;
    gap: 4px;
  }

  /* The tick stays on the phone too (Luc, 2026-10-06), a size down with the label. */
  .trade-checker-btn svg {
    width: 12px;
    height: 12px;
  }

  .indicator-badge-name {
    font-size: 10px;
  }

  .asset-ticker-overlay {
    font-size: 11px;
  }

  /* No room for the exchange on a phone: with it, the star and bookmark after the
     legend slid under the Trade Checker button in the same corner. */
  .asset-ticker-exchange,
  .asset-ticker-exchange-sep {
    display: none;
  }

  .asset-ticker-logo {
    width: 14px;
    height: 14px;
    font-size: 8px;
  }

  /* --- Reclaiming plot area -------------------------------------------------
     The tool column is 44px wide while the buttons inside it were already cut to 36px
     further up, so 8px of every phone screen was empty column taken permanently from
     the chart. The dark selector is repeated for the same reason it is above:
     .dark-mode .drawing-toolbar out-specifies a bare .drawing-toolbar.

     42 rather than the 36 this was first cut to. The column had been sized down twice over
     - once here and once on the buttons inside it - and between them the rail ended up the
     narrowest thing on the screen with 15px icons in it, which is small for a finger and
     small to read. The buttons go back to 36px below, so this is the same 3px of rail
     either side of them that the 36/30 pairing had; it costs 6px of plot width. */
  .drawing-toolbar,
  .dark-mode .drawing-toolbar {
    width: 42px;
    min-width: 42px;
  }

  /* Tracks the rail above: 42px here, and the navbar's padding is 6px rather than 12px. */
  .navbar-left {
    width: 42px;
    margin-left: -6px;
  }

  .navbar-left .profile-picture {
    width: 26px;
    height: 26px;
    font-size: 12px;
  }


  /* The strip is already icon-only here (font-size: 0 above), so its 44px was the
     touch floor rather than anything being drawn. The strip declares its own 44px
     height, so shrinking only the buttons left the difference as dead space. */
  .bottom-strip button {
    min-height: 36px;
    height: 36px;
  }

  /* The strip's content also ran 343px into 323px of room, leaving the UTC clock 20px
     past the right edge - hidden behind the overflow-x: auto set up above rather than
     visibly clipped, so it read as simply missing. The 15px desktop gap was the whole
     overage: it cost 60px across the four buttons, and dropping it to 8px brought the
     row to 315px. Price Alerts has since moved up into the chart legend, so three
     buttons remain and the row has ~48px more room than it needs. */
  .bottom-strip {
    height: 38px;
    gap: 8px;
  }

  /* --- Navbar ---------------------------------------------------------------
     Measured at 1114px of controls in a 375px viewport: logo 62 + centre group 800 +
     right group 220. It was set to scroll horizontally, which on a phone means two
     thirds of the buttons sit behind an invisible scrollbar - they are present but
     nobody can find them. Wrap onto as many rows as needed instead, and strip the
     labelled action buttons back to their icons so that costs two rows rather than four. */
  /* Fills .App rather than measuring the viewport a second time and risking a different
     answer than the one .App settled on. The padding reserves the row the bottom strip now
     occupies, since the strip is positioned rather than flowing at the end of this column. */
  .chart-container {
    height: 100%;
    padding-bottom: calc(38px + env(safe-area-inset-bottom));
    box-sizing: border-box;
  }

  .navbar {
    height: auto;
    min-height: 48px;
    overflow-x: visible;
    overflow-y: visible;
    /* 6px rather than 8 sides: with the symbol button sized to its label, BTC/USD landed
       on exactly 52px of text in a 52px box. scrollWidth and clientWidth are integers, so
       that reads as fitting while the renderer still ellipsises on the sub-pixel
       remainder. The extra 4px puts it clear of the boundary. */
    /* No top safe-area inset here. It belonged with the black-translucent status bar, where
       the web view sat underneath the clock and the navbar had to hold its own contents
       clear of it. With the default status bar style iOS reserves that strip itself and
       paints it with theme-color, so adding the inset as well counts the status bar twice:
       the whole column shifts down by its height and the bottom strip is pushed off the
       screen, out of reach. The strip below still takes the bottom inset, because the view
       does extend under the home indicator. */
    padding: 4px 6px;
    gap: 4px;
  }

  /* max-width/min-width matter as much as flex-wrap here: these groups are flex items, and
     a flex item is sized by its content, so without a ceiling they simply grew to 557px
     and carried their buttons off-screen instead of wrapping inside the navbar. */
  .navbar-left,
  .navbar-center,
  .navbar-right {
    flex-wrap: wrap;
    max-width: 100%;
    min-width: 0;
  }

  /* The centre group's 20px desktop gap costs 100px across its six controls - more than a
     quarter of the viewport spent on whitespace, which is what forced a second row. 4px
     rather than 5 buys back the last 5px a ticker like BTC/USD needs to render in full
     instead of ellipsising, and costs no touch target to do it. */
  .navbar-center,
  .navbar-right {
    gap: 4px;
  }

  /* The profile picture is the only thing left in the right group here - its icon
  /* Even with its icon buttons gone, the profile picture still wrapped: the right
     group's 20px margin put a single row at 365px against the 359px available, missing
     by 6. Without the margin it is 345px and fits. The centre group's auto left margin
     goes with it so the controls sit against the left edge and the remaining slack
     collects between them and the picture, which puts the picture on the right where it
     was before. */
  /* ...but collecting it all in one place put 99px of nothing between the last icon and the
     profile picture, which reads as two bars with a hole in the middle rather than one row.
     The group takes the slack instead and shares it out: every control grows by the same
     amount, so the four icon buttons stay identical to one another - nothing looks
     singled out - while the ticker and the timeframe keep the head start their labels
     give them, since growth is added to each control's own content width rather than
     forcing them all to one size. */
  .navbar-center {
    margin-left: 0;
    margin-right: 0;
    flex-grow: 1;
  }

  .navbar-center > * {
    flex-grow: 1;
    flex-basis: auto;
  }

  /* The timeframe control is a wrapper around its button, so the growth above landed on the
     wrapper and left the button at its old width with dead space beside it - a 21px hole in
     a row that was just closed up. Pass it through. */
  .navbar-center .timeframe-dropdown-container {
    display: flex;
  }

  .navbar-center .timeframe-dropdown-container > button {
    flex: 1 1 auto;
    width: 100%;
  }

  /* The picture is pulled 8px left to tuck against the divider it used to sit beside. That
     divider is hidden here, and now the controls reach the picture instead of stopping
     short of it, so the negative margin just laps it over the last icon. */
  .navbar .profile-picture {
    margin-left: 0;
  }

  /* Each separator is drawn 10px to the right of its own button, which centres it in the
     20px gap the desktop bar uses. These rows are tighter - 4px in the navbar, 8px in the
     bottom strip - so 10px carried the line past the gap entirely and set it down inside
     the next button's hit box, where it reads as belonging to that button rather than
     dividing the two. Each row gets the offset its own gap wants: half the gap, plus half
     the line's 1.5px width, so the line sits centred in the space between the hit boxes. */
  /* ...which held while the navbar's gap really was the 4px declared above. It is not any
     more: the row is justified with space-between (see the flat-row block at the end of
     this file), so the gap is whatever is left over after the buttons - 15.5px on a 375px
     screen, 24px on a 430px one. A line hung 2.75px off its own button therefore sits hard
     against that button with the whole remainder on the other side, which is the uneven
     space to the left of the painter, the scanner and the trading panel.
     No offset can be right at every width when the gap itself is measured at layout time,
     so the navbar's lines stop being decoration hung off a button and become items of the
     row instead - see .navbar-divider. space-between then puts the same space either side
     of every one of them, at any width, with nothing to keep in sync by hand.
     The bottom strip keeps the pseudo-element: its gap is a fixed 8px. */
  .navbar .symbol-btn::after,
  .navbar .timeframe-dropdown-btn::after,
  .navbar .indicators-btn::after {
    display: none;
  }

  .bottom-strip .indicators-btn::after {
    right: -4.75px;
  }

  /* Cancels the navbar's own 6px of right padding, the way .navbar-left cancels the
     padding on its side - without it the cell stops 6px short of the window and its
     edge misses the chart's divider by exactly that. */
  .navbar-right {
    margin-right: -6px;
  }

  /* The bar sets a 4px column gap between every pair of its children at this size, which
     is the one place the journal must not have one: it sits against the divider. Pulled
     back by exactly that gap. */
  .navbar > .journal-btn {
    margin-right: -4px;
  }


  /* Dropping that margin left only 14px spare, which held for a short ticker but not for
     a longer one: BTC/USD widens the symbol button from 72px to 92px, put the row 1px
     over 359, and wrapped the profile picture onto a second line again.

     Shaving pixels would leave the layout depending on how long the ticker is, so the
     symbol button is made the part that yields instead - its label already ellipsises.
     That needs nowrap: a flex container wraps before it shrinks, so with wrap left on,
     flex-shrink never gets the chance to act. Wrapping was the right call when this
     bar carried eleven controls, but the four icon buttons have moved into the profile
     menu and the seven that remain fit on one line once the symbol can compress. Nothing
     is hidden by this - unlike the horizontal scroll wrapping originally replaced. */
  .navbar,
  .navbar-center {
    flex-wrap: nowrap;
  }

  .navbar-center {
    flex-shrink: 1;
    min-width: 0;
  }

  /* Floor it so a long ticker ellipsises rather than collapsing to nothing. 56px rather
     than 64 to match the trimmed padding below - the old floor would have held the button
     wider than its own content once the chrome came off. */
  .navbar-center .symbol-btn {
    flex-shrink: 1;
    min-width: 56px;
  }

  .navbar-center > *:not(.symbol-btn) {
    flex-shrink: 0;
  }

  /* font-size:0 collapses the labels, which are bare text nodes on three of these four
     buttons and so cannot be hidden by selecting an element. The icons are SVG and are
     unaffected; the count badge sets its own size back below. Each keeps its title
     attribute, so the label is still available on long-press. */
  /* 40px rather than 44: at 44 the centre group needed 368px against the 359px available
     and tipped onto a second row, which cost more than the 4px per button saves. */
  .navbar .indicators-btn {
    font-size: 0;
    gap: 0;
    padding: 8px;
    min-width: 36px;
    width: 36px;
  }

  .navbar .indicators-btn .indicators-count {
    font-size: 10px;
  }

  /* .indicators-text declares font-size: 14px of its own, so it survived the font-size: 0
     above and kept the Indicators button at 101px while its siblings collapsed to 44px. */
  .navbar .indicators-text {
    display: none;
  }

  /* The wordmark was taking an entire row to itself. The symbol button is the other
     reason the centre group needed two rows - capped and ellipsised, the whole group
     fits on one, which brings the navbar down from four rows to two. */
  /* The coin logo (22px) left about 8px for the ticker, so "BTC/USD" ellipsised down to
     a bare "B". Dropping the logo gives the text room inside the same footprint. */
  .navbar .symbol-logo-small {
    display: none;
  }

  /* The market and timeframe controls are the only two labelled buttons left in the centre
     group - their four neighbours are already icon-only at 36px - so between them they
     took 159px of the 323px available. Both are trimmed to their text: side padding down
     from 12px to 8px and the icon gap from 6px to 4px, which pulls the button to roughly
     78px while still clearing BTC/USD at 11px without ellipsising. */
  /* No overflow: hidden here. The separator is drawn just outside the button's right edge,
     so clipping the button clipped the line away with it - which is why this was the one
     gap in the row without a divider while every other control had one. The ellipsis it was
     added for is already handled by .symbol-text below, which does its own clipping. */
  .navbar .symbol-btn {
    max-width: 96px;
    padding: 6px 8px;
    gap: 4px;
  }

  /* 11px keeps a seven-character ticker inside the narrower cap. Widening the button
     instead would push the centre group onto a second row at 375px. */
  .navbar .symbol-text {
    font-size: 11px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* 32px of side padding and an 8px gap around a two-character label ("1m") made this the
     second-widest control in the bar at 67px. The same trim brings it to about 44px. The
     44px height is deliberately left alone on both: it is the touch-target floor, and
     these sit in a row with four 44px-tall icon buttons that would no longer line up. */
  .navbar .timeframe-dropdown-btn {
    padding: 6px 8px;
    gap: 4px;
    font-size: 12px;
    min-width: 38px;
  }

  /* --- Strips and toolbars --------------------------------------------------
     The bottom strip holds more buttons than a phone is wide; scroll it rather than
     letting the overflow spill across the chart. */
  /* --- Replay transport ------------------------------------------------------
     The buttons are 28px by design and mobile.css's 44px floor was inflating all five,
     which took the bar to 261x58 sitting over the candles it is there to replay. Back to
     their intended size, with the padding and gaps trimmed to match, and the icons scaled
     with them. It already centres on the chart rather than the window - left: 50% resolves
     against the chart wrapper, not the viewport - so only the size needed changing.
     Lifted clear of the bottom strip, which is now pinned to the bottom of the screen. */
  .pb-controls {
    padding: 3px 5px;
    gap: 1px;
    bottom: calc(38px + env(safe-area-inset-bottom) + 10px);
    /* left: 50% is half of the chart wrapper, and the wrapper carries the price scale on
       its right, so the bar sat 28px right of the middle of the candles. Half the scale's
       width brings it back onto the plot. The variable is published from JS while replay is
       open; without it this is unchanged. */
    left: calc(50% - var(--price-scale-width, 0px) / 2);
  }

  .pb-btn {
    height: 28px;
    width: 28px;
    min-height: 0;
    min-width: 0;
    padding: 0;
    font-size: 10px;
  }

  .pb-btn--wide {
    width: auto;
    padding: 0 7px;
  }

  .pb-btn svg {
    width: 13px;
    height: 13px;
  }

  /* Taken out of the column and placed from the measured height instead.
     As the last item in a flex column the strip was only ever visible if everything above
     it added up to less than the screen, and on iOS that sum has been wrong in both
     directions - which is how it kept ending up below the bottom edge, out of reach.
     Positioned from the top by --app-height, it does not depend on that sum at all, and it
     does not depend on the browser's idea of where "bottom" is either: bottom: 0 resolves
     against the large viewport in Safari, which is the same trap as inset: 0. Falls back to
     dvh if the script has not run. .chart-container reserves the same height below, so
     nothing hides underneath it. */
  .bottom-strip {
    position: fixed;
    left: 0;
    right: 0;
    top: calc(var(--app-height, 100dvh) - 38px - env(safe-area-inset-bottom));
    z-index: 70;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    height: calc(38px + env(safe-area-inset-bottom));
    padding-bottom: env(safe-area-inset-bottom);
  }

  .bottom-strip::-webkit-scrollbar {
    display: none;
  }

  /* These buttons keep labels ("Chartify AI", "Trading Panel", ...) that are far wider
     than the 44px box mobile.css floors them at, and the strip was shrinking them on top
     of that - so the text spilled out and printed over the neighbouring button. Same
     icon-only treatment as the navbar, which fits all four plus the clock without
     scrolling, and flex-shrink: 0 stops the strip squeezing them again. */
  .bottom-strip > * {
    flex-shrink: 0;
  }

  /* The label stays written out here, unlike the navbar and the trade checker.
     Icon-only was the right trade when this strip carried four buttons and the row ran
     343px into 323px of room - see the note above. Price Alerts moved up into the chart
     legend since, and the strip is down to this one button plus the clock pinned to the
     right, so the room that was missing is now spare: at 375px the button needs about
     125px of the ~250px free before the clock.
     It is also the button that most needs its name. A speech bubble on its own reads as
     "chat", not as the thing that draws on your chart. */
  .bottom-strip .indicators-btn {
    font-size: 12px;
    gap: 6px;
    padding: 8px 12px;
    width: auto;
    min-width: 0;
  }

  .bottom-strip .indicators-count {
    font-size: 10px;
  }

  /* The tool column ran 784px of content into 756px of height, pushing Delete All
     Drawings past the bottom edge. Tightening the gap and padding recovers more than
     that, so every tool fits without scrolling. */
  /* .dark-mode .drawing-toolbar sets its own 12px padding and out-specifies a bare
     .drawing-toolbar, so the dark selector is repeated here to keep this deterministic
     rather than depending on which theme is active. */
  /* The gap went to 3px when this column still held every tool as its own button. The
     measurement tools, the fibs, the lines and the patterns have since collected behind
     five group buttons, so the run is ten buttons and two dividers - about 440px in the
     750 the column has. There is room to let them breathe again. */
  .drawing-toolbar,
  .dark-mode .drawing-toolbar {
    overflow-y: auto;
    padding: 4px 0;
    gap: 4px;
    scrollbar-width: none;
  }

  /* mobile.css floors every button at 44px; across ~15 tools that is 70px more than the
     column has between the navbar and the bottom strip, so the last tools fell off the
     bottom edge. 36px keeps them all on screen and is still a comfortable target.
     30 was the next cut, made because the rail was 36px wide and a 36px button was exactly
     as wide as the rail holding it - the selected highlight then drew straight onto the
     rail's own border with no gap at all. The rail is 42px now, so 36 restores the button
     to the size it was meant to be and still leaves that highlight 3px of rail either
     side. It is also the size the desktop rail uses, so the two now match. */
  .drawing-toolbar .tool-btn {
    min-height: 36px;
    height: 36px;
    min-width: 36px;
    width: 36px;
    padding: 0;
  }

  /* The glow spreads 8px in every direction from a button that has only 3px of rail beside
     it, so it washed over the edge however small the box got. The border and fill already
     mark the selection at this size. */
  .drawing-toolbar .tool-btn.active {
    box-shadow: none;
    border-radius: 10px;
  }

  /* Back to the shared 3px inset and 9px radius now the button is 36px again - the tighter
     pair here was for the 30px box, where the mark would otherwise have been barely wider
     than the icon inside it. */
  .drawing-toolbar .tool-btn::before {
    inset: 3px;
    border-radius: 9px;
  }

  /* Same one-control highlight here, on a 36px button in a 42px rail - so it reaches to
     the button's edge rather than past it, which is all the room there is. */
  .drawing-toolbar .tool-group .tool-btn::before {
    left: 0;
    right: 0;
  }

  /* 15px was the icon for a 30px button. On the 36px box it reads as undersized, and it
     was the smallest glyph anywhere in the app. This is the size the markup asks for. */
  .drawing-toolbar .tool-btn svg {
    width: 16px;
    height: 16px;
  }

  .drawing-toolbar::-webkit-scrollbar {
    display: none;
  }

  /* --- Floating popovers ----------------------------------------------------
     Both already clamp their left edge to the viewport in JS; this caps the width so a
     narrow phone cannot push them past the right edge either. */
  .info-tip-popover,
  .sensitivity-dropdown-menu,
  .context-menu {
    max-width: calc(100vw - 16px);
  }

  /* The chart's context menu opens under a double tap here, so it sits directly over the
     candles the tap was aimed at - at 186x208 it covered a quarter of the chart. These are
     the desktop paddings, sized for a pointer; the menu is a short list of four labels and
     reads fine much tighter. */
  .context-menu {
    min-width: 132px;
    padding: 5px;
    gap: 1px;
    border-radius: 10px;
  }

  /* Each item is a <button>, so mobile.css's 44px touch floor applied and held the rows at
     52px however little padding they were given - the same override the drawing toolbar
     needs. 34px is below that floor deliberately: these are list rows with the full width
     of the menu to hit, not 36px icon squares, so the row is still an easy target. */
  .context-menu-item {
    min-height: 30px;
    height: auto;
    padding: 5px 8px;
    gap: 7px;
    font-size: 11px;
    border-radius: 8px;
  }

  /* Declared at 14 on the element, so it needs overriding rather than inheriting. */
  .context-menu-item svg {
    width: 12px;
    height: 12px;
    flex: 0 0 auto;
  }

  /* "Alt + R" is a keyboard hint on a device with no keyboard to press it with, and at 48px
     of text plus its 16px gutter it was the widest thing in the row after the label - it,
     not the min-width, was holding the menu at 174px. */
  .context-menu-shortcut {
    display: none;
  }

  /* --- Bottom-strip panels --------------------------------------------------
     The four buttons in the bottom strip (Chartify AI, Trading Panel, Journal, Alerts)
     open panels sized for a desktop column. The dialog rule at the top of this block
     catches the ones that are centred overlays; these two are not. */

  /* The assistant docks rather than floating: .chatbot-modal.ai-side-panel is a flow
     child of .ai-panel-dock, which begins after the 52px tool rail. calc(100vw - 44px)
     is measured from the viewport, not from where the panel actually starts, so a 331px
     panel opening at x=54 ended at 385 on a 375px screen and lost its right edge - the
     scroll-to-bottom control and the composer's send button sat in the missing 10px.
     Both boxes need the cap, since the dock was the wider of the two at 380px. */
  /* The dock is a flex sibling of the chart, which is right when there is room for two
     columns. On a phone there is not: 313px of panel beside the 36px tool rail left the
     chart itself 10px wide - the candles were gone, and the Trade Checker button, which
     positions itself from the chart's width, was pushed to -91 and off the screen
     entirely. Taking the dock out of the flow lets the chart keep its full width and the
     panel sit over it, which is how a phone shows a side panel anyway.
     .chart-layout is already position: relative, so this anchors to it. */
  /* The assistant and the painter open where the market and indicator tabs open: same
     centre, same size, same backdrop. The assistant reaches this from a docked column and
     the painter from a corner anchor, so both need their own positioning undone -
     .ai-side-panel is position: relative inside the dock, and .chatbot-modal is absolute at
     left: 52px, bottom: 54px. Sizes come from the shared dialog rule at the top of this
     block; .ai-side-panel additionally clears height: 100% and max-height: none, which it
     sets to fill the column it no longer sits in.
     Lifting the panel out of the dock's flow also leaves the chart its full width, which is
     what the dock override here used to be for. */
  .chatbot-modal,
  .chatbot-modal.ai-side-panel {
    position: fixed !important;
    top: 50% !important;
    left: 50% !important;
    right: auto !important;
    bottom: auto !important;
    transform: translate(-50%, -50%) !important;
    height: auto !important;
    max-height: 68vh !important;
    max-height: 68dvh !important;
    animation: none;
    /* Der hohe Wert zurueck, den die angedockte Regel weggenommen hat: hier ist der
       Assistent eine schwebende Karte und hat ein eigenes .modal-overlay unter sich
       (nur auf dem Telefon gerendert), ueber dem er stehen muss. */
    z-index: 10000;
  }

  /* A centred card here rather than a docked column - nothing to sit flush against, so it
     keeps the frame the docked one drops, and skips the entrance (which would fight the
     centring transform above in any case). Written with .dark-mode to match the rule that
     squares the docked panel: at a lower specificity that rule would win here too and
     leave this card square with a single edge down one side. */
  .chatbot-modal.ai-side-panel,
  .dark-mode .chatbot-modal.ai-side-panel {
    border: 1px solid var(--bk-border);
    border-radius: 16px;
  }

  /* Empty once the panel above is lifted out of it, and nothing left to resize by hand. */
  .ai-panel-dock {
    width: 0 !important;
    min-width: 0;
    /* Padding as well as width: an empty dock still measured 8px, and it is a flex sibling
       of the chart, so that came straight off the chart's width. */
    padding: 0 !important;
    border: 0 !important;
    overflow: visible;
  }

  .ai-panel-resizer {
    display: none;
  }

  /* With the field raised to 16px above, it was left 139px of the composer's 275 - the mode
     picker, credit count and send button take the rest - and "Ask about this chart..."
     wrapped to two lines inside a one-line box. Letting the composer wrap puts the field on
     its own row at 253px, which is what the space wants on a phone regardless. */
  .chatbot-modal.ai-side-panel .ai-composer {
    flex-wrap: wrap;
  }

  .chatbot-modal.ai-side-panel .ai-composer > textarea {
    flex: 1 1 100%;
  }

  .chatbot-modal.ai-side-panel .ai-composer-right {
    margin-left: auto;
  }

  /* The journal's "i" badges are 18px wide, but each carries a 260px tooltip in ::after,
     absolutely positioned and centred on the badge. It is hidden with visibility rather
     than display, and a visibility: hidden box still contributes to scrollWidth - so all
     23 of them pushed ~138px of invisible overflow into whatever tile they sat in, 26px
     of which reached the dashboard itself. Taking the tooltip out of layout until it is
     wanted removes that entirely. The width cap then keeps the tooltip on screen when it
     does appear, which a 260px box centred inside a 331px panel could not manage. */
  .journal-stat-info::after,
  .journal-stat-info::before {
    display: none;
  }

  .journal-stat-info:hover::after,
  .journal-stat-info:hover::before {
    display: block;
  }

  .journal-stat-info:hover::after {
    width: min(220px, calc(100vw - 80px));
  }

  /* The bottom strip's alerts panel is built from inline styles with no class of its own,
     so nothing here could reach it - and it could not borrow .alert-modal, which
     AlertModal.css already owns and styles for a different component. It gets its own hook
     instead. !important throughout because the values being overridden are inline, and the
     numbers match the dialog rule at the top of this block so the two line up when the
     bottom strip switches between panels rather than shifting by 3px. */
  .price-alerts-modal {
    width: calc(100vw - 44px) !important;
    max-width: calc(100vw - 44px) !important;
    max-height: 68vh !important;
    max-height: 68dvh !important;
    padding: 14px !important;
    border-radius: 14px !important;
  }

  .price-alerts-modal h2 {
    font-size: 16px !important;
  }
}

/* ---- Chartify AI: working steps and streamed text -------------------------- */
/* The assistant can spend half a minute reading candles and drawing before it
   says anything. These are the two things that make that wait legible: a list of
   what it is doing, and text that arrives as it is written. */

.ai-side-panel .message-body {
  display: flex;
  flex-direction: column;
  gap: 7px;
  min-width: 0;
  flex: 1;
}

.ai-side-panel .ai-step-list {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 7px 9px;
  border-radius: 9px;
  background: rgba(142, 142, 147, 0.08);
  border: 1px solid rgba(142, 142, 147, 0.12);
  font-size: 11.5px;
  line-height: 1.35;
}

.chatbot-modal.ai-side-panel.dark-mode .ai-step-list {
  background: rgba(255, 255, 255, 0.035);
  border-color: var(--bk-border);
}

.ai-side-panel .ai-step {
  display: flex;
  align-items: baseline;
  gap: 6px;
  color: var(--bk-text-3);
}

/* Each step slides in as it is announced, so the list reads as work being done.
   Only while live: the settled copy of a reply is a different DOM element, and
   replaying the entry animation there made the finished answer look like it
   flickered out and back the moment it completed. */
.ai-side-panel .ai-step-list.is-live .ai-step {
  animation: aiStepIn 0.22s ease-out both;
}

.chatbot-modal.ai-side-panel.dark-mode .ai-step { color: var(--bk-text-2); }

@keyframes aiPanelIn {
  from { transform: translateX(100%); }
  to { transform: translateX(0); }
}

@keyframes aiStepIn {
  from { opacity: 0; transform: translateY(-2px); }
  to   { opacity: 1; transform: none; }
}

.ai-side-panel .ai-step.running { color: var(--ai-accent); }
.chatbot-modal.ai-side-panel.dark-mode .ai-step.running { color: var(--ai-accent); }
.ai-side-panel .ai-step.done .ai-step-icon { color: #34C759; }
.ai-side-panel .ai-step.error .ai-step-icon { color: #FF9500; }

.ai-side-panel .ai-step-icon {
  width: 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  align-self: center;
}

.ai-side-panel .ai-step-spinner {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 1.5px solid currentColor;
  border-top-color: transparent;
  animation: aiSpin 0.65s linear infinite;
}

@keyframes aiSpin { to { transform: rotate(360deg); } }

/* Label and detail share a wrapping row, so a long detail drops to its own
   line under the label instead of being clipped in a narrow panel. */
.ai-side-panel .ai-step-text {
  display: flex;
  flex-wrap: wrap;
  gap: 0 6px;
  min-width: 0;
}

.ai-side-panel .ai-step-label { flex: 0 0 auto; }

.ai-side-panel .ai-step-detail {
  color: #AEAEB2;
  font-variant-numeric: tabular-nums;
  min-width: 0;
  overflow-wrap: anywhere;
}

.chatbot-modal.ai-side-panel.dark-mode .ai-step-detail { color: var(--bk-text-3); }

@media (prefers-reduced-motion: reduce) {
  .ai-side-panel .ai-step { animation: none; }
}

/* ---- Chartify AI: reading surface ------------------------------------------ */
/* Rewritten to read like a document rather than a chat toy. Three decisions do
   most of the work: the user's turn is a neutral chip instead of a saturated
   blue banner, the assistant is plain prose with no bubble and no avatar, and
   the vertical rhythm is set here rather than by inline styles. Brand blue is
   spent only where it means something - the send button and a running step. */

.chatbot-modal.ai-side-panel .chatbot-messages {
  padding: 18px 16px 8px;
  gap: 0;
}

.ai-side-panel .chat-message {
  gap: 0;
  margin: 0 0 22px;
  align-items: flex-start;
}

.ai-side-panel .chat-message:last-child { margin-bottom: 6px; }

/* The reader's own words: sized to content, right-aligned, quiet. */
.ai-side-panel .chat-message.user .message-content,
.chatbot-modal.ai-side-panel.dark-mode .chat-message.user .message-content {
  background: rgba(120, 120, 128, 0.10);
  color: #1D1D1F;
  border-radius: 16px;
  padding: 9px 14px;
  font-size: 13.5px;
  line-height: 1.55;
  max-width: 88%;
  width: fit-content;
  margin-left: auto;
}

.chatbot-modal.ai-side-panel.dark-mode .chat-message.user .message-content {
  background: rgba(255, 255, 255, 0.08);
  color: #F2F2F7;
}

.ai-side-panel .chat-message.assistant .message-content,
.chatbot-modal.ai-side-panel.dark-mode .chat-message.assistant .message-content {
  font-size: 13.5px;
  line-height: 1.68;
  color: #1D1D1F;
  letter-spacing: -0.003em;
}

.chatbot-modal.ai-side-panel.dark-mode .chat-message.assistant .message-content {
  color: #E8E8ED;
}

.ai-side-panel .message-body { gap: 12px; }

/* Vertical rhythm for the prose itself. */
.ai-side-panel .chat-line { margin: 0; }
.ai-side-panel .chat-line + .chat-line { margin-top: 0.55em; }
.ai-side-panel .chat-gap { height: 0.7em; }

.ai-side-panel .chat-bullet {
  display: flex;
  gap: 9px;
  padding-left: 2px;
}
.ai-side-panel .chat-bullet + .chat-bullet { margin-top: 0.3em; }
.ai-side-panel .chat-bullet-dot {
  flex: 0 0 auto;
  opacity: 0.45;
  line-height: inherit;
}

.ai-side-panel .message-content strong {
  font-weight: 600;
  letter-spacing: -0.005em;
}

/* Steps sit between paragraphs, so they read as an aside: no border, barely a
   background, and a tick that confirms rather than shouts. */
.ai-side-panel .ai-step-list {
  background: rgba(120, 120, 128, 0.055);
  border: none;
  border-radius: 10px;
  padding: 8px 11px;
  gap: 5px;
  font-size: 11.5px;
  line-height: 1.4;
}

.chatbot-modal.ai-side-panel.dark-mode .ai-step-list {
  background: rgba(255, 255, 255, 0.045);
}

.ai-side-panel .ai-step { color: #86868B; gap: 8px; }
.chatbot-modal.ai-side-panel.dark-mode .ai-step { color: var(--bk-text-2); }

.ai-side-panel .ai-step.done .ai-step-icon { color: #34C759; opacity: 0.9; }
.ai-side-panel .ai-step.running { color: var(--ai-accent); }
.chatbot-modal.ai-side-panel.dark-mode .ai-step.running { color: var(--ai-accent); }

.ai-side-panel .ai-step-label { font-weight: 500; }

.ai-side-panel .ai-step-detail {
  color: #AEAEB2;
  font-weight: 400;
}
.chatbot-modal.ai-side-panel.dark-mode .ai-step-detail { color: var(--bk-text-3); }

/* The caret should sit with the text, not jitter the line height. */
.ai-side-panel .message-content.is-streaming .chat-line:last-child::after {
  content: '';
  display: inline-block;
  width: 2px;
  height: 1em;
  margin-left: 3px;
  vertical-align: -0.14em;
  border-radius: 1px;
  background: currentColor;
  opacity: 0.5;
  animation: aiCaret 1.1s ease-in-out infinite;
}

@keyframes aiCaret {
  0%, 45% { opacity: 0.5; }
  55%, 100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .ai-side-panel .message-content.is-streaming .chat-line:last-child::after { animation: none; }
}

/* ---- Chartify AI: composer controls ---------------------------------------- */
/* Depth and balance sit inside the input box on their own row, so the composer
   reads as one object instead of a field with a strip of controls floating under
   it. The trigger is deliberately quiet - it is a setting, not an action. */

/* One row, as before: the input grows, the controls trail it. Stacking them
   nearly doubled the composer's height for no gain. */
.ai-side-panel .ai-composer-right {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
}

.ai-side-panel .ai-mode-picker { position: relative; }

.ai-side-panel .ai-mode-trigger {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border: none;
  background: transparent;
  color: #86868B;
  font-family: inherit;
  font-size: 11.5px;
  font-weight: 500;
  /* Pinned to the send button's height. Left to itself the panel's button
     styling rendered this at 40px and pushed the whole composer taller. */
  height: 30px;
  line-height: 1;
  padding: 0 7px 0 9px;
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.13s ease, color 0.13s ease;
}

.ai-side-panel .ai-mode-trigger:hover:not(:disabled),
.ai-side-panel .ai-mode-trigger.open {
  background: rgba(120, 120, 128, 0.10);
  color: #1D1D1F;
}

.chatbot-modal.ai-side-panel.dark-mode .ai-mode-trigger:hover:not(:disabled),
.chatbot-modal.ai-side-panel.dark-mode .ai-mode-trigger.open {
  background: rgba(255, 255, 255, 0.08);
  color: #F2F2F7;
}

.ai-side-panel .ai-mode-trigger:disabled { opacity: 0.45; cursor: default; }
.ai-side-panel .ai-mode-trigger svg { opacity: 0.7; }

/* Opens upward: the composer is pinned to the bottom of the panel. */
.ai-side-panel .ai-mode-menu {
  position: absolute;
  bottom: calc(100% + 8px);
  right: 0;
  z-index: 30;
  width: 208px;
  padding: 4px;
  border-radius: 12px;
  background: #FFFFFF;
  border: 1px solid rgba(0, 0, 0, 0.08);
  box-shadow: 0 8px 26px rgba(0, 0, 0, 0.13);
  animation: aiMenuIn 0.13s ease-out both;
  /* Die Hoehe und Breite, die hier wirklich zur Verfuegung stehen, misst die Komponente
     und setzt sie als max-height/max-width am Element - .chatbot-modal schneidet seinen
     Ueberlauf ab, und in einem niedrigen Fenster war der Kopf der Liste weg. Ueberzaehlige
     Zeilen scrollen dann innerhalb des Menues, statt aus ihm herauszulaufen.

     min-width, damit die gemessene Breite die Liste zusammenschieben kann, ohne dass die
     Zeilen zu Buchstabensalat werden. Der Wert ist die schmalste Blurb-Zeile, die noch in
     zwei Zeilen umbricht. */
  min-width: 176px;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Auf der Farbe der drei Leisten, wie die uebrigen Menues der App - vorher #101010 und
   damit eine Stufe dunkler als alles, was um es herum steht. Der Grund darunter ist der
   Assistent selbst, der auf --bk-shell steht, also loest sich das Menue weiterhin ab. */
.chatbot-modal.ai-side-panel.dark-mode .ai-mode-menu {
  background: var(--bk-elevated);
  border-color: var(--bk-border);
  box-shadow: 0 8px 26px rgba(0, 0, 0, 0.5);
}

@keyframes aiMenuIn {
  from { opacity: 0; transform: translateY(3px); }
  to   { opacity: 1; transform: none; }
}

.ai-side-panel .ai-mode-option {
  display: flex;
  flex-direction: column;
  /* The panel centres its buttons' contents by default, which shrink-wrapped the
     label row and left the option looking centred. Both are pinned here. */
  align-items: stretch;
  gap: 1px;
  width: 100%;
  text-align: left;
  border: none;
  background: transparent;
  padding: 7px 9px;
  border-radius: 8px;
  cursor: pointer;
  font-family: inherit;
  transition: background 0.12s ease;
}

.ai-side-panel .ai-mode-option:hover { background: rgba(120, 120, 128, 0.10); }
.chatbot-modal.ai-side-panel.dark-mode .ai-mode-option:hover { background: rgba(255, 255, 255, 0.07); }

.ai-side-panel .ai-mode-option-head {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  color: #1D1D1F;
  font-size: 12.5px;
  font-weight: 500;
}

.chatbot-modal.ai-side-panel.dark-mode .ai-mode-option-head { color: #F2F2F7; }
.ai-side-panel .ai-mode-option.selected .ai-mode-option-head svg { color: var(--ai-accent); }
.chatbot-modal.ai-side-panel.dark-mode .ai-mode-option.selected .ai-mode-option-head svg { color: var(--ai-accent); }

.ai-side-panel .ai-mode-option-blurb {
  font-size: 11px;
  line-height: 1.35;
  color: #86868B;
}

.chatbot-modal.ai-side-panel.dark-mode .ai-mode-option-blurb { color: var(--bk-text-2); }

/* Just the number, in the header. "Credits" is carried by the tooltip; spelling
   it out beside the title competes with the symbol line for attention. */
.ai-side-panel .ai-credits {
  font-size: 11.5px;
  font-weight: 500;
  color: #86868B;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  cursor: default;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 2px 7px 2px 6px;
  margin-right: 2px;
  border-radius: 6px;
  background: rgba(120, 120, 128, 0.10);
}

.ai-side-panel .ai-credits svg { opacity: 0.75; flex: 0 0 auto; }

.chatbot-modal.ai-side-panel.dark-mode .ai-credits {
  background: rgba(255, 255, 255, 0.07);
  color: var(--bk-text-2);
}

.ai-side-panel .ai-credits.empty,
.chatbot-modal.ai-side-panel.dark-mode .ai-credits.empty {
  color: #FF9500;
  background: rgba(255, 149, 0, 0.12);
}

@media (prefers-reduced-motion: reduce) {
  .ai-side-panel .ai-mode-menu { animation: none; }
}

/* ---- Chartify AI: undo the send-button styling on composer controls --------- */
/* The mode picker and its menu sit inside .chatbot-input, where `button` is
   styled as the round blue send button - 40px, 50% radius, and a dark blue
   hover that outranks a plain .ai-* rule (0,3,1 beats 0,3,0). That is why an
   option turned blue on hover and why the two-line rows were being squeezed
   into a 40px circle. These carry .chatbot-modal to win on specificity and
   reset the geometry the send button imposed. */

.chatbot-modal.ai-side-panel .chatbot-input .ai-mode-trigger {
  width: auto;
  min-width: 0;
  border-radius: 8px;
  transform: none;
  box-shadow: none;
}

/* Fills the menu. Undoing the send button's `width: 40px` with `auto` left each
   row shrink-wrapped to its text, so the highlight stopped short of the edge. */
.chatbot-modal.ai-side-panel .chatbot-input .ai-mode-option {
  width: 100%;
  min-width: 0;
  border-radius: 8px;
  transform: none;
  box-shadow: none;
}

.chatbot-modal.ai-side-panel .chatbot-input .ai-mode-option {
  height: auto;
  min-height: 0;
  padding: 8px 10px;
  border-radius: 8px;
  background: transparent;
  color: inherit;
}

.chatbot-modal.ai-side-panel .chatbot-input .ai-mode-trigger {
  height: 30px;
  background: transparent;
  color: #86868B;
}

/* Hover, at a specificity the send button's rule cannot outrank. */
.chatbot-modal.ai-side-panel .chatbot-input .ai-mode-trigger:hover:not(:disabled),
.chatbot-modal.ai-side-panel .chatbot-input .ai-mode-trigger.open {
  background: rgba(120, 120, 128, 0.12);
  color: #1D1D1F;
  transform: none;
}

.chatbot-modal.ai-side-panel.dark-mode .chatbot-input .ai-mode-trigger { color: var(--bk-text-2); }

.chatbot-modal.ai-side-panel.dark-mode .chatbot-input .ai-mode-trigger:hover:not(:disabled),
.chatbot-modal.ai-side-panel.dark-mode .chatbot-input .ai-mode-trigger.open {
  background: rgba(255, 255, 255, 0.10);
  color: #F2F2F7;
}

.chatbot-modal.ai-side-panel .chatbot-input .ai-mode-option:hover:not(:disabled) {
  background: rgba(120, 120, 128, 0.12);
  color: inherit;
  transform: none;
}

.chatbot-modal.ai-side-panel.dark-mode .chatbot-input .ai-mode-option:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.08);
}

/* Room for two lines of text, and a width that suits the panel. */
.chatbot-modal.ai-side-panel .ai-mode-menu {
  width: 232px;
  padding: 5px;
}

/* ---- Chartify AI: the reply's mark ----------------------------------------- */
/* Sits at the foot of each answer. It turns while the reply is being written and
   comes to rest when it is finished, so the panel reads as busy or done without
   a separate spinner taking up a line. */

/* The mark and the undo offer share a row under the newest reply. The mark keeps its
   place at the left; the button sits beside it rather than under the text, so a reply
   that changed nothing looks exactly as it did before. */
.ai-side-panel .ai-message-footer {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Quiet by default. Taking back what the assistant just did is a correction, not the
   expected next step, so it reads as a footnote until the pointer is on it. */
.ai-side-panel .ai-undo-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px 3px 7px;
  margin-top: 2px;
  border: 1px solid var(--bk-border);
  border-radius: 999px;
  background: transparent;
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  color: var(--bk-text-2);
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}

.ai-side-panel .ai-undo-btn:hover {
  color: var(--bk-text);
  border-color: var(--bk-text-2);
  background: var(--bk-hover);
}

.ai-side-panel .ai-undo-btn svg {
  flex-shrink: 0;
}

.ai-side-panel .ai-message-mark {
  display: flex;
  align-items: center;
  height: 18px;
  margin-top: 2px;
  color: #C7C7CC;
  transition: color 0.4s ease;
}

.chatbot-modal.ai-side-panel.dark-mode .ai-message-mark { color: #48484A; }

.ai-side-panel .ai-message-mark.thinking { color: var(--ai-accent); }
.chatbot-modal.ai-side-panel.dark-mode .ai-message-mark.thinking { color: var(--ai-accent); }

/* A slow turn with a slight breath to it - fast enough to read as working,
   slow enough not to pull the eye off the text being written beside it. */
.ai-side-panel .ai-message-mark.thinking svg {
  animation: aiMarkWorking 1.9s cubic-bezier(0.45, 0, 0.25, 1) infinite;
  transform-origin: 50% 50%;
}

@keyframes aiMarkWorking {
  0%   { transform: rotate(0deg)   scale(1); }
  50%  { transform: rotate(180deg) scale(0.78); }
  100% { transform: rotate(360deg) scale(1); }
}

/* Settling in, so a finished mark doesn't just pop into place. */
.ai-side-panel .ai-message-mark:not(.thinking) svg {
  animation: aiMarkSettle 0.45s cubic-bezier(0.2, 0.8, 0.3, 1) both;
}

@keyframes aiMarkSettle {
  from { transform: rotate(-70deg) scale(0.85); opacity: 0.4; }
  to   { transform: none; opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .ai-side-panel .ai-message-mark svg,
  .ai-side-panel .ai-message-mark.thinking svg { animation: none; }
}

/* A reply is already on screen by the time it finishes: it was streamed in word
   by word. The generic `.chat-message { animation: fadeIn }` then replayed on the
   stored copy - a different DOM element - so the finished answer visibly faded
   out and back. The streaming reveal is the entry animation for a reply; the
   user's own turn still fades in, since that one really does appear at once. */
.ai-side-panel .chat-message.assistant {
  animation: none;
}

/* Scales & Lines tab -------------------------------------------------------------- */

/* A switch rather than a bare checkbox, to match the weight of the controls in the
   Style tab next to it. */
.chart-settings-switch {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
}

.chart-settings-switch input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

.chart-settings-switch-track {
  position: relative;
  display: block;
  width: 40px;
  height: 24px;
  border-radius: 12px;
  background: rgba(120, 120, 128, 0.32);
  transition: background 0.18s ease;
}

.chart-settings-switch-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #FFFFFF;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
  transition: transform 0.18s ease;
}

.chart-settings-switch input:checked + .chart-settings-switch-track {
  background: #34C759;
}

.chart-settings-switch input:checked + .chart-settings-switch-track .chart-settings-switch-thumb {
  transform: translateX(16px);
}

.chart-settings-switch input:focus-visible + .chart-settings-switch-track {
  box-shadow: 0 0 0 3px rgba(52, 199, 89, 0.25);
}

.chart-settings-hint {
  margin: 8px 2px 0;
  font-size: 12px;
  line-height: 1.45;
  color: #8E8E93;
}

/* Backtest dashboard.
 *
 * Built exactly like the panel it is modelled on: a title bar, then a rule, then rows of
 * label-left / value-right - a header row naming the metric, the two win rates, and the two
 * settings that produced the better one. No emoji and no close button, matching that source;
 * the settings checkbox is what turns it off.
 *
 * The colours are this app's rather than the source's navy, so the panel belongs to the chart
 * it sits on and follows the theme. Every rule is scoped under .backtest-dashboard on purpose:
 * BacktestResultsModal.css also defines .backtest-stat-label and .backtest-stat-value, and an
 * unscoped rule here would reach into the modal.
 */
.backtest-dashboard {
  position: absolute;
  top: 58px;
  right: 10px;
  width: 200px;
  background: rgba(255, 255, 255, 0.96);
  backdrop-filter: blur(40px) saturate(180%);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  border: 1px solid rgba(142, 142, 147, 0.28);
  border-radius: 8px;
  padding: 0;
  z-index: 50;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
  font-family: var(--font-ui);
  overflow: hidden;
  user-select: none;
  cursor: grab;
  /* Without this the browser claims a finger on the card as a scroll and the drag never
     starts - the pointer events fire once and then stop coming. */
  touch-action: none;
}

.backtest-dashboard:active {
  cursor: grabbing;
}

/* Grip, title, and an empty cell the same width as the grip - so the title sits centred
   rather than shunted right by the dots. The whole bar is the drag surface. */
.backtest-dashboard-header {
  display: grid;
  grid-template-columns: 14px 1fr 14px;
  align-items: center;
  gap: 6px;
  padding: 7px 10px;
  border-bottom: 1px solid rgba(142, 142, 147, 0.28);
  text-align: center;
}

.backtest-dashboard-grip {
  display: flex;
  align-items: center;
  color: #C7C7CC;
}

.backtest-dashboard-header:hover .backtest-dashboard-grip {
  color: #8E8E93;
}

.backtest-dashboard-title {
  font-size: 12px;
  font-weight: 700;
  color: #1D1D1F;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

/* Label left, value right - the shape of every row in the panel. */
.backtest-dashboard-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 5px 10px;
}

.backtest-dashboard-row.head {
  border-bottom: 1px solid rgba(142, 142, 147, 0.2);
}

.backtest-dashboard-cell {
  font-size: 12px;
  line-height: 1.3;
}

.backtest-dashboard-cell.label {
  color: var(--bk-text-3);
  font-weight: 600;
}

.backtest-dashboard-row.head .backtest-dashboard-cell {
  color: #1D1D1F;
  font-weight: 700;
}

/* Tabular figures so the percentages line up down the column and do not jitter as digits
   change under a live re-run. */
.backtest-dashboard-cell.value {
  color: #1D1D1F;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.backtest-dashboard-cell.value.best {
  color: #10B981;
}

.backtest-dashboard-empty {
  padding: 10px;
  font-size: 11px;
  line-height: 1.45;
  color: var(--bk-text-3);
}

/* -------------------------------------------------------------------------- dark theme */

.dark-mode .backtest-dashboard {
  background: rgba(28, 28, 30, 0.96);
  border-color: var(--bk-border);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);
}

.dark-mode .backtest-dashboard-header {
  border-bottom-color: var(--bk-border);
}

.dark-mode .backtest-dashboard-row.head {
  border-bottom-color: var(--bk-border);
}

.dark-mode .backtest-dashboard-title,
.dark-mode .backtest-dashboard-row.head .backtest-dashboard-cell,
.dark-mode .backtest-dashboard-cell.value {
  color: #F7F7F7;
}

.dark-mode .backtest-dashboard-cell.label,
.dark-mode .backtest-dashboard-empty {
  color: var(--bk-text-2);
}

.dark-mode .backtest-dashboard-grip {
  color: var(--bk-text-3);
}

.dark-mode .backtest-dashboard-header:hover .backtest-dashboard-grip {
  color: var(--bk-text-2);
}

.dark-mode .backtest-dashboard-cell.value.best {
  color: #34d399;
}

/* On a phone the chart is about 320px wide, so a plate pinned to the top right lands on the
   indicator badges - measured at 375px, the badge row runs to x=223 and the panel began at
   x=192. Dropping it below that row clears the badges and the BUY/SELL controls above them
   (which end at y=132) rather than shaving pixels off the width until it happens to fit. */
@media (max-width: 768px), (max-height: 500px) and (orientation: landscape) {
  .backtest-dashboard {
    top: 122px;
    right: 6px;
    /* 184 rather than 168: the header is a 14px grip, the title, a 14px spacer and two 6px
       gaps, and at 168 the title's own width pushed that past the content box, so the grid
       overflowed and the title sat 8px off centre. */
    width: 184px;
  }

  .backtest-dashboard-title { font-size: 11px; }
  .backtest-dashboard-cell { font-size: 11px; }
  .backtest-dashboard-row { padding: 4px 8px; }
}

/* ========================================
   MULTI-CHART PANES
   ======================================== */

/* The grid the panes sit in. One pane and it is indistinguishable from the single chart,
   because a 1x1 grid of a full-size cell is exactly that. */
.chart-grid {
  display: grid;
  width: 100vw;
  height: 100dvh;
  height: 100vh;
  gap: 1px;
  /* Neutral enough to read as a divider in both themes without a theme class. */
  background: rgba(142, 142, 147, 0.45);
}

/* The arrangement itself is an inline grid-template on the element: it is a number of rows
   by a number of columns chosen at runtime, and enumerating 16 class pairs here to say what
   `repeat(n, 1fr)` already says would be a list to keep in step with the picker. */

/* A pane is a chart-container that has given up its claim on the viewport.
   .chart-container is width:100vw/height:100dvh - correct for the only chart on the page,
   wrong for a cell in a grid, which must take the size the grid gives it. */
.chart-pane > .chart-container {
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
}

.chart-pane {
  position: relative;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
}

/* Which pane the navbar and the tool rail are acting on. Deliberately a thin inset line
   rather than a border: a border would take a pixel off the chart and shift the candles
   every time the active pane changed. */
.chart-pane.active::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  box-shadow: inset 0 0 0 2px rgba(16, 185, 129, 0.55);
  z-index: 60;
}

/* Multi-chart is desktop only. The single-chart layout already reshapes 15+ regions for a
   phone; splitting that in half again would leave nothing usable. */
@media (max-width: 768px), (max-height: 500px) and (orientation: landscape) {
  .chart-grid {
    /* !important because the arrangement arrives as an inline style, and an inline style
       outranks anything a stylesheet can say without it. */
    grid-template-columns: 1fr !important;
    grid-template-rows: 1fr !important;
  }

  .chart-grid .chart-pane:not(.active) {
    display: none;
  }
}

/* The chrome spans the whole window, even though it lives inside one pane.
 *
 * The navbar, tool rail and bottom strip are rendered by the primary pane, so in a grid
 * they are laid out inside that pane's cell - measured at 640px of a 1280px window, i.e.
 * a navbar over the left chart and nothing over the right one.
 *
 * The honest fix is to lift the chrome out of the component and put it above the grid, and
 * that is the multi-week extraction this staging deliberately defers. Pinning it to the
 * viewport gets the same picture with no JSX moved: the elements stay where they are in the
 * tree, owned by the active pane, and are simply painted across the full width. The grid
 * insets itself by their heights so no pane sits underneath them.
 *
 * Scoped under .chart-grid, so the single chart - which has no grid - is untouched.
 */
.chart-grid {
  padding-top: 48px;    /* navbar */
  padding-bottom: 44px; /* bottom strip */
  padding-left: 44px;   /* tool rail */
  box-sizing: border-box;
}

.chart-grid .navbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  width: auto;
  z-index: 120;
}

.chart-grid .bottom-strip {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  width: auto;
  z-index: 120;
}

.chart-grid .drawing-toolbar {
  position: fixed;
  top: 48px;
  bottom: 44px;
  left: 0;
  z-index: 120;
}

/* The panes sit inside the padding, so their own containers must not try to be the window. */
.chart-grid .chart-pane > .chart-container {
  width: 100%;
  height: 100%;
}

/* Below the navbar (z-index 100), not above it. The navbar is a stacking context, so a
   backdrop above it swallows the click on the very button that opened the menu and the
   button then reopens it - the menu could never be closed from its own trigger. Down here
   it still catches every click outside the navbar, and the other navbar buttons close the
   menu themselves through closeNavbarPanels. */
.layout-sync-backdrop {
  position: fixed;
  inset: 0;
  z-index: 99;
}

/* The layout panel.
   ─────────────────
   Two columns: the arrangement on the left, what the panes share on the right. They sit
   side by side rather than stacked because they are answers to two different questions and
   a single column made the second one look like a continuation of the first.

   Fixed, not absolute: it is mounted outside the navbar, and the top/right below are the
   button's usual resting place, overwritten inline with its measured position on open. */
.layout-sync-menu {
  position: fixed;
  top: 52px;
  right: 96px;
  z-index: 201;
  display: flex;
  align-items: flex-start;
  gap: 28px;
  padding: 14px 16px 12px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.98);
  border: 1px solid rgba(142, 142, 147, 0.25);
  box-shadow: 0 10px 32px rgba(0, 0, 0, 0.16);
  font-family: var(--font-ui);
}

.layout-sync-col {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.layout-sync-title {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 0 0 10px;
  font-size: 10px;
  font-weight: 600;
  color: #8E8E93;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  white-space: nowrap;
}

/* Carries the one thing the grid cannot say for itself: that each cell is a whole chart,
   not a slice of this one. Title-only, so it costs nothing to ignore. */
.layout-sync-help {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: rgba(142, 142, 147, 0.22);
  color: #8E8E93;
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0;
  cursor: help;
}

/* ── The arrangement picker ──────────────────────────────────────────────────
   Sized by sweeping the pointer across it and fixed by one click, the way a table-insert
   grid works. Cheaper than a row of named buttons once there are sixteen arrangements, and
   it shows the shape rather than describing it. */
.layout-grid-picker {
  display: grid;
  gap: 4px;
}

.layout-grid-cell {
  width: 20px;
  height: 20px;
  padding: 0;
  border: none;
  border-radius: 3px;
  background: rgba(142, 142, 147, 0.22);
  cursor: pointer;
  transition: background 0.12s ease;
}

/* What the pointer is currently sweeping out. Sits between the resting cells and the chosen
   ones in weight, so hovering over part of the current selection still reads as a preview. */
.layout-grid-cell.preview {
  background: rgba(142, 142, 147, 0.55);
}

.layout-grid-cell.chosen {
  background: #1D1D1F;
}

/* A preview drawn over the current selection has to win, otherwise sweeping back from 2x2
   to 1x1 shows no change at all - the cells you are dropping are still lit as chosen. */
.layout-grid-cell.chosen.preview {
  background: #1D1D1F;
}

.layout-grid-cell.chosen:not(.preview) {
  background: rgba(29, 29, 31, 0.35);
}

.layout-grid-picker:not(:hover) .layout-grid-cell.chosen {
  background: #1D1D1F;
}

.layout-grid-cell:focus-visible {
  outline: 2px solid #10B981;
  outline-offset: 1px;
}

.layout-grid-readout {
  padding-top: 9px;
  font-size: 11px;
  font-weight: 500;
  color: #8E8E93;
  white-space: nowrap;
}

/* ── Sync ────────────────────────────────────────────────────────────────────
   A switch rather than a checkbox: these turn a behaviour on across every pane and stay on,
   which is what a switch means, and a native checkbox cannot be styled to sit level with a
   10px caps heading without fighting the platform for it. */
.layout-sync-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  width: 100%;
  padding: 5px 6px;
  margin: 0 -6px;
  border: none;
  border-radius: 6px;
  background: transparent;
  font-family: inherit;
  font-size: 13px;
  color: #1D1D1F;
  text-align: left;
  /* "Date range" is the only two-word label, and letting it wrap made its row a third taller
     than the four above it. The panel is sized by its content, so it simply gets wider. */
  white-space: nowrap;
  cursor: pointer;
}

.layout-sync-row:hover {
  background: rgba(142, 142, 147, 0.1);
}

.layout-sync-switch {
  position: relative;
  flex: none;
  width: 30px;
  height: 17px;
  border-radius: 999px;
  background: rgba(142, 142, 147, 0.35);
  transition: background 0.15s ease;
}

.layout-sync-switch::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: #ffffff;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
  transition: transform 0.15s ease;
}

/* Emerald, the same colour the active pane is outlined in - these switches are about what
   the panes share, so they should answer to the thing that marks a pane. */
.layout-sync-switch.on {
  background: #10B981;
}

.layout-sync-switch.on::after {
  transform: translateX(13px);
}

.layout-sync-row:focus-visible {
  outline: 2px solid #10B981;
  outline-offset: -2px;
}

/* ── Dark ─── */
.layout-sync-menu.dark-mode {
  background: rgba(28, 28, 30, 0.98);
  border-color: var(--bk-border);
  box-shadow: 0 10px 32px rgba(0, 0, 0, 0.5);
}

.layout-sync-menu.dark-mode .layout-sync-title,
.layout-sync-menu.dark-mode .layout-grid-readout {
  color: var(--bk-text-2);
}

.layout-sync-menu.dark-mode .layout-sync-help {
  background: rgba(255, 255, 255, 0.12);
  color: var(--bk-text-2);
}

.layout-sync-menu.dark-mode .layout-sync-row {
  color: #F7F7F7;
}

.layout-sync-menu.dark-mode .layout-sync-row:hover {
  background: rgba(255, 255, 255, 0.08);
}

.layout-sync-menu.dark-mode .layout-grid-cell {
  background: rgba(255, 255, 255, 0.1);
}

.layout-sync-menu.dark-mode .layout-grid-cell.preview {
  background: rgba(255, 255, 255, 0.34);
}

.layout-sync-menu.dark-mode .layout-grid-cell.chosen,
.layout-sync-menu.dark-mode .layout-grid-cell.chosen.preview,
.layout-sync-menu.dark-mode .layout-grid-picker:not(:hover) .layout-grid-cell.chosen {
  background: #ffffff;
}

.layout-sync-menu.dark-mode .layout-grid-cell.chosen:not(.preview) {
  background: rgba(255, 255, 255, 0.45);
}

.layout-sync-menu.dark-mode .layout-sync-switch {
  background: rgba(255, 255, 255, 0.18);
}

.layout-sync-menu.dark-mode .layout-sync-switch.on {
  background: #10B981;
}

/* ══════════════════════════════════════════════════════════════════════
   SCHWARZ — Flächen

   Kein Glas, kein backdrop-filter, keine Transparenz auf Strukturflächen.
   Die Schalen gehen in der schwarzen Leinwand auf, schwebende Flächen
   heben sich um wenige Helligkeitsstufen und einen leisen Schatten ab.

   Rahmen als inset-Ring statt border - siehe index.css. Das ist die
   Bedingung dafür, dass keine Bounding-Box wandert.
   ══════════════════════════════════════════════════════════════════════ */

/* Schalen: gehen in der Leinwand auf, nur eine Trennkante */
/* --shell-surface is the colour chosen under Chart Settings > Style > Design elements.
   It is set on :root only while a colour is actually picked, so every shell rule below
   keeps its theme value as the fallback and nothing changes until someone chooses. One
   variable rather than a class, so the bars and the phone bar cannot drift apart.

   The assistant panel and its dock are deliberately NOT on it. They are painted the same
   #151619/--bk-shell the bars default to, so an untouched app still reads as one surface,
   but a colour chosen here stops at the frame and leaves the assistant alone. */
.navbar,
.drawing-toolbar,
.bottom-strip,
.dark-mode .navbar,
.dark-mode .drawing-toolbar,
.dark-mode .bottom-strip{
  background: var(--shell-surface, var(--bk-shell));
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
  border-color: var(--bk-border);
}

.navbar,
.dark-mode .navbar{
  box-shadow: inset 0 -1px 0 var(--bk-border);
  border-bottom-color: transparent;
}

/* Die drei Leisten stehen in Dark Mode einen Schritt heller als die uebrige Schale:
   #151619 statt der #050505, die --bk-shell traegt. Als eigene Regel und nicht als neuer
   Tokenwert, weil derselbe Token auch Flaechen im Journal und in den Panels faerbt, die
   dabei bleiben sollen, wo sie sind. */
.dark-mode .navbar,
.dark-mode .drawing-toolbar,
.dark-mode .bottom-strip{
  background: var(--shell-surface, #151619);
}

.bottom-strip,
.dark-mode .bottom-strip{
  box-shadow: inset 0 1px 0 var(--bk-border);
  border-top-color: transparent;
}

.drawing-toolbar,
.dark-mode .drawing-toolbar{
  box-shadow: inset -1px 0 0 var(--bk-border);
  border-right-color: transparent;
}

/* schwebende Paneele */
.symbol-modal,
.indicator-modal,
.journal-dashboard-modal,
.alert-modal,
.profile-modal,
.profile-dropdown,
.chatbot-modal,
.color-picker-modal,
.chart-settings-modal,
.trading-panel-modal,
.order-panel,
.watchlist-picker,
.price-alerts-modal,
.backtest-dashboard,
.support-modal,
.bug-report-panel,
.pb-controls,
.dark-mode .symbol-modal,
.dark-mode .indicator-modal,
.dark-mode .journal-dashboard-modal,
.dark-mode .alert-modal,
.dark-mode .profile-modal,
.dark-mode .profile-dropdown,
.dark-mode .chatbot-modal,
.dark-mode .color-picker-modal,
.dark-mode .chart-settings-modal,
.dark-mode .trading-panel-modal,
.dark-mode .order-panel,
.dark-mode .watchlist-picker,
.dark-mode .price-alerts-modal,
.dark-mode .backtest-dashboard,
.dark-mode .support-modal,
.dark-mode .bug-report-panel,
.pb-controls.dark-mode,
.dark-mode .pending-order-controls{
  background: var(--bk-elevated);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: inset 0 0 0 1px var(--bk-border), var(--bk-lift);
  border-color: transparent;
  border-radius: var(--bk-r-panel);
}

/* Menüs und Popover */
/* .pen-toolbar, nicht .drawing-popup: die Werkzeugleiste hiess einmal so, und der Name
   blieb hier stehen, als das Element umbenannt wurde. Die Regel traf also nichts, und die
   Leiste behielt als einziges Popover ihr altes rgba(50,50,55,.95) - heller und grauer
   als jedes andere Panel, und heller als die eigenen Menues, die hier aufgefuehrt sind. */
.navbar-menu,
.timeframe-dropdown-menu,
.layout-sync-menu,
.context-menu,
.pen-toolbar,
.pen-color-dropdown,
.pen-thickness-dropdown,
.quantity-menu,
.sensitivity-dropdown-menu,
.speed-dropdown-menu,
.selection-tooltip,
.dark-mode .navbar-menu,
.dark-mode .timeframe-dropdown-menu,
.dark-mode .layout-sync-menu,
.dark-mode .context-menu,
.dark-mode .pen-toolbar,
.dark-mode .pen-color-dropdown,
.dark-mode .pen-thickness-dropdown,
.dark-mode .quantity-menu,
.dark-mode .sensitivity-dropdown-menu,
.dark-mode .speed-dropdown-menu,
.dark-mode .selection-tooltip{
  background: var(--bk-elevated);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: inset 0 0 0 1px var(--bk-border), var(--bk-lift);
  border-color: transparent;
  border-radius: var(--bk-r-control);
}

/* Ein Popover, das ueber einem Panel aufgeht, steht eine Stufe ueber ihm.
   ─────────────────────────────────────────────────────────────────────
   Die Gruppe darueber setzt jedes Menue auf --bk-elevated. Das stimmt, solange ein Menue
   ueber dem Chart aufgeht - dort ist es die hellere Flaeche. Diese drei gehen aber INNEN
   auf, ueber den Indikatorfenstern, und die stehen seit dieser Runde selbst auf
   --bk-elevated: Menue und Grund waeren dieselbe Farbe, und vom Sensitivity-Menue blieb
   nur sein 1px-Rahmen uebrig.

   --bk-card ist die Stufe darueber - dieselbe, auf der die Karten im Assistenten und die
   Kacheln im Journal stehen. Der Rahmen und der Schatten aus der Gruppe bleiben, nur die
   Flaeche steigt. Nur das Sensitivity-Menue steht hier: .preset-menu und
   .info-tip-popover sind nicht in der Gruppe darueber und tragen --bk-card schon an
   ihrer eigenen Regel weiter oben. */
.dark-mode .sensitivity-dropdown-menu{
  background: var(--bk-card);
}

/* die Leinwand selbst */
.dark-mode{
  background: var(--bk-app);
}

/* Die Flaeche hinter dem Chart folgt dem Chart, nicht der App.
   ────────────────────────────────────────────────────────────
   Der Chart zeichnet seinen Grund auf ein Canvas, und das Canvas trifft die Pixelgrenzen
   seines Containers nicht immer genau: bei 375px Breite lief es bis 374 und 727 in einem
   Wrapper, der bis 375 und 728 geht - je ein Pixel rechts und unten. Durch dieses eine
   Pixel sah man den Wrapper.

   Solange beide schwarz waren, fiel das nicht auf. Seit der Chart auf #151619 steht, las
   sich der Spalt als schwarze Linie zwischen Chart und Strip darunter und zwischen
   Preisachse und dem Assistenten daneben.

   --chart-surface traegt die Hintergrundfarbe des Charts selbst, gesetzt von der
   Komponente. Damit ist die Naht immer die Farbe dessen, woran sie grenzt - auch wenn
   jemand den Chart-Hintergrund umfaerbt. Der Fallback ist nur die Dunkelmodus-Vorgabe,
   fuer den Moment vor dem ersten Setzen. */
/* .chart-container.dark-mode, nicht .dark-mode .chart-container: der Container traegt die
   Klasse selbst, ist also kein Nachfahre von ihr. Der Nachfahren-Selektor hat nie
   gegriffen, und die Flaeche kam still aus der blanken .dark-mode-Regel darueber. */
.chart-container.dark-mode,
.dark-mode .chart-container,
.dark-mode .chart-wrapper{
  background: var(--chart-surface, #151619);
}

.dark-mode .chart-wrapper{
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
  border-color: var(--bk-border);
}

/* ── Zeilen und Zustände ─────────────────────────────────────────────
   Ruhezustand fast schwarz, Trennung über hauchdünne Linien. Kein
   zweiter Kasten im Kasten. */
.navbar-menu-item + .navbar-menu-item,
.context-menu-item + .context-menu-item,
.dark-mode .navbar-menu-item + .navbar-menu-item,
.dark-mode .context-menu-item + .context-menu-item{
  box-shadow: inset 0 1px 0 var(--bk-divider);
}

.navbar .icon-btn:hover, .bottom-strip button:hover,
.navbar-menu-item:hover, .context-menu-item:hover,
.layout-sync-row:hover, .symbol-item:hover,
.dark-mode .navbar .icon-btn:hover, .dark-mode .bottom-strip button:hover,
.dark-mode .navbar-menu-item:hover, .dark-mode .context-menu-item:hover,
.dark-mode .symbol-item:hover{
  background: var(--bk-hover);
}

.navbar .icon-btn:active, .bottom-strip button:active,
.navbar-menu-item:active, .context-menu-item:active, .symbol-item:active{
  background: var(--bk-active);
}

/* Eingabefelder */
/* Die Indikatorsuche gehoert hier mit hinein: sie ist dasselbe Feld wie die
   Marktsuche und sah nur deshalb anders aus - hellerer Grund, 10px statt 12px -
   weil sie beim Umstellen auf das schwarze System uebersehen wurde. Auf das
   Suchfeld begrenzt, damit die uebrigen Eingaben des Fensters unberuehrt bleiben.

   Der Marktarm hiess bis eben .symbol-modal input[type="text"] und war damit genau
   das nicht. Das Replay-Fenster ist ebenfalls ein .symbol-modal (JSX: className=
   "symbol-modal replay-modal"), und seine Stunden- und Minutenfelder sind type="text" -
   die Regel hat also auch die Uhr eingefaerbt. Aufgefallen ist das nie, weil
   .replay-time-field zufaellig denselben Token trug; sobald hier eine andere Farbe
   steht, brechen die beiden Segmente sichtbar aus ihrem Rahmen aus. Jetzt auf
   .modal-search begrenzt, wie der Indikatorarm es immer schon war. */
.symbol-modal .modal-search input,
.indicator-modal .modal-search input,
.watchlist-picker input,
.dark-mode .symbol-modal .modal-search input,
.dark-mode .indicator-modal .modal-search input,
.dark-mode .watchlist-picker input{
  background: var(--bk-input);
  border-color: var(--bk-border);
  border-radius: var(--bk-r-control);
  color: var(--bk-text);
}

/* Fokus der beiden Suchfelder (Markt und Indikatoren).

   Muss hier stehen und nicht oben bei .modal-search: die Regel darueber setzt
   Hintergrund und Rahmen genau dieser Felder und ist gleich spezifisch, gewann also
   allein durch ihre Position. Vom Fokus blieb damit nur der Schatten uebrig - ein
   flaches, hartkantiges 4px-Band bei 5% Weiss, ohne Rahmen- oder Flaechenwechsel.
   Das ist der abgeschnitten wirkende Balken, der hier verschwindet.

   Zwei Lagen: ein scharfer Ring, der den Rahmen fortsetzt, und darunter ein weicher,
   grosszuegig gestreuter Schein, damit der Ring nach aussen ausklingt statt an einer
   Kante aufzuhoeren. Bewegung nur in Farbe, nie in Position - dieselbe Regel, der die
   uebrigen Bedienelemente hier folgen. */
.symbol-modal .modal-search input:focus,
.indicator-modal .modal-search input:focus,
.dark-mode .symbol-modal .modal-search input:focus,
.dark-mode .indicator-modal .modal-search input:focus {
  outline: none;
  border-color: var(--bk-border-strong);
  background: var(--bk-hover);
  box-shadow: 0 0 0 3px var(--bk-divider), 0 6px 20px rgba(0, 0, 0, 0.22);
}

/* Das Suchfeld im Dunkelmodus.
   ───────────────────────────
   --bk-input ist #141414 und lag damit UNTER dem Panel, seit das auf #151619 steht:
   1.02 Kontrast, also praktisch nichts - allein der Rahmen hat das Feld noch gehalten.
   #202124 ist dieselbe Flaeche, auf der die Starter im Assistenten und die Kacheln im
   Journal liegen, und bringt das Feld auf 1.12 ueber seinen Grund.

   Der Token bleibt unangetastet: --bk-input faerbt auch die Replay-Uhr, den
   Watchlist-Picker und das Install-Sheet, die alle tiefer stehen sollen. */
.dark-mode .symbol-modal .modal-search input,
.dark-mode .indicator-modal .modal-search input{
  background: #202124;
}

/* Fokus muss ueber die Ruhelage, nicht darunter. --bk-hover ist #191919 und lag damit
   unter der neuen Ruheflaeche - der Fokus haette das Feld abgedunkelt und das Signal
   umgedreht. Auch dieser Token bleibt: er traegt den Zeilen-Hover der ganzen App. */
.dark-mode .symbol-modal .modal-search input:focus,
.dark-mode .indicator-modal .modal-search input:focus{
  background: #2A2D34;
}

/* Die Lupe gehoert zum Feld, also hellt sie mit auf. Ohne das blieb das einzige
   Zeichen fuer "hier wird getippt" ein Rahmen am anderen Ende des Feldes. */
.symbol-modal .modal-search:focus-within .modal-search-icon,
.indicator-modal .modal-search:focus-within .modal-search-icon {
  color: var(--bk-text);
}

.modal-search-icon {
  transition: color 0.18s ease;
}

/* Bewegung nur in Farbe, nie in Position */
.navbar .icon-btn, .bottom-strip button, .navbar-menu-item,
.context-menu-item, .symbol-item, .layout-sync-row{
  transition: background 150ms ease, color 150ms ease, box-shadow 150ms ease;
}

@media (prefers-reduced-motion: reduce){
  .navbar .icon-btn, .bottom-strip button, .navbar-menu-item,
  .context-menu-item, .symbol-item, .layout-sync-row{ transition: none !important }
}

/* Die Vorgabe schließt Glasoptik aus. Statt 50 Einzelregeln zu jagen,
   wird der Filter einmal flächendeckend abgeschaltet; er hat keinerlei
   Wirkung auf Layout oder Maße. */
*, *::before, *::after{
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}

/* ══════════════════════════════════════════════════════════════════════
   Nackte Steuergruppen

   Diese beiden sind keine Paneele, sondern reine Flex-Reihen: die Farbe
   tragen die Knöpfe darin, der Behälter war immer unsichtbar. Als
   Paneel behandelt bekam er Fläche, 16px Radius, Ring und Schatten -
   und lugte hinter den 6px-Radius-Knöpfen hervor, während die 6px
   Zwischenräume seine Fläche zeigten. Genau das sah falsch aus.
   ══════════════════════════════════════════════════════════════════════ */
.trade-buttons-panel,
.pending-order-controls,
.dark-mode .trade-buttons-panel,
.dark-mode .pending-order-controls,
.trade-buttons-panel.dark-mode,
.pending-order-controls.dark-mode{
  background: transparent;
  box-shadow: none;
  border-color: transparent;
}

/* ══════════════════════════════════════════════════════════════════════
   EIN DIALOGFUSS

   Vier gleichrangige Modalfuesse trugen vier Knopfgeometrien. Ein Primitiv
   fuer alle: gleiche Hoehe, gleicher Radius, gleicher Schnitt, gleicher
   Abstand. Angehaengt statt in die vier Bloecke gestreut, damit die
   Definition an einer Stelle steht.
   ══════════════════════════════════════════════════════════════════════ */
.fib-levels-actions,
.custom-input-buttons,
.indicator-settings-footer,
.backtest-modal-footer{
  gap: 12px;
  padding: 16px 24px;
}

.fib-levels-actions > button,
.custom-input-buttons > button,
.indicator-settings-footer > button,
.backtest-modal-footer > button{
  height: 44px;
  padding: 0 20px;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
}

/* ══════════════════════════════════════════════════════════════════════
   EIN SCHLIESSEN-KNOPF

   Er existierte in fuenf Geometrien - drei Groessen, vier Radien, vier
   Glyphengroessen. Radius war nirgends gesetzt, deshalb reichte es nicht,
   vorhandene Deklarationen anzugleichen: er muss ergaenzt werden.

   Die Groesse selbst bleibt, wo die Media-Query sie hinstellt: mobile.css
   zieht Knoepfe zwischen 769 und 1024px auf 40px und darunter auf 44px.
   Das ist Trefferflaeche und wird hier nicht unterlaufen.
   ══════════════════════════════════════════════════════════════════════ */
.close-btn,
.trade-checker-header .close-btn,
.chatbot-header .close-btn,
.dark-mode .close-btn{
  border-radius: 8px;
  border: none;
}

.close-btn:hover,
.dark-mode .close-btn:hover{
  background: var(--bk-hover);
}


/* ══════════════════════════════════════════════════════════════════════
   FUSSLEISTE: gleiche Kante wie der Chart

   Sie trug nur eine Oberkante, waehrend Chart und Paneele umlaufend
   gefasst sind - und war oben links gerundet, oben rechts nicht.

   Der Rahmen bleibt ein inset-Ring statt eines border: ein echter Rahmen
   addierte 2px und schoebe die Leiste. Unten laeuft sie an die Fensterkante,
   deshalb bleiben die unteren Ecken eckig.
   ══════════════════════════════════════════════════════════════════════ */
.bottom-strip,
.dark-mode .bottom-strip{
  box-shadow: inset 0 0 0 1px var(--bk-border);
  border-top-color: transparent;
  border-radius: 12px 12px 0 0;
}


/* ══════════════════════════════════════════════════════════════════════
   BUENDIG: keine Luecken zwischen Chart und Leisten

   Der Chart lag als schwebende Karte mit 8px Rand, 16px Rundung und
   Schlagschatten in der Flaeche. Jetzt stoesst er direkt an Navigation,
   Werkzeugschiene und Fussleiste.

   Sein eigener Rahmen entfaellt dabei: die drei Leisten zeichnen ihre
   Kante bereits: buendig nebeneinander ergaeben zwei 1px-Linien direkt
   nebeneinander eine 2px-Doppellinie. Eine Grenze, eine Linie.

   Die Fussleiste rueckt von 52px auf 44px nach links, damit sie mit der
   Chartkante fluchtet statt um die alte Luecke eingerueckt zu stehen,
   und traegt wieder nur ihre Oberkante - links stoesst sie an die
   Werkzeugschiene, die dort schon eine Linie hat.
   ══════════════════════════════════════════════════════════════════════ */
.chart-wrapper,
.dark-mode .chart-wrapper{
  margin: 0;
  border-radius: 0;
  border: none;
  box-shadow: none;
}

/* Die Karte darunter rundete weiter. .chart schneidet mit overflow:hidden auf seine
   eigenen 16px zu, also blieben die vier Ecken der Chartflaeche ausgespart: die
   Hintergrundfarbe des Charts hoerte davor auf und die dunkle Flaeche des Containers kam
   durch. Der Zuschnitt bleibt - er haelt das Canvas im Kasten - die Rundung geht. */
.chart{
  border-radius: 0;
}

/* Die Zeitachse zieht ihre Oberkante nur ueber ihre eigene Zelle. Neben ihr sitzt das
   Eckfeld unter der Preisskala, und dort brach die Linie ab: die letzten ~64px der
   Chartflaeche standen ohne Kante da. Solange die Ecken rund waren, schnitt die Rundung
   genau dieses Feld an; eckig liegt die Luecke frei.

   Nachgezogen wird sie als Overlay ueber dem Canvas. Ein border-top auf der Zelle machte
   die Reihe 1px hoeher und verschoebe den Chart, ein inset-Schatten laege unter dem Canvas
   und wuerde von ihm uebermalt. Beide Eckfelder, damit auch eine linke Preisskala traegt. */
.chart .tv-lightweight-charts table tr:last-child td:first-child,
.chart .tv-lightweight-charts table tr:last-child td:last-child{
  position: relative;
}

.chart .tv-lightweight-charts table tr:last-child td:first-child::after,
.chart .tv-lightweight-charts table tr:last-child td:last-child::after{
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  /* Dieselben Werte, die der Chart selbst fuer timeScale/priceScale borderColor setzt. */
  background: rgba(0, 0, 0, 0.08);
  pointer-events: none;
}

.dark-mode .chart .tv-lightweight-charts table tr:last-child td:first-child::after,
.dark-mode .chart .tv-lightweight-charts table tr:last-child td:last-child::after{
  background: #242424;
}

.bottom-strip,
.dark-mode .bottom-strip{
  margin-left: 44px;
  border-radius: 0;
  box-shadow: inset 0 1px 0 var(--bk-border);
}

/* Die Werkzeugschiene stand 8px unter der Navigation und war oben rechts
   gerundet - dieselbe Luecke wie beim Chart, nur an einer anderen Kante. */
.drawing-toolbar,
.dark-mode .drawing-toolbar{
  margin: 0;
  border-radius: 0;
  /* Die Schiene laeuft absichtlich neben der Fussleiste weiter. Die 36px
     waren auf den alten 8px-Versatz oben gerechnet; ohne ihn fehlten
     genau diese 8px unten. Die Fussleiste ist 44px hoch. */
  height: calc(100% + 44px);
}


/* Auf dem Telefon ist die Werkzeugschiene 42px breit statt 44px. Diese Regel
   muss NACH dem buendigen Block oben stehen: Media-Queries erhoehen die
   Spezifitaet nicht, eine gleich spezifische Regel weiter unten gewinnt. */
@media (max-width: 768px), (max-height: 500px) and (orientation: landscape) {
  .bottom-strip,
  .dark-mode .bottom-strip {
    margin-left: 42px;
  }
}


/* ══════════════════════════════════════════════════════════════════════
   DOPPELLINIE oben links

   Die Werkzeugschiene zog einen eigenen oberen Rahmen - direkt unter der
   Unterkante der Navigation. Uebereinander ergab das im Bereich der
   Schiene einen 2px-Strich, waehrend rechts daneben nur 1px lag.

   Links und unten stiess sie an den Fensterrand, wo es nichts zu trennen
   gibt. Sie behaelt nur die Kante, die wirklich eine Grenze ist: rechts,
   zum Chart.

   Nur die Farbe wird auf transparent gesetzt, nicht die Breite - sonst
   verschoebe sich die Schiene um 1px.
   ══════════════════════════════════════════════════════════════════════ */
.drawing-toolbar,
.dark-mode .drawing-toolbar{
  border-top-color: transparent;
  border-left-color: transparent;
  border-bottom-color: transparent;
}

/* ========================================
   PHONE: THE BOTTOM CONTROL BAR
   ======================================== */
/* Market, timeframe and indicators, moved out of the navbar into their own bar below the
   strip. On a tall phone the top of the screen is the hardest place to reach and these are
   the three controls used most, so they go where the thumb already is.

   Two fixed bars now stack at the bottom, and the container reserves the height of both.
   Everything here is expressed against --app-height for the same reason the strip is:
   100dvh on iOS reports the viewport with the chrome retracted, which is taller than what
   is actually on screen. */
@media (max-width: 768px), (max-height: 500px) and (orientation: landscape) {
  .chart-container {
    padding-bottom: calc(38px + 46px + env(safe-area-inset-bottom));
  }

  /* Lifted by the new bar's height. The safe-area padding goes with the bottom-most
     element, which is no longer this one. */
  .bottom-strip {
    top: calc(var(--app-height, 100dvh) - 38px - 46px - env(safe-area-inset-bottom));
    height: 38px;
    padding-bottom: 0;
  }

  .mobile-tool-bar {
    position: fixed;
    left: 0;
    right: 0;
    top: calc(var(--app-height, 100dvh) - 46px - env(safe-area-inset-bottom));
    z-index: 70;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    height: calc(46px + env(safe-area-inset-bottom));
    padding: 0 10px env(safe-area-inset-bottom);
    box-sizing: border-box;
    /* Frosted until a colour is chosen, solid once one is - a chosen colour behind a
       blur is not the colour that was chosen. */
    background: var(--shell-surface, rgba(255, 255, 255, 0.86));
    backdrop-filter: blur(80px) saturate(200%);
    -webkit-backdrop-filter: blur(80px) saturate(200%);
    border-top: 1px solid var(--bk-border);
    /* The full width, unlike the strip: the drawing rail is bounded by the container's
       padding and stops above this bar, so there is nothing here to clear. */
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
  }

  .mobile-tool-bar::-webkit-scrollbar {
    display: none;
  }

  /* The navbar squeezes its controls to fit a crowded row; this bar holds three, so they
     get their full labels back and a target worth tapping. */
  .mobile-tool-bar > *,
  .mobile-tool-bar .symbol-btn,
  .mobile-tool-bar .timeframe-dropdown-btn,
  .mobile-tool-bar .indicators-btn {
    flex-shrink: 0;
    min-height: 34px;
  }

  .mobile-tool-bar .indicators-text {
    display: inline;
  }

  /* The three controls are separated the same way the navbar separates its own: the
     market button already drew a line after itself here and the indicators button did
     not, so the row had one divider and one gap where a divider should have been.
     :not(:last-child) because this rule outranks .indicators-btn:last-child::after and
     would otherwise hang a line off the end of the row. */
  .mobile-tool-bar .indicators-btn:not(:last-child)::after {
    display: block;
  }

  /* The same #151619 the navbar, the drawing toolbar and the strip carry - see the rule
     that sets those three. This bar was added after that change and stayed on the old
     frosted glass: rgba(8, 8, 8, 0.86) over the black canvas resolved to about #080808,
     a shade darker than the strip sitting directly on top of it, so the two bars that
     meet at the bottom of the screen read as two tones instead of one surface.
     backdrop-filter goes with it - nothing shows through an opaque fill for the blur to
     work on, so it was only buying a compositing layer on every scroll. */
  .dark-mode .mobile-tool-bar {
    background: var(--shell-surface, #151619);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border-top: 1px solid var(--bk-border);
  }
}

/* ========================================
   PHONE: MARKET AND INDICATORS AS SHEETS
   ======================================== */
/* Both are opened from the bar at the bottom of the screen now, so they come up from that
   edge rather than fading in at the centre - the panel arrives from where it was asked
   for. The timeframe menu already does this by anchoring itself above its button; these
   two are modals, so it is the surface itself that moves.

   Everything here carries !important because it is overriding the shared phone block
   above, which caps every dialog's width and height that way, and because the indicator
   window's position comes from inline coordinates it is dragged to on a desktop. */
@media (max-width: 768px), (max-height: 500px) and (orientation: landscape) {
  .symbol-modal,
  .indicator-modal {
    top: auto !important;
    bottom: 0 !important;
    left: 0 !important;
    right: 0 !important;
    transform: none !important;
    width: 100% !important;
    max-width: 100% !important;
    /* Taller than the 68vh the centred dialogs get: a sheet gives up no room at the
       bottom, so the same content fits without the list scrolling as soon as it opens. */
    max-height: 82dvh !important;
    border-radius: 20px 20px 0 0 !important;
    /* The bottom edge is off-screen, so a border there is a line that never renders and
       the side borders would run to nowhere. */
    border-bottom: 0 !important;
    padding-bottom: env(safe-area-inset-bottom) !important;
    animation: mobileSheetUp 0.26s cubic-bezier(0.33, 1, 0.68, 1) both;
  }

  @keyframes mobileSheetUp {
    from { transform: translateY(100%) !important; }
    to { transform: translateY(0) !important; }
  }
}

/* ========================================
   PHONE: ONE EVEN ROW IN THE NAVBAR
   ======================================== */
/* The centre group used to share the row's slack among its own children so they all grew
   by the same amount and none looked singled out. That worked while the group held six
   controls. With the market, indicators and replay buttons moved down to the phone's own
   bar it holds three, so each absorbed twice as much - the painter and scanner sat in 60px
   boxes next to a 36px trading panel and journal, and the icons ended up at uneven
   intervals across the row even though every flex gap was the same 4px.

   The group stops generating a box, so its children become items of the navbar itself and
   the whole bar is one flat row. The slack is then shared as spacing between every button
   rather than as width inside three of them: equal gaps, equal boxes, and no 99px hole in
   the middle - which is the failure the growth trick was there to avoid in the first
   place. */
@media (max-width: 768px), (max-height: 500px) and (orientation: landscape) {
  .navbar-center {
    display: contents;
  }

  /* The children are still matched by this selector - display: contents suppresses the
     box, not the element - so the growth has to be turned off explicitly or they would
     stretch as items of the navbar instead. */
  .navbar-center > * {
    flex-grow: 0;
  }

  .navbar {
    flex-wrap: nowrap;
    justify-content: space-between;
  }

  /* The row's separators, as items rather than as pseudo-elements hung off the button to
     their left. The reason is spacing: space-between divides the leftover width evenly
     between the items it can see, so a line that is one of them gets the same space on
     both sides automatically. Hung off a button it was invisible to that division and kept
     the fixed 2.75px offset it was given for a 4px gap, which left it pinned to one button
     with the whole gap on the other side.

     It also puts a line between the scanner and the trading panel, which had none. The
     scanner is the last child of .navbar-center and so was caught by
     .indicators-btn:last-child::after - correct on a desktop, where the group ends the run
     of centre controls, but on a phone the group generates no box and the two buttons are
     plain neighbours in one flat row.

     Same 1.5px width and 18px height as the pseudo-element it replaces, so the row reads
     exactly as it did - only evenly spaced. */
  .navbar-divider {
    display: block;
    flex: 0 0 auto;
    width: 1.5px;
    height: 18px;
    background: rgba(0, 0, 0, 0.1);
  }

  .dark-mode .navbar-divider {
    background: rgba(255, 255, 255, 0.15);
  }
}

/* On a 320px screen the row has nothing left to distribute: the five controls, the four
   separators and the two end cells come to 294px, and the 4px floor between them takes the
   bar 14px past the window. space-between cannot absorb that - there is no slack to share
   - and the bar does not wrap or scroll at this size, so the overflow would simply carry
   the tools button off the right edge.

   The floor is what gives. It is only ever a floor: at every width that fits, the spacing
   is the leftover width divided between the gaps, and this number does not enter into it.
   So this changes nothing above about 335px, which is where the row stops fitting. */
@media (max-width: 360px) {
  .navbar {
    gap: 2px;
  }

  /* Cancels the gap above the way the 4px version does at wider sizes: the journal sits
     against the tools cell's own divider and must not have a gap of its own. */
  .navbar > .journal-btn {
    margin-right: -2px;
  }

  /* Trade Checker stays on the ticker's line down here too (it used to drop to the BUY /
     SELL row below 360px). The ticker ends at 172px at 320; with its tick the button came to
     95px and started at 167, over the alarm icon. A size down on everything but the words
     brings it back clear for a symbol as long as BTC/USD; a much longer symbol on a 320px
     phone would still reach it. It keeps right: 58px here - the 6px more the wider phones
     get would put it back over the alarm icon. */
  .trade-checker-btn {
    right: 58px;
    padding: 4px 5px;
    gap: 3px;
    font-size: 9.5px;
  }

  .trade-checker-btn svg {
    width: 11px;
    height: 11px;
  }
}


/* ══════════════════════════════════════════════════════════════════════
   CHOSEN TEXT COLOUR
   ══════════════════════════════════════════════════════════════════════

   Nothing here any more, on purpose.

   The chosen text colour used to repaint the navbar, the tool rail, the bottom strip and
   the phone's tool bar as well as the chart's scales, on the reasoning that they are all
   one frame. In use that was wrong: picking a colour for the numbers down the right-hand
   edge also recoloured every button and icon in the app, which is not what the control
   looks like it does.

   It now reaches the price scale and the time scale only, the way TradingView's equivalent
   does. Those are drawn to a canvas rather than styled, so there is no CSS to write - they
   go through layout.textColor, see resolveScaleTextColor in CandlestickChart.jsx.

   The --shell-ink variable and the .has-shell-ink class that hung off it are gone with the
   rules; the app no longer sets either. If the bars ever need their own ink again it
   should be its own control with its own name, not this one widened back out. */


/* ══════════════════════════════════════════════════════════════════════
   Contact Support
   ══════════════════════════════════════════════════════════════════════
   Deliberately small. It carries one address and two ways to use it, so it is
   sized to its content rather than to the panel grid the settings windows use.
   The surface, border and radius come from the floating-panel group above - it
   is listed there rather than painting itself, so it follows the shell colour
   with everything else. */
.support-modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 340px;
  max-width: calc(100vw - 44px);
  padding: 20px 22px 22px;
  z-index: 10050;          /* above the profile panel it opens from */
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.support-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.support-modal-header h3 {
  font-family: var(--font-ui);
  font-size: 17px;
  font-weight: 700;
  margin: 0;
  color: var(--bk-text);
}

.support-modal-text {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 13px;
  line-height: 1.45;
  color: var(--bk-text-2);
}

/* The address is the point of the panel, so it gets the weight of a value rather
   than of body text, and a surface of its own to read as something to be taken. */
.support-modal-address {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 11px 12px;
  border-radius: var(--bk-r-control);
  background: var(--bk-input);
  box-shadow: inset 0 0 0 1px var(--bk-border);
}

.support-modal-address span {
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 600;
  color: var(--bk-text);
  /* Selectable: copying by hand has to stay possible where the clipboard API is
     refused, which is the case this panel exists to survive. */
  user-select: text;
}

.support-modal-copy {
  flex: 0 0 auto;
  height: 30px;
  padding: 0 12px;
  border: none;
  border-radius: 8px;
  background: var(--bk-primary);
  color: var(--bk-on-primary);
  font-family: var(--font-ui);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 150ms ease;
}

.support-modal-copy:hover { opacity: 0.85; }

.support-modal-mail {
  align-self: flex-start;
  font-family: var(--font-ui);
  font-size: 12.5px;
  font-weight: 500;
  color: var(--bk-text-2);
  text-decoration: none;
}

.support-modal-mail:hover {
  color: var(--bk-text);
  text-decoration: underline;
}

/* ══════════════════════════════════════════════════════════════════════
   Report a bug
   ══════════════════════════════════════════════════════════════════════
   The button at the foot of the tool rail and the panel it opens. The panel
   is Contact Support with a text box above the address: its header, text,
   address row and mail link are that panel's own classes, and its surface
   comes from the floating-panel group above. Only what is new is here. */

/* Pushed to the bottom of the rail by the free space above it. When the rail
   is too short and scrolls there is no free space, and it simply follows the
   bin like any other button. */
.drawing-toolbar .tool-btn-bug-report {
  margin-top: auto;
}

/* The same quiet mark a group button keeps while its menu is open: the pointer
   is on the panel by then, and the button only has to look engaged. */
.tool-btn-bug-report.open::before {
  background: rgba(0, 0, 0, 0.04);
}

.dark-mode .tool-btn-bug-report.open::before {
  background: rgba(255, 255, 255, 0.1);
}

/* Until the account first opens it, the button sends out a slow ping in the brand colour -
   the same breath the walkthrough ring takes, so the eye finds it without being shouted at.
   Drawn inside the button: the rail clips anything past its own edge, which is only 3 to
   4px beyond the button. The ring starts just clear of the icon and has faded out by the
   time it reaches the button's edge. The icon keeps its own colour - in the brand purple it
   would drop to 2.4:1 against the dark rail. */
.tool-btn-bug-report.attention::after {
  content: '';
  position: absolute;
  inset: 8px;
  border-radius: 7px;
  pointer-events: none;
  animation: bugReportPing 2.4s ease-out infinite;
}

@keyframes bugReportPing {
  0%   { box-shadow: 0 0 0 0 rgba(var(--brand-rgb), 0.55); }
  70%  { box-shadow: 0 0 0 8px rgba(var(--brand-rgb), 0); }
  100% { box-shadow: 0 0 0 0 rgba(var(--brand-rgb), 0); }
}

/* The walkthrough's lighter purple, which is what holds up against the dark rail. */
.dark-mode .tool-btn-bug-report.attention::after {
  animation-name: bugReportPingDark;
}

@keyframes bugReportPingDark {
  0%   { box-shadow: 0 0 0 0 rgba(139, 109, 255, 0.55); }
  70%  { box-shadow: 0 0 0 8px rgba(139, 109, 255, 0); }
  100% { box-shadow: 0 0 0 0 rgba(139, 109, 255, 0); }
}

/* No motion asked for: a still ring in its place, so the button is marked all the same. */
@media (prefers-reduced-motion: reduce) {
  .tool-btn-bug-report.attention::after {
    animation: none;
    box-shadow: 0 0 0 2px rgba(var(--brand-rgb), 0.45);
  }

  .dark-mode .tool-btn-bug-report.attention::after {
    box-shadow: 0 0 0 2px rgba(139, 109, 255, 0.55);
  }
}

/* Fixed and positioned from a measurement of the button, like the rail's
   flyouts, and slides out of the rail the same way. It hangs from the bottom
   edge on a desktop and from the top on a phone; the coordinates here only
   stand in for the frame before that measurement lands. */
.bug-report-panel {
  position: fixed;
  left: 52px;
  bottom: 12px;
  z-index: 1201;
  width: 320px;
  max-width: calc(100vw - 64px);
  box-sizing: border-box;
  padding: 18px 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  overflow-y: auto;
  scrollbar-width: none;
  animation: toolFlyoutIn 0.16s cubic-bezier(0.33, 1, 0.68, 1);
}

.bug-report-panel::-webkit-scrollbar {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .bug-report-panel { animation: none; }
}

/* Bug or feature idea, at the top of the panel. A two-way segmented switch in the
   panel's own tokens, so it follows the theme like the fields below it. */
.bug-report-kind {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px;
  padding: 3px;
  border-radius: var(--bk-r-control);
  background: var(--bk-input);
  box-shadow: inset 0 0 0 1px var(--bk-border);
}

.bug-report-kind button {
  padding: 6px 10px;
  border: none;
  border-radius: calc(var(--bk-r-control) - 2px);
  background: transparent;
  color: var(--bk-text-2);
  font-family: var(--font-ui);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.bug-report-kind button:hover:not(.active) {
  color: var(--bk-text);
}

.bug-report-kind button.active {
  background: var(--bk-elevated);
  color: var(--bk-text);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), inset 0 0 0 1px var(--bk-border);
}

/* Drawn like the address row under it, so the panel reads as two fields: what
   went wrong, and where it goes. */
.bug-report-input {
  display: block;
  width: 100%;
  min-height: 96px;
  box-sizing: border-box;
  padding: 10px 12px;
  border: none;
  border-radius: var(--bk-r-control);
  background: var(--bk-input);
  box-shadow: inset 0 0 0 1px var(--bk-border);
  color: var(--bk-text);
  font-family: var(--font-ui);
  font-size: 13px;
  line-height: 1.45;
  resize: vertical;
  outline: none;
}

.bug-report-input::placeholder {
  color: var(--bk-text-3);
}

.bug-report-input:focus {
  box-shadow: inset 0 0 0 1px var(--bk-text-3);
}

/* 16px on a phone, as mobile.css sets for every field there - anything smaller
   and iOS zooms the page in when the box takes focus. This class out-specifies
   that rule's bare textarea, so it has to say so itself. */
@media (max-width: 768px), (max-height: 500px) and (orientation: landscape) {
  .bug-report-input {
    font-size: 16px;
  }
}

/* ══════════════════════════════════════════════════════════════════════
   How many runs are left on a metered feature
   ══════════════════════════════════════════════════════════════════════
   Sits inside the AI Painter and Chart Scan buttons, and only in the last
   stretch before the allowance runs out - see FEATURE_WARN_AT. It borrows the
   assistant's credit pill rather than inventing a second shape for the same
   idea, but stays smaller: that one is the whole point of its corner, this one
   is a footnote on a button that already has a label. */
.feature-remaining {
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 600;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
  background: rgba(120, 120, 128, 0.16);
  color: var(--bk-text-2);
}

.dark-mode .feature-remaining {
  background: rgba(255, 255, 255, 0.09);
  color: var(--bk-text-2);
}

/* Nothing left. The same amber the assistant uses when its credits are gone, so
   the two read as one state rather than as two unrelated warnings. */
.feature-remaining.empty,
.dark-mode .feature-remaining.empty {
  background: rgba(255, 149, 0, 0.14);
  color: #FF9500;
}

/* Sits under the assistant's composer. Deliberately the quietest text in the panel:
   it has to be present and legible without competing with the reply above it. */
.ai-disclaimer {
  margin: 8px 2px 0;
  font-family: var(--font-ui);
  font-size: 10.5px;
  line-height: 1.35;
  text-align: center;
  color: var(--bk-text-3);
}

/* The tool rail on a phone held sideways.
   ───────────────────────────────────────
   The rail is a column, and turning the phone takes two thirds of the height away: at the
   portrait size of 36px per tool its 17 tools need 444px in a rail that now has 287, so
   five of them sat below the fold. It scrolls, but a 42px-wide scrolling strip is not
   something anyone discovers mid-trade.

   So the tools get a little smaller, and only here - portrait has the room and keeps the
   comfortable size. Not small enough to fit all seventeen, which would mean 28px targets;
   this is the last one or two still scrolling rather than five, at a size a thumb can
   still hit. */
@media (max-height: 500px) and (orientation: landscape) {
  .drawing-toolbar {
    gap: 2px;
    padding: 2px 0;
  }

  /* .drawing-toolbar .tool-btn, not .drawing-toolbar button: the phone rule that pins these
     to 36px for touch is itself written at that specificity, and a tag selector loses to a
     class one no matter how far down the file it sits. */
  .drawing-toolbar .tool-btn,
  .drawing-toolbar button {
    height: 30px;
    min-height: 30px;
  }

  .drawing-toolbar .tool-divider {
    margin: 2px auto;
  }
}

/* The settings footer on a phone.
   ──────────────────────────────
   Three buttons at their natural widths come to 366px inside a 329px footer, and the third
   one - Apply Settings - simply ran off the end. On a narrow footer they stop being sized by
   their labels and share the row instead. */
@media (max-width: 768px), (max-height: 500px) and (orientation: landscape) {
  .indicator-settings-footer {
    gap: 8px;
  }

  .indicator-rewatch-tour-btn,
  .indicator-reset-colors-btn,
  .indicator-apply-settings-btn {
    flex: 1 1 0;
    min-width: 0;
    padding: 10px 6px;
    font-size: 12px;
    justify-content: center;
    text-align: center;
  }
}


/* ========================================
   SERVER ALERTS - drawing and indicator alerts, in the price alerts panel and the dialog
   opened from a drawing's bell. Built on the panel's own classes; these are the extras.
   ======================================== */
.server-alerts-hint {
  margin: 8px 0 10px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--bk-text-3);
}

.server-alerts-error,
.server-alerts-done {
  margin: 8px 0;
  padding: 8px 10px;
  border-radius: 8px;
  font-size: 12.5px;
  line-height: 1.4;
}

.server-alerts-error {
  background: rgba(239, 68, 68, 0.1);
  color: var(--bk-neg);
}

.server-alerts-done {
  background: rgba(16, 185, 129, 0.12);
  color: var(--bk-pos);
}

.drawing-alert-modal {
  max-width: 440px;
}

.drawing-alert-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  justify-content: flex-end;
}

.drawing-alert-actions .alerts-submit {
  flex: 1;
}

.alerts-submit:disabled {
  opacity: 0.6;
  cursor: default;
}

/* The bell on a drawing's toolbar lights up when that drawing has an alert. */
.drawing-alert-btn.has-alert {
  color: #F59E0B;
}

/* A replay switch that could not keep its moment: shown just above the playback controls. */
.pb-notice {
  position: fixed;
  left: 50%;
  bottom: 82px;
  transform: translateX(-50%);
  z-index: 1000;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  max-width: calc(100vw - 32px);
  padding: 8px 12px;
  border: 1px solid rgba(0, 0, 0, 0.12);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.95);
  color: #1d1d1f;
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  font-size: 12px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
}

.pb-notice.dark-mode {
  border-color: rgba(255, 255, 255, 0.14);
  background: rgba(30, 30, 30, 0.95);
  color: #f2f2f7;
}

.pb-notice-close {
  border: none;
  background: none;
  color: inherit;
  opacity: 0.6;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}

/* The chart and the Strategy Tester under it, as one column beside the drawing tools
   (CandlestickChart.jsx). Without a tester the chart fills it exactly as before. */
.chart-column {
  flex: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  position: relative;
}
.chart-column > .chart-wrapper {
  flex: 1 1 auto;
  min-height: 0;
}
/* ══════════════════════════════════════════════════════════════════════
   The desktop top bar, tightened
   ══════════════════════════════════════════════════════════════════════
   Loaded after CandlestickChart.css and only for the desktop layout (the same media
   query as PHONE_LAYOUT_QUERY, negated), so the phone bar is untouched. It changes how
   the bar looks, never what is in it or what any button does.

   What it does, and why: the bar used to spread its controls across the width with a line
   after every one, in bold 14px - a phone tab bar stretched over a desktop. Now the main
   controls sit centred and grouped, with quiet labels (medium weight,
   secondary colour) until hovered or open. The chart is the loudest thing on screen, not
   the bar. The bar's own colours are left exactly as they were. */

@media (min-width: 769px) and (min-height: 501px), (min-width: 769px) and (orientation: portrait) {
  /* Height and padding only - the bar keeps its own colours, border and shadow in both
     themes (and a custom shell colour, if one is set). */
  .chart-container .navbar.navbar {
    height: 42px;
    /* No padding on the right: the menu's cell is sized to the price scale's column (see
       navbar-right in CandlestickChart.jsx) and has to end flush with it to sit over it. */
    padding: 0 0 0 10px;
  }

  /* The brand, smaller: it is not what anyone came to look at. */
  .chart-container .navbar .profile-picture {
    width: 26px;
    height: 26px;
    font-size: 12px;
  }
  .chart-container .navbar .navbar-wordmark {
    font-size: 14px;
    font-weight: 650;
    letter-spacing: -0.01em;
    margin: 0 14px 0 6px;
  }

  /* The main controls stay centred (CandlestickChart.css does the centring), grouped, with
     thin lines between the groups only. */
  .chart-container .navbar .navbar-center {
    gap: 2px;
  }

  /* Every control the same height, padding and type. */
  .chart-container .navbar :is(.symbol-btn, .timeframe-dropdown-btn, .indicators-btn) {
    height: 28px;
    padding: 0 10px;
    gap: 6px;
    border-radius: 6px;
    font-size: 13px;
    font-weight: 500;
    color: var(--bk-text-2);
    background: transparent;
    box-shadow: none;
    border: none;
  }
  .chart-container .navbar :is(.symbol-btn, .timeframe-dropdown-btn, .indicators-btn) svg {
    stroke: currentColor;
    width: 15px;
    height: 15px;
  }
  .chart-container .navbar :is(.symbol-btn, .timeframe-dropdown-btn, .indicators-btn):hover,
  .chart-container .navbar :is(.symbol-btn, .timeframe-dropdown-btn, .indicators-btn).active {
    color: var(--bk-text);
    background: rgba(0, 0, 0, 0.06);
  }
  .chart-container.dark-mode .navbar :is(.symbol-btn, .timeframe-dropdown-btn, .indicators-btn):hover,
  .chart-container.dark-mode .navbar :is(.symbol-btn, .timeframe-dropdown-btn, .indicators-btn).active {
    background: rgba(255, 255, 255, 0.08);
  }
  /* In dark mode the secondary grey (#949494) is too faint on the bar - the labels read as
     disabled. A bright white instead, just short of the full white used on hover. Every
     control in the bar the same colour and weight - the market, the timeframe and the
     chart type included - so the row reads as one. Same for the menu and the bottom strip. */
  .chart-container.dark-mode .navbar :is(.symbol-btn, .timeframe-dropdown-btn, .indicators-btn),
  .chart-container.dark-mode .navbar .navbar-right .icon-btn,
  .chart-container.dark-mode .bottom-strip .indicators-btn {
    color: #EDEDED;
  }
  .chart-container.dark-mode .navbar :is(.symbol-btn, .timeframe-dropdown-btn, .indicators-btn):is(:hover, .active),
  .chart-container.dark-mode .navbar .navbar-right .icon-btn:hover,
  .chart-container.dark-mode .bottom-strip .indicators-btn:hover {
    color: var(--bk-text);
  }

  /* The market's name and the timeframe follow their buttons (each has a colour and
     weight of its own). */
  .chart-container .navbar .symbol-btn .symbol-text,
  .chart-container .navbar .timeframe-dropdown-btn .timeframe-text {
    font-size: 13px;
    font-weight: inherit;
    color: inherit;
  }
  .chart-container .navbar .symbol-btn .symbol-logo-small {
    width: 18px;
    height: 18px;
  }

  /* No line after every control ... */
  .chart-container .navbar :is(.symbol-btn, .timeframe-dropdown-btn, .indicators-btn)::after {
    display: none;
  }
  /* ... but a thin line between every control in the centre row (each one after another
     control gets the line on its left). */
  .chart-container .navbar .navbar-center > :is(.symbol-btn, .timeframe-dropdown-container, .indicators-btn) ~ :is(.symbol-btn, .timeframe-dropdown-container, .indicators-btn) {
    position: relative;
    margin-left: 9px;
  }
  .chart-container .navbar .navbar-center > :is(.symbol-btn, .timeframe-dropdown-container, .indicators-btn) ~ :is(.symbol-btn, .timeframe-dropdown-container, .indicators-btn)::before {
    content: '';
    position: absolute;
    left: -6px; /* the middle of the 11px between two controls (2px gap + 9px margin) */
    top: 50%;
    width: 1px;
    height: 14px;
    transform: translateY(-50%);
    background: var(--bk-border-strong);
    pointer-events: none;
  }

  .chart-container .navbar .indicators-btn .indicators-count {
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    font-size: 10px;
    line-height: 16px;
    border-radius: 8px;
  }

  /* The menu keeps the right end to itself - pushed there whether the centre group is in
     the flow or lifted out of it to sit on the window's centre line. */
  .chart-container .navbar .navbar-right {
    margin-left: auto;
  }
  .chart-container .navbar .navbar-right .icon-btn {
    width: 30px;
    height: 30px;
    border-radius: 6px;
    color: var(--bk-text-2);
  }
  .chart-container .navbar .navbar-right .icon-btn:hover {
    color: var(--bk-text);
    background: var(--bk-hover);
  }

  /* The Indicators label has a style of its own (bold, dark); here it follows its button. */
  .chart-container .navbar .indicators-btn .indicators-text {
    font: inherit;
    color: inherit;
  }

  /* The bottom strip, the same way: quiet labels, full colour on hover. Its height and
     colours stay as they were - panels above it are positioned against its 44px. */
  .chart-container .bottom-strip .indicators-btn {
    height: 28px;
    padding: 0 10px;
    gap: 6px;
    border-radius: 6px;
    font-size: 12.5px;
    font-weight: 500;
    color: var(--bk-text-2);
  }
  .chart-container .bottom-strip .indicators-btn .indicators-text {
    font: inherit;
    color: inherit;
  }
  .chart-container .bottom-strip .indicators-btn svg {
    stroke: currentColor;
    width: 14px;
    height: 14px;
  }
  .chart-container .bottom-strip .indicators-btn:hover {
    color: var(--bk-text);
    background: var(--bk-hover);
  }
  .chart-container .bottom-strip .strip-label {
    font-size: 11px;
    letter-spacing: 0.04em;
  }
  .chart-container .bottom-strip .strip-value {
    font-size: 12px;
    font-weight: 500;
    color: var(--bk-text-2);
  }

  /* The tool rail's group arrows open each group's flyout, so they stay - but faint until
     the group is hovered, instead of a row of chevrons beside every icon. */
  .chart-container .drawing-toolbar .tool-group-caret {
    opacity: 0.3;
    transition: opacity 0.15s ease;
  }
  .chart-container .drawing-toolbar .tool-group:hover .tool-group-caret,
  .chart-container .drawing-toolbar .tool-group-caret:focus-visible {
    opacity: 1;
  }

  /* The market line over the chart in the app's own type, not monospace. */
  .chart-container .asset-ticker-overlay {
    font-family: var(--font-ui);
    font-size: 13px;
    font-weight: 600;
    gap: 7px;
  }
  .chart-container .asset-ticker-overlay :is(.asset-ticker-exchange, .asset-ticker-timeframe) {
    font-weight: 500;
    color: var(--bk-text-2);
  }
}
/* ══════════════════════════════════════════════════════════════════════
   The chart's right-click menu and the navbar's tools (burger) menu
   ══════════════════════════════════════════════════════════════════════
   Loaded after CandlestickChart.css. Looks only - what is in the menus and what each item
   does is unchanged.

   What was wrong: in dark mode both menus sat on --bk-elevated, which is the chart's own
   colour (#151619), so they read as a hole cut in the chart with a border round it; a rule
   under every row turned a short list into a stack of cards; and hovering an item turned
   its label GREY, which reads as disabled rather than as "this one". Now: a surface one
   step above the chart, rows with no rules between them, lines only where one group of
   actions ends and the next begins, and a hover that lifts the row instead of dimming it.

   Colours apply on every layout. Row sizes are desktop only (the same query topbar.css
   uses): the phone sizes both menus for touch in CandlestickChart.css and mobile.css, and
   those stay as they are. */

/* --- Surface ----------------------------------------------------------------------- */
.context-menu.context-menu,
.navbar-menu.navbar-menu {
  background: #FFFFFF;
  box-shadow:
    inset 0 0 0 1px rgba(0, 0, 0, 0.08),
    0 1px 2px rgba(0, 0, 0, 0.06),
    0 12px 32px rgba(0, 0, 0, 0.12);
  border: none;
  border-radius: 10px;
}
.dark-mode .context-menu.context-menu,
.navbar-menu.navbar-menu.dark-mode {
  background: #1C1D21;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.08),
    0 1px 2px rgba(0, 0, 0, 0.4),
    0 14px 36px rgba(0, 0, 0, 0.55);
}

/* --- Rows -------------------------------------------------------------------------- */
/* No rule under every row. */
.context-menu .context-menu-item + .context-menu-item,
.navbar-menu .navbar-menu-item + .navbar-menu-item {
  box-shadow: none;
}

.context-menu .context-menu-item,
.navbar-menu .navbar-menu-item {
  border: none;
  color: var(--bk-text);
}
/* The icons a step quieter than the labels, and full colour on the row being pointed at. */
.context-menu .context-menu-item svg,
.navbar-menu .navbar-menu-item svg {
  color: var(--bk-text-2);
  transition: color 150ms ease;
}
.dark-mode .context-menu .context-menu-item svg,
.navbar-menu.dark-mode .navbar-menu-item svg {
  color: #A3A3A3;
}

/* Hover lifts the row and keeps the label at full colour - it used to fade the label to
   grey, the look of a disabled item. */
.context-menu .context-menu-item:hover,
.navbar-menu .navbar-menu-item:hover {
  background: rgba(0, 0, 0, 0.05);
  color: var(--bk-text);
}
.dark-mode .context-menu .context-menu-item:hover,
.navbar-menu.dark-mode .navbar-menu-item:hover {
  background: rgba(255, 255, 255, 0.07);
  color: #FFFFFF;
}
.context-menu .context-menu-item:hover svg,
.navbar-menu .navbar-menu-item:hover svg {
  color: currentColor;
}
.context-menu .context-menu-item:active,
.navbar-menu .navbar-menu-item:active {
  background: rgba(0, 0, 0, 0.08);
}
.dark-mode .context-menu .context-menu-item:active,
.navbar-menu.dark-mode .navbar-menu-item:active {
  background: rgba(255, 255, 255, 0.1);
}

/* The panel this item opened is the one on screen. */
.navbar-menu .navbar-menu-item.active {
  background: rgba(0, 0, 0, 0.05);
}
.navbar-menu.dark-mode .navbar-menu-item.active {
  background: rgba(255, 255, 255, 0.07);
}

/* The two that throw work away go red when pointed at, so they are never clicked as
   casually as the rest. */
.context-menu .context-menu-item.danger:hover,
.context-menu .context-menu-item.danger:hover svg {
  color: var(--bk-neg);
}

/* Keyboard hint at the right edge, quieter than the label. */
.context-menu .context-menu-shortcut {
  color: var(--bk-text-3);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.02em;
}
.dark-mode .context-menu .context-menu-shortcut {
  color: #7A7A7A;
}
.context-menu .context-menu-item:hover .context-menu-shortcut {
  color: var(--bk-text-2);
}

/* --- Between groups ---------------------------------------------------------------- */
.context-menu .menu-separator,
.navbar-menu .menu-separator {
  flex: 0 0 auto;
  height: 1px;
  margin: 5px 6px;
  background: rgba(0, 0, 0, 0.08);
}
.dark-mode .context-menu .menu-separator,
.navbar-menu.dark-mode .menu-separator {
  background: rgba(255, 255, 255, 0.08);
}

/* --- Desktop sizes ----------------------------------------------------------------- */
@media (min-width: 769px) and (min-height: 501px), (min-width: 769px) and (orientation: portrait) {
  .context-menu.context-menu,
  .navbar-menu.navbar-menu {
    padding: 5px;
    gap: 0;
  }
  .context-menu.context-menu {
    min-width: 230px;
  }
  .navbar-menu.navbar-menu {
    min-width: 240px;
  }

  .context-menu .context-menu-item,
  .navbar-menu .navbar-menu-item {
    height: 32px;
    min-height: 32px;
    padding: 0 10px;
    gap: 10px;
    border-radius: 6px;
    font-family: var(--font-ui);
    font-size: 13px;
    font-weight: 500;
    line-height: 1;
  }
  .context-menu .context-menu-item svg,
  .navbar-menu .navbar-menu-item svg {
    width: 15px;
    height: 15px;
    flex: 0 0 auto;
  }
}
/* What the free plan does not include, shown as such rather than hidden: the alert forms
   with a note above them, layout cells past two charts and the higher AI effort levels,
   greyed. Only ever drawn for an account whose plan has these limits (planLimits.js). */

.plan-upgrade-note {
  margin: 0 0 14px;
  padding: 12px 14px;
  border-radius: 10px;
  background: rgba(124, 92, 255, 0.08);
  box-shadow: inset 0 0 0 1px rgba(124, 92, 255, 0.22);
  color: var(--bk-text);
  font-size: 12.5px;
  line-height: 1.5;
}
.plan-upgrade-note strong {
  font-weight: 600;
}
.dark-mode .plan-upgrade-note,
.dark-mode.price-alerts-modal .plan-upgrade-note {
  background: rgba(124, 92, 255, 0.12);
  box-shadow: inset 0 0 0 1px rgba(124, 92, 255, 0.3);
}

/* "Paid plans" next to a locked option's name. */
.plan-lock-tag {
  margin-left: auto;
  padding: 1px 6px;
  border-radius: 999px;
  background: rgba(124, 92, 255, 0.12);
  color: #7C5CFF;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.dark-mode .plan-lock-tag {
  background: rgba(124, 92, 255, 0.2);
  color: #B3A1FF;
}

.ai-side-panel .ai-mode-option.locked {
  cursor: default;
  opacity: 0.55;
}
.ai-side-panel .ai-mode-option.locked:hover {
  background: transparent;
}

/* Layout cells past the plan's chart count: still there, plainly unavailable. */
.layout-grid-cell.locked,
.layout-grid-cell.locked.preview {
  cursor: not-allowed;
  background: repeating-linear-gradient(
    135deg,
    rgba(142, 142, 147, 0.14) 0 3px,
    rgba(142, 142, 147, 0.05) 3px 6px
  );
}

/* "Upgrade" on the right of the top bar, just before the menu. A small pill with a light
   violet tint - plainly a button, quieter than a filled one. It takes the free space to its
   left, so the menu's own cell keeps its place over the price scale. */
.chart-container .navbar .navbar-upgrade-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex-shrink: 0;
  height: 26px;
  margin-left: auto;
  margin-right: 6px;
  padding: 0 11px 0 9px;
  border: none;
  border-radius: 999px;
  background: rgba(124, 58, 237, 0.1);
  color: #6D28D9;
  font-family: var(--font-ui);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.chart-container .navbar .navbar-upgrade-btn:hover { background: rgba(124, 58, 237, 0.16); }
.chart-container.dark-mode .navbar .navbar-upgrade-btn { background: rgba(167, 139, 250, 0.14); color: #DDD6FE; }
.chart-container.dark-mode .navbar .navbar-upgrade-btn:hover { background: rgba(167, 139, 250, 0.22); color: #FFFFFF; }
.chart-container .navbar .navbar-upgrade-btn svg { color: #A78BFA; }
.chart-container .navbar .navbar-upgrade-btn + .navbar-right { margin-left: 0; }
/* A narrower window: the spark alone, so the bar still fits without scrolling. */
@media (max-width: 1239px) {
  .chart-container .navbar .navbar-upgrade-btn { width: 28px; padding: 0; justify-content: center; }
  .chart-container .navbar .navbar-upgrade-label { display: none; }
}

.plan-upgrade-chip {
  margin-left: 8px;
  padding: 3px 10px;
  border: none;
  border-radius: 999px;
  background: linear-gradient(135deg, #7C3AED, #D946EF);
  color: #FFFFFF;
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 650;
  letter-spacing: 0.01em;
  vertical-align: middle;
  cursor: pointer;
}
.plan-upgrade-chip:hover { filter: brightness(1.1); }
.plan-upgrade-note .plan-upgrade-chip { margin-left: 6px; }

.profile-action-btn.profile-upgrade-btn {
  background: linear-gradient(135deg, rgba(124, 58, 237, 0.12), rgba(217, 70, 239, 0.12));
  border-color: rgba(168, 85, 247, 0.35);
  color: #7C3AED;
  font-weight: 650;
}
.dark-mode .profile-action-btn.profile-upgrade-btn,
.profile-action-btn.profile-upgrade-btn:where(.dark-mode *) {
  color: #C4B5FD;
}

/* Above the Chartify AI input once a free account's credits are spent. */
.ai-out-of-credits {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 0 12px 8px;
  padding: 10px 12px;
  border-radius: 12px;
  background: rgba(124, 92, 255, 0.1);
  box-shadow: inset 0 0 0 1px rgba(124, 92, 255, 0.25);
  font-family: var(--font-ui);
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--bk-text);
}
.ai-out-of-credits button {
  flex: 0 0 auto;
  padding: 6px 12px;
  border: none;
  border-radius: 999px;
  background: linear-gradient(135deg, #7C3AED, #D946EF);
  color: #FFFFFF;
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 650;
  cursor: pointer;
}
.ai-out-of-credits button:hover { filter: brightness(1.1); }
/* ══════════════════════════════════════════════════════════════════════
   The phone layout
   ══════════════════════════════════════════════════════════════════════
   Everything here is scoped to .chart-container.phone-ui, a class the chart only sets while
   isPhoneLayout is true - so not one rule of this file can reach the desktop. It is loaded
   after the other stylesheets and every selector starts with that pair of classes, which is
   what lets it overrule the older phone rules in CandlestickChart.css without touching them.

   The layout, top to bottom:
   - Top bar: profile, then market, timeframe, Trading Panel, Replay and the menu - each an
     icon over a short label, evenly spaced, drawn exactly like the bottom bar.
   - The chart, the full width: the drawing tools are not a permanent column any more. The
     pencil button (.phone-draw-fab) brings the rail up out of itself and it tucks away again
     once a tool is picked.
   - One bar at the bottom, in the thumb's reach: AI Painter, Chart Scan, Chartify AI in the
     middle, Indicators, Journal. It replaces the two bars that were stacked there (the
     Chartify AI strip with the clock, and market / indicators / replay). The clock's UTC
     switch and the Strategy Tester toggle moved into the menu. */

/* ── The one button style, top bar and bottom bar ────────────────────── */

/* Both bars use the same button: an icon over a short label, no box around it, quiet until
   pressed. Written once as a list of the buttons it applies to, so the two bars cannot drift
   apart. */
.chart-container.phone-ui .phone-top-row > *,
.chart-container.phone-ui .phone-top-row .timeframe-dropdown-container > .timeframe-dropdown-btn,
.chart-container.phone-ui .navbar-right .icon-btn,
.chart-container.phone-ui .phone-nav .indicators-btn {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  width: auto;
  min-width: 0;
  height: 100%;
  min-height: 0;
  margin: 0;
  padding: 4px 2px;
  border: none;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  color: var(--bk-text-2);
  font-family: var(--font-ui);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.01em;
  line-height: 1.1;
  white-space: nowrap;
}

.chart-container.phone-ui .phone-top-row svg,
.chart-container.phone-ui .navbar-right .icon-btn svg,
.chart-container.phone-ui .phone-nav .indicators-btn svg {
  width: 21px;
  height: 21px;
  flex: 0 0 auto;
}

.chart-container.phone-ui .phone-top-row > *:active,
.chart-container.phone-ui .phone-top-row .timeframe-dropdown-btn:active,
.chart-container.phone-ui .navbar-right .icon-btn:active,
.chart-container.phone-ui .phone-nav .indicators-btn:active {
  color: var(--bk-text);
}

/* The labels inside the buttons (the market's name, the timeframe, "Indicators") carry their
   own size and colour from the older rules; here they are plain labels like the rest. */
.chart-container.phone-ui .phone-top-row .symbol-text,
.chart-container.phone-ui .phone-top-row .timeframe-text,
.chart-container.phone-ui .phone-nav .indicators-text {
  color: inherit;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.01em;
}

/* The desktop bar draws its separators as ::after lines on these buttons; neither phone bar
   has any. */
.chart-container.phone-ui .navbar .indicators-btn::after,
.chart-container.phone-ui .phone-nav .indicators-btn::after {
  display: none;
}

/* ── Top bar ─────────────────────────────────────────────────────────── */

/* A grid: the profile picture, then the buttons in equal columns - the market's name gets no
   more room than Replay does, so nothing leaves a hole in the row. As many columns as there
   are buttons: Replay hides itself while a replay runs, and the other four close up. */
.chart-container.phone-ui .navbar {
  display: grid;
  grid-template-columns: 42px;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  align-items: stretch;
  gap: 0;
  height: 56px;
  min-height: 56px;
  padding: 0 4px 0 4px;
  box-sizing: border-box;
}

.chart-container.phone-ui .navbar-left {
  display: flex;
  align-items: center;
  /* The picture sits clear of the line on the column's right edge (its ::after). */
  justify-content: flex-start;
  padding-left: 2px;
  width: auto;
  margin: 0;
}

.chart-container.phone-ui .navbar-left .profile-picture {
  width: 30px;
  height: 30px;
  font-size: 13px;
}

.chart-container.phone-ui .navbar-wordmark {
  display: none;
}

/* Its buttons take the navbar's columns directly. */
.chart-container.phone-ui .phone-top-row {
  display: contents;
}

.chart-container.phone-ui .phone-top-row .timeframe-dropdown-container {
  display: flex;
  min-width: 0;
  height: 100%;
}

.chart-container.phone-ui .phone-top-row .timeframe-dropdown-container > .timeframe-dropdown-btn {
  flex: 1 1 auto;
}

/* The market: its logo is the icon, its name the label. */
.chart-container.phone-ui .phone-top-row .symbol-logo-small {
  display: flex;
  width: 21px;
  height: 21px;
  flex: 0 0 auto;
}

.chart-container.phone-ui .phone-top-row .symbol-text {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 10.5px;
  font-weight: 600;
}

.chart-container.phone-ui .phone-top-row .symbol-btn::after {
  display: none;
}

/* The timeframe: a clock for its icon and the value ("1m") for its label. The chevron goes -
   no other button in either bar has one. */
.chart-container.phone-ui .phone-top-row .timeframe-dropdown-btn::before {
  content: '';
  display: block;
  width: 21px;
  height: 21px;
  flex: 0 0 auto;
  /* The icon colour Replay and Trading Panel take from .indicators-btn svg - brighter than the
     label under it. */
  background: #1D1D1F;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpolyline points='12 7 12 12 15 14'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpolyline points='12 7 12 12 15 14'/%3E%3C/svg%3E") center / contain no-repeat;
}

.chart-container.phone-ui .phone-top-row .timeframe-chevron {
  display: none;
}

.chart-container.phone-ui .phone-top-row .timeframe-text {
  font-size: 10.5px;
  font-weight: 600;
}

/* .indicators-btn svg strokes its icons brighter than the label; the masked clock and the menu's
   lines are not .indicators-btn, so they are given the same colour here. */
.chart-container.phone-ui.dark-mode .phone-top-row .timeframe-dropdown-btn::before,
.dark-mode .chart-container.phone-ui .phone-top-row .timeframe-dropdown-btn::before {
  background: #F7F7F7;
}

.chart-container.phone-ui .navbar-right .icon-btn svg {
  stroke: #1D1D1F;
}

.chart-container.phone-ui.dark-mode .navbar-right .icon-btn svg,
.dark-mode .chart-container.phone-ui .navbar-right .icon-btn svg {
  stroke: #F7F7F7;
}

/* The menu takes the last column like any other button, and is labelled like them. */
.chart-container.phone-ui .navbar-right {
  display: flex;
  width: auto !important;
  min-width: 0;
  height: 100%;
  margin: 0;
  padding: 0;
  border: none;
}

.chart-container.phone-ui .navbar-right::before,
.chart-container.phone-ui .navbar-right::after {
  display: none;
}

.chart-container.phone-ui .navbar-right .icon-btn {
  flex: 1 1 auto;
}

/* ::before, moved below the icon - ::after is the red dot for an unread support reply. */
.chart-container.phone-ui .navbar-right .icon-btn::before {
  content: 'Menu';
  order: 2;
}

/* What it opens: a compact menu in the chart's top-right corner - its top on the line
   between the bar and the chart, its right edge on the line between the chart and the
   price scale, so the prices stay readable while it is open. top and right come from the
   measurement in CandlestickChart.jsx (toolsAnchor); these are only the frame before it
   arrives. */
.chart-container.phone-ui .navbar-menu {
  top: 56px;
  right: 48px;
  min-width: 0;
  max-width: calc(100vw - 72px);
  max-height: calc(var(--app-height, 100dvh) - 56px - 60px - env(safe-area-inset-bottom) - 8px);
  overflow-y: auto;
  padding: 3px;
  border-radius: 10px;
}

/* Rows of 32px rather than the 44px every button gets on a touch screen: still easy to hit,
   and the menu stays a small panel in the corner instead of covering the chart. */
.chart-container.phone-ui .navbar-menu-item {
  height: 32px;
  min-height: 32px !important;
  gap: 8px;
  padding: 0 11px 0 8px;
  font-size: 12px;
}

.chart-container.phone-ui .navbar-menu-item svg {
  width: 13px;
  height: 13px;
}

.chart-container.phone-ui .navbar-menu .menu-separator {
  margin-top: 2px;
  margin-bottom: 2px;
}

/* The report button moves from the foot of the rail into the menu. */
.chart-container.phone-ui .drawing-toolbar .tool-btn-bug-report {
  display: none;
}

/* ── The chart ───────────────────────────────────────────────────────── */

/* The bottom bar is 60px; the strip that used to sit on top of it is gone. */
.chart-container.phone-ui {
  padding-bottom: calc(60px + env(safe-area-inset-bottom));
}

.chart-container.phone-ui .chart-layout {
  position: relative;
}

/* Replay's transport bar and the notice above it are fixed to the window and were placed for
   the old 38px strip, so the 60px bar covered half of them. Now they clear the bar and the
   time scale (28px) over it. */
.chart-container.phone-ui .pb-controls {
  bottom: calc(60px + env(safe-area-inset-bottom) + 28px + 8px);
}

.chart-container.phone-ui .pb-notice {
  bottom: calc(60px + env(safe-area-inset-bottom) + 28px + 8px + 40px);
}

/* The legend in the corner names the market, nothing else: the timeframe is in the top bar
   and the data provider is not something to read on a phone. Its quick actions stay. */
.chart-container.phone-ui .asset-ticker-separator,
.chart-container.phone-ui .asset-ticker-exchange,
.chart-container.phone-ui .asset-ticker-timeframe {
  display: none;
}

/* ── A multi-chart layout on a phone ─────────────────────────────────── */

/* A phone shows only the active pane of a saved multi-chart layout, but the grid still kept
   the desktop's insets for the chrome it pins to the window: 44px on the left for a rail
   that is not a column here, and 44px at the bottom for the strip that is gone. Only the
   top bar's height is left to reserve. :has() because the grid is the chart's parent, which
   the .phone-ui class on the chart cannot reach. */
.chart-grid:has(> .chart-pane > .chart-container.phone-ui) {
  padding: 56px 0 0 0;
}

/* The green frame that says which pane is active means nothing with one pane on screen. */
.chart-grid .chart-pane.active:has(> .chart-container.phone-ui)::after {
  display: none;
}

/* ── The drawing tools ───────────────────────────────────────────────── */

/* The pencil: bottom left of the chart, clear of the time axis. */
.chart-container.phone-ui .phone-draw-fab {
  position: absolute;
  left: 12px;
  bottom: 42px;
  z-index: 91;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--bk-border);
  background: var(--bk-elevated);
  color: var(--bk-text);
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.28);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, transform 0.12s ease;
}

.chart-container.phone-ui .phone-draw-fab:active {
  transform: scale(0.94);
}

/* A drawing tool is in hand: the chart draws on a tap instead of scrolling. */
.chart-container.phone-ui .phone-draw-fab.drawing {
  background: var(--brand, #4C29E9);
  border-color: transparent;
  color: #FFFFFF;
}

.chart-container.phone-ui .phone-draw-fab.open {
  background: var(--bk-text);
  border-color: transparent;
  color: var(--bk-elevated);
}

/* The rail grows up out of the pencil: it stands on the button - its bottom edge just above
   it, centred on it - and rises from there, so it reads as the button opening rather than
   as a panel arriving from somewhere else. Tucked away it is pulled down into the button and
   faded out. */
.chart-container.phone-ui .drawing-toolbar {
  position: absolute;
  top: auto;
  bottom: calc(42px + 46px + 8px);
  left: 11px;
  z-index: 90;
  width: 48px;
  min-width: 48px;
  height: auto;
  max-height: calc(100% - 42px - 46px - 20px);
  padding: 6px 0;
  overflow-y: auto;
  border: 1px solid var(--bk-border);
  border-radius: 16px;
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.32);
  transform-origin: 50% 100%;
  transform: translateY(24px) scale(0.92);
  opacity: 0;
  pointer-events: none;
  transition: transform 0.24s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.18s ease;
}

.chart-container.phone-ui.phone-rail-open .drawing-toolbar {
  transform: none;
  opacity: 1;
  pointer-events: auto;
}

@media (prefers-reduced-motion: reduce) {
  .chart-container.phone-ui .drawing-toolbar,
  .chart-container.phone-ui .phone-draw-fab {
    transition: none;
  }
}

/* ── The bottom bar ──────────────────────────────────────────────────── */

.chart-container.phone-ui .phone-nav {
  top: calc(var(--app-height, 100dvh) - 60px - env(safe-area-inset-bottom));
  height: calc(60px + env(safe-area-inset-bottom));
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  align-items: stretch;
  gap: 0;
  padding: 0 4px env(safe-area-inset-bottom);
  overflow: visible;
}

.chart-container.phone-ui .phone-nav .indicators-btn {
  height: 60px;
  padding: 6px 2px 5px;
}

/* Indicators carries its label in a span the desktop hides on narrow widths. */
.chart-container.phone-ui .phone-nav .indicators-text {
  display: inline;
}

/* How many indicators are on: a small count on the icon's corner. */
.chart-container.phone-ui .phone-nav .indicators-count {
  position: absolute;
  top: 5px;
  left: calc(50% + 6px);
  min-width: 15px;
  height: 15px;
  padding: 0 4px;
  border-radius: 8px;
  box-sizing: border-box;
  background: var(--brand, #4C29E9);
  color: #FFFFFF;
  font-size: 9.5px;
  font-weight: 700;
  line-height: 15px;
  text-align: center;
}

/* Chartify AI: in line with the others, the same size - marked out only by its colour. */
.chart-container.phone-ui .phone-nav .phone-nav-ai {
  color: var(--brand, #4C29E9);
}

/* The brand purple is too dark to read as text on the dark bar; the lighter tint the script
   editor uses for its accents in dark mode. */
.chart-container.phone-ui.dark-mode .phone-nav .phone-nav-ai {
  color: #A897FF;
}

.chart-container.phone-ui .phone-nav .phone-nav-ai-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 21px;
  height: 21px;
}

.chart-container.phone-ui .phone-nav .phone-nav-ai .phone-nav-ai-mark svg {
  width: 21px;
  height: 21px;
}

/* What is left of a metered tool's allowance, on the icon's corner rather than in the label. */
.chart-container.phone-ui .phone-nav .feature-remaining {
  position: absolute;
  top: 5px;
  left: calc(50% + 7px);
  margin: 0;
  padding: 0 5px;
  font-size: 9px;
  line-height: 15px;
}

/* ── Replay: picking the start ───────────────────────────────────────────
   At 375 x 667 the picker came to about 730px in a sheet of 547, so the time field and
   Start were below the fold and it had to be scrolled to be used. The stack stays the
   same - Select on Chart, OR, the calendar, the time, Start - only smaller: a shorter
   Select on Chart card, a tighter calendar, and the 44px floor
   every phone button gets (mobile.css) lifted from the controls that are not the main
   targets here. */
.chart-container.phone-ui .replay-modal .modal-header {
  position: relative;
  justify-content: center;
  padding: 10px 48px 6px;
}

.chart-container.phone-ui .replay-modal .modal-header h3 {
  font-size: 17px;
}

/* The title is centred on the sheet; the close button sits apart at the right, so it
   does not push the title off centre. */
.chart-container.phone-ui .replay-modal .modal-header h3 {
  text-align: center;
}

.chart-container.phone-ui .replay-modal .close-btn {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  width: 32px;
  height: 32px;
  min-width: 0;
  min-height: 0;
  padding: 0;
}

/* max-width: none undoes mobile.css's 95vw cap on .modal-content: inside a sheet the full
   width of the screen it left the content 18px short of the right edge, so the cards sat
   13px from the left and 30px from the right. */
.chart-container.phone-ui .replay-modal-content {
  max-width: none;
  padding: 10px 12px 12px;
}

.chart-container.phone-ui .replay-modal .replay-mode-buttons {
  gap: 6px;
}

/* Select on Chart: the first way in, so a card of its own - the icon above, the two
   lines under it, all centred - but shorter than the desktop card. */
.chart-container.phone-ui .replay-modal .replay-mode-btn:not(.replay-datetime-confirm) {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  text-align: center;
  padding: 12px 14px;
  min-height: 0;
}

.chart-container.phone-ui .replay-modal .replay-mode-btn:not(.replay-datetime-confirm) .replay-mode-icon {
  font-size: 24px;
  line-height: 1;
  margin-bottom: 2px;
}

.chart-container.phone-ui .replay-modal .replay-mode-btn:not(.replay-datetime-confirm) .replay-mode-text {
  font-size: 15px;
}

.chart-container.phone-ui .replay-modal .replay-mode-btn:not(.replay-datetime-confirm) .replay-mode-desc {
  font-size: 12px;
}

.chart-container.phone-ui .replay-modal .replay-mode-datetime {
  padding: 10px 12px;
}

.chart-container.phone-ui .replay-modal .replay-datetime-label {
  margin-bottom: 4px;
  font-size: 12px;
}

.chart-container.phone-ui .replay-modal .replay-cal-nav {
  width: 28px;
  height: 28px;
  min-width: 0;
  min-height: 0;
  padding: 0;
}

.chart-container.phone-ui .replay-modal .replay-cal-day {
  height: 25px;
  max-height: 25px;
  min-width: 0;
}

.chart-container.phone-ui .replay-modal .replay-cal-time {
  gap: 8px;
}

.chart-container.phone-ui .replay-modal .replay-time-field {
  padding: 5px 10px;
}

.chart-container.phone-ui .replay-modal .replay-time-seg {
  min-height: 0;
  font-size: 15px;
}

.chart-container.phone-ui .replay-modal .replay-datetime-confirm {
  min-height: 0;
  padding: 9px;
  margin-top: 8px;
}

.chart-container.phone-ui .replay-modal .replay-mode-footer {
  margin-top: 8px;
  font-size: 11px;
  line-height: 1.35;
}
/* ========================================
   LOGIN SCREEN
   Matches the platform's liquid-glass design
   ======================================== */
.login-screen {
  position: relative;
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  overflow: hidden;
  background: #F5F5F7;
  background-image: var(--bg-primary);
  font-family: var(--font-ui);
}

/* Ambient accent glow behind the card */
.login-glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(90px);
  pointer-events: none;
  opacity: 0.35;
}

.login-glow-one {
  width: 460px;
  height: 460px;
  top: -140px;
  left: -120px;
  background: radial-gradient(circle, #8E8E93 0%, rgba(142, 142, 147, 0) 70%);
}

.login-glow-two {
  width: 520px;
  height: 520px;
  bottom: -180px;
  right: -140px;
  background: radial-gradient(circle, #6E6E73 0%, rgba(110, 110, 115, 0) 70%);
}

/* Faint grid, echoing the chart surface */
.login-grid {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: linear-gradient(rgba(0, 0, 0, 0.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 0, 0, 0.035) 1px, transparent 1px);
  background-size: 48px 48px;
  mask-image: radial-gradient(ellipse at center, #000 20%, transparent 75%);
  -webkit-mask-image: radial-gradient(ellipse at center, #000 20%, transparent 75%);
}

/* ========================================
   CARD
   ======================================== */
.login-card {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 420px;
  padding: 40px 36px 28px;
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(40px) saturate(180%);
  -webkit-backdrop-filter: blur(40px) saturate(180%);
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 24px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.12);
  text-align: center;
  animation: loginCardIn 0.5s cubic-bezier(0.16, 1, 0.3, 1) both;
}

@keyframes loginCardIn {
  from {
    opacity: 0;
    transform: translateY(12px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

.login-mark {
  width: 60px;
  height: 60px;
  margin: 0 auto 20px;
  border-radius: 18px;
  /* White in both themes, because the mark is a purple gradient drawn for a light ground -
     it is the same artwork as the app icon, so the tile here reads as that icon. The old
     near-black tile was built for a white glyph that inherited currentColor. */
  background: #FFFFFF;
  border: 1px solid rgba(0, 0, 0, 0.06);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.22);
}

.login-logo {
  display: block;
  width: 36px;
  height: 36px;
}

.login-title {
  font-family: var(--font-ui);
  font-size: 28px;
  font-weight: 700;
  letter-spacing: -0.5px;
  color: #1D1D1F;
  margin: 0 0 8px;
}

.login-subtitle {
  font-size: 15px;
  font-weight: 400;
  line-height: 1.5;
  color: #48484A;
  margin: 0 0 28px;
}

/* ========================================
   ERROR BANNER
   ======================================== */
.login-error {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  text-align: left;
  padding: 14px 16px;
  margin-bottom: 20px;
  background: rgba(255, 59, 48, 0.08);
  border: 1px solid rgba(255, 59, 48, 0.2);
  border-radius: 12px;
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1.45;
  color: #C7261C;
}

.login-error svg {
  flex-shrink: 0;
  margin-top: 1px;
  color: var(--danger-red);
}

/* ========================================
   LOGIN BUTTON
   ======================================== */
.login-button {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  padding: 15px 20px;
  background: linear-gradient(135deg, #2C2C2E 0%, #1D1D1F 100%);
  color: #FFFFFF;
  text-decoration: none;
  border-radius: 14px;
  font-family: var(--font-ui);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.1px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
  transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
}

.login-button:hover {
  ;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.28);
  filter: brightness(1.35);
}

.login-button:active {
  transform: translateY(0);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.2);
}

.login-button svg {
  flex-shrink: 0;
}

.login-footer {
  margin-top: 24px;
  font-size: 12px;
  font-weight: 500;
  color: #8E8E93;
  letter-spacing: 0.01em;
}

/* ========================================
   EMAIL SIGN-IN
   ======================================== */
.login-form {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.login-input {
  width: 100%;
  box-sizing: border-box;
  padding: 14px 16px;
  border-radius: 14px;
  border: 1px solid rgba(0, 0, 0, 0.12);
  background: #FFFFFF;
  color: #1D1D1F;
  font-family: var(--font-ui);
  font-size: 15px;
  font-weight: 500;
  outline: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.login-input::placeholder {
  color: #A1A1A6;
}

.login-input:focus {
  border-color: rgba(0, 0, 0, 0.35);
  box-shadow: 0 0 0 4px rgba(0, 0, 0, 0.06);
}

.login-code-input {
  text-align: center;
  font-size: 24px;
  font-weight: 700;
  letter-spacing: 10px;
  padding-left: 26px; /* balances the trailing letter-spacing so the digits sit centred */
}

.login-turnstile:empty {
  display: none;
}

button.login-button {
  border: none;
  cursor: pointer;
}

.login-button:disabled {
  opacity: 0.5;
  cursor: default;
  filter: none;
  box-shadow: none;
}

/* Whop, once email is the main way in: same size, quieter. */
.login-button.login-button-secondary {
  background: transparent;
  color: #1D1D1F;
  border: 1px solid rgba(0, 0, 0, 0.14);
  box-shadow: none;
}

.login-button.login-button-secondary:hover {
  background: rgba(0, 0, 0, 0.04);
  filter: none;
  box-shadow: none;
}

.login-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 18px 0;
  font-size: 12px;
  font-weight: 500;
  color: #8E8E93;
}

.login-divider::before,
.login-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: rgba(0, 0, 0, 0.1);
}

.login-email {
  color: #1D1D1F;
  font-weight: 600;
  word-break: break-all;
}

.login-links {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-top: 16px;
}

.login-link {
  background: none;
  border: none;
  padding: 4px 0;
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  color: #48484A;
  cursor: pointer;
}

.login-link:hover:not(:disabled) {
  color: #1D1D1F;
  text-decoration: underline;
}

.login-link:disabled {
  color: #A1A1A6;
  cursor: default;
}

/* ========================================
   LOADING STATE
   ======================================== */
.login-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  padding: 8px 0 4px;
}

.login-spinner {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 3px solid rgba(0, 0, 0, 0.12);
  border-top-color: #1D1D1F;
  animation: loginSpin 0.7s linear infinite;
}

@keyframes loginSpin {
  to {
    transform: rotate(360deg);
  }
}

.login-loading-text {
  font-size: 14px;
  font-weight: 500;
  color: #48484A;
}

/* ========================================
   DARK MODE
   ======================================== */
.login-screen.dark-mode {
  background: #000000;
  background-image: none;
}

.dark-mode .login-grid {
  background-image: linear-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
}

.dark-mode .login-glow {
  opacity: 0.28;
}

.dark-mode .login-card {
  background: rgba(20, 20, 22, 0.85);
  border-color: var(--bk-border);
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
}

.dark-mode .login-title {
  color: #F7F7F7;
}

.dark-mode .login-subtitle,
.dark-mode .login-loading-text {
  color: var(--bk-text-3);
}

/* Invert the mark and CTA so they stay legible on the dark card */
.dark-mode .login-mark {
  background: #FFFFFF;
  border-color: var(--bk-border);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
}

.dark-mode .login-button {
  background: linear-gradient(135deg, #FFFFFF 0%, #D8D8DC 100%);
  color: #1D1D1F;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.45);
}

.dark-mode .login-button:hover {
  filter: brightness(1.02);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.55);
}

.dark-mode .login-spinner {
  border-color: var(--bk-border);
  border-top-color: var(--bk-border);
}

.dark-mode .login-error {
  background: rgba(255, 59, 48, 0.12);
  border-color: rgba(255, 59, 48, 0.28);
  color: #FF7A70;
}

.dark-mode .login-footer {
  color: var(--bk-text-3);
}

.dark-mode .login-input {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.14);
  color: #F7F7F7;
}

.dark-mode .login-input::placeholder {
  color: #5E5E62;
}

.dark-mode .login-input:focus {
  border-color: rgba(255, 255, 255, 0.4);
  box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.06);
}

.dark-mode .login-button.login-button-secondary {
  background: transparent;
  color: #F7F7F7;
  border-color: rgba(255, 255, 255, 0.16);
}

.dark-mode .login-button.login-button-secondary:hover {
  background: rgba(255, 255, 255, 0.06);
}

.dark-mode .login-divider {
  color: var(--bk-text-3);
}

.dark-mode .login-divider::before,
.dark-mode .login-divider::after {
  background: rgba(255, 255, 255, 0.1);
}

.dark-mode .login-email {
  color: #F7F7F7;
}

.dark-mode .login-link {
  color: #A1A1A6;
}

.dark-mode .login-link:hover:not(:disabled) {
  color: #F7F7F7;
}

.dark-mode .login-link:disabled {
  color: #5E5E62;
}

/* ========================================
   MOBILE
   ======================================== */
@media (max-width: 480px) {
  .login-screen {
    padding: 16px;
  }

  .login-card {
    padding: 32px 24px 24px;
    border-radius: 20px;
  }

  .login-title {
    font-size: 24px;
  }

  .login-subtitle {
    font-size: 14px;
    margin-bottom: 24px;
  }

  .login-button {
    min-height: 50px;
  }
}

/* Short viewports (landscape phones): tighten the card */
@media (max-height: 620px) {
  .login-card {
    padding: 28px 24px 22px;
  }

  .login-subtitle {
    margin-bottom: 22px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .login-card {
    animation: none;
  }

  .login-spinner {
    animation-duration: 1.6s;
  }

  .login-button:hover {
    transform: none;
  }
}

/* The Swift Algo members' page. */
.login-eyebrow {
  display: inline-block;
  margin: -6px 0 12px;
  padding: 4px 11px;
  border-radius: 999px;
  background: rgba(124, 92, 255, 0.1);
  color: #6D4AFF;
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 650;
  letter-spacing: 0.02em;
}
.dark-mode .login-eyebrow {
  background: rgba(124, 92, 255, 0.18);
  color: #B9A7FF;
}
.login-footer-link {
  color: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.login-footer-link:hover { color: #1D1D1F; }
.dark-mode .login-footer-link:hover { color: #F7F7F7; }
/* A sheet rising from the bottom rather than a centred box: it is the shape a phone user
   already reads as "the system is offering me something", and it keeps the chart visible
   above it so the offer has context. */

.install-sheet-backdrop {
  position: fixed;
  inset: 0;
  z-index: 12000;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: rgba(0, 0, 0, 0.55);
  animation: installFade 0.22s ease both;
  /* Tapping outside closes it, but without remembering - a mis-tap should not be the
     last time the offer is ever made. */
  cursor: default;
}

.install-sheet-backdrop.closing {
  animation: installFade 0.2s ease both reverse;
}

.install-sheet {
  width: 100%;
  max-width: 460px;
  box-sizing: border-box;
  padding: 10px 20px calc(20px + env(safe-area-inset-bottom, 0px));
  background: var(--bk-panel);
  border-top: 1px solid var(--bk-border);
  border-radius: 20px 20px 0 0;
  box-shadow: 0 -8px 40px rgba(0, 0, 0, 0.35);
  animation: installRise 0.28s cubic-bezier(0.33, 1, 0.68, 1) both;
  font-family: var(--font-ui);
}

.install-sheet-backdrop.closing .install-sheet {
  animation: installRise 0.2s ease both reverse;
}

@keyframes installFade {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes installRise {
  from { transform: translateY(100%); }
  to { transform: translateY(0); }
}

/* The handle every bottom sheet has. Decorative, but its absence is noticed. */
.install-grip {
  width: 36px;
  height: 4px;
  margin: 0 auto 16px;
  border-radius: 2px;
  background: var(--bk-border-strong);
}

.install-head {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  margin-bottom: 18px;
}

.install-icon {
  flex-shrink: 0;
  width: 52px;
  height: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 12px;
  background: var(--bk-input);
  overflow: hidden;
}

.install-icon img {
  width: 44px;
  height: 44px;
  border-radius: 9px;
}

.install-head-text h2 {
  margin: 2px 0 6px;
  font-size: 17px;
  font-weight: 650;
  line-height: 1.25;
  letter-spacing: -0.2px;
  color: var(--bk-text);
}

.install-head-text p {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--bk-text-2);
}

/* Android's one-tap path. Full width because it is the only thing to do here. */
.install-cta {
  display: block;
  width: 100%;
  padding: 13px;
  border: 0;
  border-radius: 12px;
  background: var(--brand);
  font-family: var(--font-ui);
  font-size: 15px;
  font-weight: 600;
  color: #FFFFFF;
  cursor: pointer;
  transition: background 0.15s ease;
}

.install-cta:active {
  background: var(--brand-hover);
}

/* Numbered because the order matters and the user is following along on a screen they
   cannot see this sheet on once they start. */
.install-steps {
  list-style: none;
  margin: 0;
  padding: 0;
}

.install-steps li {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 7px;
  padding: 9px 0;
  font-size: 14px;
  line-height: 1.4;
  color: var(--bk-text);
  border-bottom: 1px solid var(--bk-divider);
}

.install-steps li:last-child {
  border-bottom: 0;
}

.install-step-n {
  flex-shrink: 0;
  width: 21px;
  height: 21px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--bk-input);
  font-size: 11.5px;
  font-weight: 650;
  color: var(--bk-text-2);
}

.install-steps b {
  font-weight: 650;
}

/* Drawn rather than named: "the share button" is a description, the glyph is the thing
   they are looking for. */
.install-inline-icon {
  width: 17px;
  height: 17px;
  vertical-align: middle;
  color: #0A84FF;
}

.install-note {
  margin: 0;
  padding: 12px 14px;
  border-radius: 12px;
  background: var(--bk-input);
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--bk-text);
}

/* Quiet, and it is the one that remembers - saying no once should be enough. */
.install-dismiss {
  display: block;
  width: 100%;
  margin-top: 14px;
  padding: 11px;
  border: 0;
  border-radius: 12px;
  background: transparent;
  font-family: var(--font-ui);
  font-size: 14px;
  font-weight: 500;
  color: var(--bk-text-2);
  cursor: pointer;
}

.install-dismiss:active {
  background: var(--bk-hover);
}

/* The dark palette, restated on the sheet itself. It is mounted beside the chart rather
   than inside it, and the app puts .dark-mode on components rather than on the document,
   so there is nothing above it to inherit from. */
.install-sheet.dark-mode {
  --bk-panel: #080808;
  --bk-input: #141414;
  --bk-hover: #191919;
  --bk-border: #242424;
  --bk-border-strong: #303030;
  --bk-divider: rgba(255, 255, 255, .075);
  --bk-text: #F7F7F7;
  --bk-text-2: #949494;
}
/* The first-run walkthrough.
   ──────────────────────────
   Everything here is scoped under .tour-root and nothing outside it is touched, so the tour
   can be removed by deleting one element. */

.tour-root {
  position: fixed;
  inset: 0;
  /* Above everything, and that is not a round number chosen for comfort.
     ────────────────────────────────────────────────────────────────────
     3000 cleared the navbar and the layout panel, which is all the app tour needed. The
     feature panels sit at 10000 and above - the Painter's card was drawn correctly and then
     hidden behind the very panel it was explaining. The highest z-index anywhere else in
     this app is 999999, so the tour sits one step past it: a walkthrough that something can
     cover is a walkthrough that does not work. */
  z-index: 1000000;
  font-family: var(--font-ui);
}

/* The fade lives on the layers, never on .tour-root.
   ─────────────────────────────────────────────────
   An ancestor with an opacity animation becomes the backdrop root for everything inside it,
   and a backdrop-filter can only blur what is inside ITS backdrop root - which, in that
   arrangement, is nothing. The tour spent its first run with a perfectly valid
   `blur(3px)` computed on the panels and a perfectly unblurred chart behind them; raising it
   to 14px changed nothing, which is what gave it away. Fading each layer on its own keeps
   the chart in the frost's backdrop where it belongs. */
.tour-frost,
.tour-ring,
.tour-card {
  animation: tour-in 260ms ease both;
}

.tour-root.leaving .tour-frost,
.tour-root.leaving .tour-ring,
.tour-root.leaving .tour-card {
  animation: tour-out 200ms ease both;
}

@keyframes tour-in  { from { opacity: 0 } to { opacity: 1 } }
@keyframes tour-out { from { opacity: 1 } to { opacity: 0 } }

/* Catches the click, so nothing behind reacts while the tour is talking about it. */
.tour-blocker {
  position: absolute;
  inset: 0;
  cursor: default;
}

/* The frosted area, in four pieces around the cut-out. Position and size are animated, not
   opacity: the four panels are one shape as far as the eye is concerned, and moving that
   shape from one control to the next is the whole effect. */
.tour-frost {
  position: absolute;
  background: rgba(8, 8, 10, 0.46);
  /* !important, and the only place in the app that needs it.
     ──────────────────────────────────────────────────────────
     The stylesheet turns glass off everywhere with `*, *::before, *::after { backdrop-filter:
     none !important }` - a deliberate house rule, not an oversight. This is the one surface
     where the blur IS the message: it says "the thing in focus is over there, everything else
     can wait". A class beats the universal selector at equal importance, so this carve-out is
     exactly as wide as the tour and not a pixel wider. */
  backdrop-filter: blur(4px) saturate(108%) !important;
  -webkit-backdrop-filter: blur(4px) saturate(108%) !important;
  pointer-events: none;
  transition:
    top 420ms cubic-bezier(0.32, 0.72, 0, 1),
    left 420ms cubic-bezier(0.32, 0.72, 0, 1),
    width 420ms cubic-bezier(0.32, 0.72, 0, 1),
    height 420ms cubic-bezier(0.32, 0.72, 0, 1);
}

/* The frame around the lit control. Drawn just outside it - see PAD - so the control keeps
   its own shape and colours instead of wearing a border. */
.tour-ring {
  position: absolute;
  border-radius: 12px;
  pointer-events: none;
  box-shadow:
    0 0 0 2px rgba(var(--brand-rgb), 0.95),
    0 0 0 6px rgba(var(--brand-rgb), 0.22),
    0 8px 28px rgba(0, 0, 0, 0.35);
  transition:
    top 420ms cubic-bezier(0.32, 0.72, 0, 1),
    left 420ms cubic-bezier(0.32, 0.72, 0, 1),
    width 420ms cubic-bezier(0.32, 0.72, 0, 1),
    height 420ms cubic-bezier(0.32, 0.72, 0, 1);
}

/* A slow breath on the ring, so the eye finds it without being shouted at. Deliberately not
   a flash: this sits on screen for as long as it takes to read a paragraph. */
.tour-ring::after {
  content: '';
  position: absolute;
  inset: -2px;
  border-radius: 14px;
  box-shadow: 0 0 0 0 rgba(var(--brand-rgb), 0.45);
  animation: tour-pulse 2.4s ease-out infinite;
}

@keyframes tour-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(var(--brand-rgb), 0.42) }
  70%  { box-shadow: 0 0 0 12px rgba(var(--brand-rgb), 0) }
  100% { box-shadow: 0 0 0 0 rgba(var(--brand-rgb), 0) }
}

/* ── The card ─────────────────────────────────────────────────────────────── */

/* Colours written out rather than taken from the tokens.
   ─────────────────────────────────────────────────────
   The theme class sits on .chart-container, and the tour is mounted beside it in .App - so
   --bk-elevated resolves to the LIGHT value no matter what the app is wearing, and the first
   run of this card was a white panel on a black chart. The tour reads the chart's class in
   JS and sets .dark on itself; these are the two sides of that. */
.tour-card {
  position: absolute;
  width: min(380px, calc(100vw - 24px));
  padding: 18px 18px 14px;
  border-radius: 16px;
  background: #FFFFFF;
  border: 1px solid rgba(142, 142, 147, 0.25);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.22);
  color: #0B0B0B;
  /* Position is animated so the card glides from control to control instead of cutting. */
  transition:
    top 420ms cubic-bezier(0.32, 0.72, 0, 1),
    left 420ms cubic-bezier(0.32, 0.72, 0, 1);
}

/* No anchor on screen - the step plays in the middle, over a fully frosted app. */
.tour-card.centred {
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  transition: none;
}

/* The text swaps per step. Keyed in the JSX, so this runs on each one. */
.tour-card-body {
  animation: tour-text-in 340ms cubic-bezier(0.32, 0.72, 0, 1) both;
}

@keyframes tour-text-in {
  from { opacity: 0; transform: translateY(6px) }
  to   { opacity: 1; transform: none }
}

.tour-step-count {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #8A8A8A;
}

.tour-title {
  margin: 6px 0 8px;
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.tour-text {
  margin: 0;
  font-size: 14px;
  line-height: 1.55;
  color: #5E5E5E;
}

/* ── Progress ─────────────────────────────────────────────────────────────── */

.tour-dots {
  display: flex;
  gap: 5px;
  margin: 16px 0 14px;
}

/* The segment you are on grows as well as lighting up.
   ───────────────────────────────────────────────────
   Colour alone did not carry it: `.tour-root.dark .tour-dot` is three classes and
   `.tour-dot.on` is two, so in dark mode the grey override won and every segment looked the
   same. The dark rules below are now written per state, and the active one takes more than
   twice the width of its neighbours - which reads at a glance, without hunting for a shade. */
.tour-dot {
  flex: 1 1 0;
  height: 4px;
  border-radius: 2px;
  background: rgba(142, 142, 147, 0.28);
  transition:
    flex-grow 340ms cubic-bezier(0.32, 0.72, 0, 1),
    background 300ms ease;
}

.tour-dot.done { background: rgba(var(--brand-rgb), 0.55) }

.tour-dot.on {
  flex-grow: 2.6;
  background: var(--brand);
  box-shadow: 0 0 8px rgba(var(--brand-rgb), 0.5);
}

/* ── Buttons ──────────────────────────────────────────────────────────────── */

.tour-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.tour-actions-gap { flex: 1 }

.tour-btn {
  padding: 8px 14px;
  border-radius: 9px;
  border: 1px solid transparent;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: background 150ms ease, color 150ms ease, border-color 150ms ease;
}

.tour-btn.primary {
  background: var(--brand);
  color: #FFFFFF;
}

.tour-btn.primary:hover { background: var(--brand-hover) }

.tour-btn.quiet {
  background: transparent;
  border-color: rgba(142, 142, 147, 0.35);
  color: #0B0B0B;
}

.tour-btn.quiet:hover { background: rgba(0, 0, 0, 0.05) }

.tour-btn.ghost {
  padding: 8px 6px;
  background: transparent;
  color: #8A8A8A;
  font-weight: 500;
}

.tour-btn.ghost:hover { color: #0B0B0B }

.tour-btn:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* ── Dark ─────────────────────────────────────────────────────────────────── */

.tour-root.dark .tour-ring {
  box-shadow:
    0 0 0 2px #8B6DFF,
    0 0 0 6px rgba(139, 109, 255, 0.22),
    0 8px 28px rgba(0, 0, 0, 0.45);
}

.tour-root.dark .tour-ring::after {
  animation-name: tour-pulse-dark;
}

@keyframes tour-pulse-dark {
  0%   { box-shadow: 0 0 0 0 rgba(139, 109, 255, 0.42) }
  70%  { box-shadow: 0 0 0 12px rgba(139, 109, 255, 0) }
  100% { box-shadow: 0 0 0 0 rgba(139, 109, 255, 0) }
}

.tour-root.dark .tour-btn:focus-visible { outline-color: #8B6DFF }

.tour-root.dark .tour-card {
  background: #151619;
  border-color: #242424;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.55);
  color: #F7F7F7;
}

.tour-root.dark .tour-text { color: #949494 }
.tour-root.dark .tour-step-count { color: #666666 }

.tour-root.dark .tour-btn.quiet {
  border-color: #2E2E2E;
  color: #F7F7F7;
}

.tour-root.dark .tour-btn.quiet:hover { background: rgba(255, 255, 255, 0.07) }
.tour-root.dark .tour-btn.ghost { color: #8A8A8A }
.tour-root.dark .tour-btn.ghost:hover { color: #F7F7F7 }
/* Per state, and in this order: a blanket `.tour-root.dark .tour-dot` outranks
   `.tour-dot.on` on class count and would grey out the active segment again. */
.tour-root.dark .tour-dot      { background: rgba(255, 255, 255, 0.14) }
.tour-root.dark .tour-dot.done { background: rgba(139, 109, 255, 0.5) }
.tour-root.dark .tour-dot.on   { background: #8B6DFF }

/* ── Phone ────────────────────────────────────────────────────────────────── */

/* The card sits at the bottom rather than chasing a control that may be one of several in a
   40px-tall bar - at that size a card pinned next to it covers its neighbours anyway. The
   ring still moves, so the thing being talked about is still the thing lit up. */
@media (max-width: 768px), (max-height: 500px) and (orientation: landscape) {
  .tour-card,
  .tour-card.centred {
    top: auto !important;
    bottom: 14px;
    left: 12px !important;
    right: 12px;
    width: auto;
    transform: none;
    transition: none;
  }

  /* The control being explained is in the lower half - usually the bottom bar, where
     Indikatoren, Replay and Chartify AI live - so the card takes the other edge rather than
     sitting on top of the thing it is pointing at. */
  .tour-card.at-top {
    top: 14px !important;
    bottom: auto;
  }

  .tour-title { font-size: 17px }
  .tour-text  { font-size: 13.5px }

  /* Skip on the left, Back and Next on the right - one row, the same as anywhere else.
     It used to wrap, which put Next on a line of its own hanging off the edge of the card. */
  .tour-actions { flex-wrap: nowrap }
  .tour-btn { padding: 9px 13px }
  .tour-btn.ghost { padding: 9px 4px }
}

/* Someone who asked for less motion gets the spotlight without the travel. */
@media (prefers-reduced-motion: reduce) {
  .tour-root,
  .tour-frost,
  .tour-ring,
  .tour-card,
  .tour-card-body {
    animation: none !important;
    transition: none !important;
  }
  .tour-ring::after { animation: none !important }
}
/* The welcome video a new Swift Algo member watches before the app unlocks.
   ───────────────────────────────────────────────────────────────────────
   Scoped under .welcome-root, like the tour. Always dark whatever the app is wearing: it is
   a screen for watching a video on, and the frosted chart behind it reads as "still to
   come" much better through a dark veil than a light one. */

.welcome-root {
  position: fixed;
  inset: 0;
  /* One step past the tour, which is itself one past the highest z-index anywhere else. */
  z-index: 1000001;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  overflow-y: auto;
  font-family: var(--font-ui);
  color: #F7F7F7;
}

/* Fades live on the layers, never on .welcome-root: an ancestor with an opacity animation
   becomes the backdrop root and the blur then has nothing to blur. See TourGuide.css. */
.welcome-frost,
.welcome-card {
  animation: welcome-in 320ms ease both;
}

.welcome-root.leaving .welcome-frost,
.welcome-root.leaving .welcome-card {
  animation: welcome-out 240ms ease both;
}

@keyframes welcome-in  { from { opacity: 0 } to { opacity: 1 } }
@keyframes welcome-out { from { opacity: 1 } to { opacity: 0 } }

.welcome-frost {
  position: fixed;
  inset: 0;
  background: rgba(6, 6, 9, 0.62);
  /* !important for the same reason as .tour-frost: the stylesheet turns backdrop-filter off
     everywhere, and this is one of the few surfaces where the blur is the message. */
  backdrop-filter: blur(14px) saturate(110%) !important;
  -webkit-backdrop-filter: blur(14px) saturate(110%) !important;
}

.welcome-card {
  position: relative;
  /* As wide as the screen allows, but never so wide that the video pushes the buttons below
     the fold: 290px is everything in the card other than the video. */
  width: min(860px, 100%, calc((100dvh - 290px) * var(--welcome-aspect, 1.7778)));
  min-width: min(340px, 100%);
  margin: auto;
  padding: 22px 22px 18px;
  border-radius: 20px;
  background: #121317;
  border: 1px solid rgba(255, 255, 255, 0.08);
  box-shadow:
    0 30px 80px rgba(0, 0, 0, 0.6),
    0 0 0 1px rgba(var(--brand-rgb), 0.12);
}

/* ── Lock status ──────────────────────────────────────────────────────────── */

.welcome-status {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 11px;
  border-radius: 999px;
  background: rgba(255, 184, 0, 0.1);
  border: 1px solid rgba(255, 184, 0, 0.28);
  color: #FFC940;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.3;
  transition: background 300ms ease, border-color 300ms ease, color 300ms ease;
}

.welcome-status svg { flex: none }

.welcome-status.open {
  background: rgba(52, 199, 89, 0.12);
  border-color: rgba(52, 199, 89, 0.35);
  color: #4ADE80;
}

.welcome-title {
  margin: 14px 0 6px;
  font-size: 24px;
  font-weight: 700;
  letter-spacing: -0.015em;
}

.welcome-text {
  margin: 0 0 16px;
  max-width: 60ch;
  font-size: 14px;
  line-height: 1.55;
  color: #A1A1A8;
}

/* ── Video ────────────────────────────────────────────────────────────────── */

.welcome-video {
  position: relative;
  aspect-ratio: var(--welcome-aspect, 1.7778);
  border-radius: 12px;
  overflow: hidden;
  background: #000;
}

.welcome-video iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* ── Progress ─────────────────────────────────────────────────────────────── */

.welcome-progress {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 16px 0 16px;
}

.welcome-bar {
  position: relative;
  height: 6px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.1);
}

.welcome-bar-fill {
  height: 100%;
  border-radius: inherit;
  background: #8B6DFF;
  box-shadow: 0 0 10px rgba(139, 109, 255, 0.5);
  transition: width 300ms linear;
}

/* Where the unlock is, so "80%" has somewhere to point. */
.welcome-bar-mark {
  position: absolute;
  top: -3px;
  width: 2px;
  height: 12px;
  margin-left: -1px;
  border-radius: 1px;
  background: rgba(255, 255, 255, 0.55);
}

.welcome-progress-label {
  font-size: 12.5px;
  color: #8A8A92;
  font-variant-numeric: tabular-nums;
}

.welcome-note {
  margin: 16px 0;
  font-size: 13px;
  line-height: 1.5;
  color: #A1A1A8;
}

/* ── Buttons ──────────────────────────────────────────────────────────────── */

.welcome-actions {
  display: flex;
  justify-content: space-between;
  gap: 10px;
}

.welcome-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 16px;
  border-radius: 11px;
  border: 1px solid transparent;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: background 150ms ease, color 150ms ease, border-color 150ms ease, opacity 150ms ease;
}

.welcome-btn.discord {
  background: rgba(88, 101, 242, 0.14);
  border-color: rgba(88, 101, 242, 0.4);
  color: #C9CDFF;
}

.welcome-btn.discord:hover {
  background: #5865F2;
  border-color: #5865F2;
  color: #FFFFFF;
}

.welcome-btn.primary {
  min-width: 210px;
  background: var(--brand);
  color: #FFFFFF;
  font-variant-numeric: tabular-nums;
}

.welcome-btn.primary:hover:not(:disabled) { background: var(--brand-hover) }

.welcome-btn.primary:disabled {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.1);
  color: #7C7C84;
  cursor: not-allowed;
}

.welcome-btn:focus-visible {
  outline: 2px solid #8B6DFF;
  outline-offset: 2px;
}

/* ── Phone ────────────────────────────────────────────────────────────────── */

@media (max-width: 600px) {
  .welcome-root { padding: 12px }
  .welcome-card {
    width: 100%;
    min-width: 0;
    padding: 18px 16px 16px;
  }
  .welcome-title { font-size: 21px }
  .welcome-text { font-size: 13.5px }
  /* Stacked, with the way in on top - it is the one they are waiting for. */
  .welcome-actions { flex-direction: column-reverse }
  .welcome-btn { width: 100% }
}

@media (prefers-reduced-motion: reduce) {
  .welcome-frost,
  .welcome-card,
  .welcome-bar-fill,
  .welcome-status {
    animation: none !important;
    transition: none !important;
  }
}
/* The upgrade popup. Always dark, in both app themes: it is the one screen that is meant to
   feel like a premium product, and the violet glow only reads on black. Motion is
   decoration and stops for anyone who asked the system for less of it. */

.up-overlay {
  position: fixed;
  inset: 0;
  z-index: 3000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(5, 5, 10, 0.72);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  animation: up-fade 0.22s ease both;
}

.up-modal {
  --up-violet: #8B5CF6;
  --up-fuchsia: #D946EF;
  --up-blue: #6366F1;
  position: relative;
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  width: min(940px, 100%);
  max-height: calc(100vh - 48px);
  overflow: hidden;
  border-radius: 24px;
  background: #0B0B12;
  color: #F5F5F7;
  font-family: var(--font-ui);
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.08),
    0 30px 90px rgba(76, 29, 149, 0.45),
    0 12px 40px rgba(0, 0, 0, 0.6);
  animation: up-rise 0.38s cubic-bezier(0.16, 1, 0.3, 1) both;
}

.up-close {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 3;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border: none;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.06);
  color: rgba(255, 255, 255, 0.7);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.up-close:hover { background: rgba(255, 255, 255, 0.12); color: #FFFFFF; }

/* --- Left: why --------------------------------------------------------------------- */
.up-hero {
  position: relative;
  overflow: hidden;
  padding: 40px 36px 36px;
  background:
    radial-gradient(120% 80% at 0% 0%, rgba(139, 92, 246, 0.45) 0%, rgba(139, 92, 246, 0) 55%),
    radial-gradient(90% 70% at 100% 100%, rgba(217, 70, 239, 0.32) 0%, rgba(217, 70, 239, 0) 60%),
    linear-gradient(160deg, #1A1033 0%, #120B24 55%, #0B0B12 100%);
}
.up-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.045) 1px, transparent 1px);
  background-size: 28px 28px;
  mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.9), transparent 85%);
  -webkit-mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.9), transparent 85%);
  pointer-events: none;
}
.up-hero-glow {
  position: absolute;
  width: 320px;
  height: 320px;
  right: -90px;
  top: -110px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(167, 139, 250, 0.55), rgba(167, 139, 250, 0) 65%);
  filter: blur(10px);
  animation: up-breathe 6s ease-in-out infinite;
  pointer-events: none;
}
.up-hero-candles {
  position: absolute;
  right: 18px;
  bottom: 18px;
  width: 210px;
  opacity: 0.22;
  pointer-events: none;
}
.up-hero-candles line { stroke-width: 1.6; }
.up-hero-candles .up rect { fill: #34D399; }
.up-hero-candles .up line { stroke: #34D399; }
.up-hero-candles .down rect { fill: #F87171; }
.up-hero-candles .down line { stroke: #F87171; }

.up-hero > *:not(.up-hero-glow):not(.up-hero-candles) { position: relative; z-index: 1; }

.up-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px 5px 9px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: #E9D5FF;
}

.up-title {
  margin: 18px 0 10px;
  font-size: 30px;
  line-height: 1.12;
  font-weight: 750;
  letter-spacing: -0.02em;
  background: linear-gradient(180deg, #FFFFFF 30%, #D8C9FF 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.up-sub {
  margin: 0 0 26px;
  max-width: 400px;
  font-size: 14.5px;
  line-height: 1.6;
  color: rgba(237, 233, 254, 0.78);
}

.up-wins {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.up-win {
  display: flex;
  align-items: flex-start;
  gap: 13px;
  animation: up-rise 0.5s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.up-win:nth-child(1) { animation-delay: 0.08s; }
.up-win:nth-child(2) { animation-delay: 0.14s; }
.up-win:nth-child(3) { animation-delay: 0.2s; }
.up-win:nth-child(4) { animation-delay: 0.26s; }
.up-win-icon {
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border-radius: 11px;
  color: #FFFFFF;
  background: linear-gradient(135deg, var(--up-violet), var(--up-fuchsia));
  box-shadow: 0 6px 18px rgba(168, 85, 247, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.25);
}
.up-win-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-top: 1px;
}
.up-win-text strong {
  font-size: 15px;
  font-weight: 650;
  color: #FFFFFF;
}
.up-win-text span {
  font-size: 13px;
  line-height: 1.45;
  color: rgba(237, 233, 254, 0.68);
}

/* --- Right: which, and go ------------------------------------------------------------ */
.up-side {
  display: flex;
  flex-direction: column;
  padding: 40px 32px 28px;
  overflow-y: auto;
  background: #0E0E16;
}
.up-side-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}
.up-side-top .up-side-head { margin-bottom: 0; }
.up-billing {
  display: inline-flex;
  padding: 3px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}
.up-billing button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border: none;
  border-radius: 999px;
  background: transparent;
  color: rgba(255, 255, 255, 0.6);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.up-billing button.on {
  background: rgba(255, 255, 255, 0.12);
  color: #FFFFFF;
}
.up-save {
  padding: 2px 6px;
  border-radius: 999px;
  background: linear-gradient(135deg, #10B981, #34D399);
  color: #052E16;
  font-size: 10.5px;
  font-weight: 800;
}
.up-side-head {
  margin-bottom: 14px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}

.up-plans {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.up-plan {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  padding: 15px 16px;
  border: none;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.035);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.09);
  color: inherit;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease;
}
.up-plan:hover {
  background: rgba(255, 255, 255, 0.06);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.16);
}
.up-plan.chosen {
  background:
    linear-gradient(#14121F, #14121F) padding-box,
    linear-gradient(135deg, var(--up-violet), var(--up-fuchsia)) border-box;
  border: 1.5px solid transparent;
  padding: 13.5px 14.5px;
  box-shadow: 0 10px 30px rgba(139, 92, 246, 0.22);
}
.up-plan-top {
  display: flex;
  align-items: center;
  gap: 8px;
}
.up-plan-name {
  font-size: 16px;
  font-weight: 700;
  color: #FFFFFF;
}
.up-plan-badge {
  padding: 3px 8px;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--up-violet), var(--up-fuchsia));
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: #FFFFFF;
}
.up-plan-price {
  margin-left: auto;
  font-size: 18px;
  font-weight: 750;
  letter-spacing: -0.01em;
  color: #FFFFFF;
}
.up-plan-price small {
  margin-left: 1px;
  font-size: 12px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.55);
}
.up-plan-billed {
  margin-top: -6px;
  font-size: 11.5px;
  color: rgba(255, 255, 255, 0.5);
}
.up-plan-billed s {
  margin-left: 6px;
  color: rgba(255, 255, 255, 0.35);
}
.up-daily {
  margin-top: 10px;
  text-align: center;
  font-size: 12.5px;
  color: rgba(255, 255, 255, 0.62);
}
.up-daily strong {
  color: #FFFFFF;
  font-weight: 650;
}
.up-plan-lines {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px 12px;
}
.up-plan-lines span {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.72);
}
.up-plan-lines svg {
  flex: 0 0 auto;
  color: #A78BFA;
}
.up-plan.chosen .up-plan-lines svg { color: #E879F9; }

.up-cta {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  margin-top: 18px;
  padding: 16px 20px;
  border: none;
  border-radius: 14px;
  background: linear-gradient(135deg, #7C3AED 0%, #A855F7 50%, #D946EF 100%);
  color: #FFFFFF;
  font-family: inherit;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.01em;
  text-decoration: none;
  cursor: pointer;
  box-shadow: 0 12px 34px rgba(168, 85, 247, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.3);
  transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
}
/* A sweep of light across the button now and then - the one thing on screen that moves on
   its own, so the eye lands on it. */
.up-cta::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: -60%;
  width: 45%;
  background: linear-gradient(100deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.35) 50%, rgba(255, 255, 255, 0) 100%);
  transform: skewX(-18deg);
  animation: up-shine 3.2s ease-in-out infinite;
}
.up-cta:hover:not(:disabled) {
  transform: translateY(-1px);
  filter: brightness(1.08);
  box-shadow: 0 16px 42px rgba(168, 85, 247, 0.62), inset 0 1px 0 rgba(255, 255, 255, 0.3);
}
.up-cta:active:not(:disabled) { transform: translateY(0); }
.up-cta:disabled {
  cursor: default;
  background: rgba(255, 255, 255, 0.08);
  color: rgba(255, 255, 255, 0.45);
  box-shadow: none;
}
.up-cta:disabled::after { display: none; }
.up-cta > * { position: relative; z-index: 1; }

.up-trust {
  display: flex;
  justify-content: center;
  gap: 14px;
  margin-top: 12px;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.5);
}
.up-trust span { display: inline-flex; align-items: center; gap: 5px; }
.up-trust span + span::before {
  content: '';
  width: 3px;
  height: 3px;
  margin-right: 9px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.3);
}

.up-connect {
  margin-top: auto;
  padding-top: 20px;
  font-size: 12.5px;
  text-align: center;
  color: rgba(255, 255, 255, 0.55);
}
.up-connect a {
  color: #C4B5FD;
  font-weight: 600;
  text-decoration: none;
}
.up-connect a:hover { text-decoration: underline; }

/* --- After the checkout opened ------------------------------------------------------- */
.up-after {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex: 1;
  text-align: center;
  padding: 10px 6px;
}
.up-after-mark {
  width: 52px;
  height: 52px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  color: #FFFFFF;
  background: linear-gradient(135deg, var(--up-violet), var(--up-fuchsia));
  box-shadow: 0 10px 30px rgba(168, 85, 247, 0.5);
}
.up-after-mark svg { width: 24px; height: 24px; }
.up-after-title {
  margin-top: 18px;
  font-size: 20px;
  font-weight: 700;
}
.up-after-text {
  margin: 10px 0 4px;
  max-width: 320px;
  font-size: 13.5px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.65);
}
.up-note {
  margin-top: 12px;
  font-size: 12.5px;
  line-height: 1.5;
  color: #FCD34D;
}
.up-back {
  margin-top: 16px;
  border: none;
  background: none;
  font-family: inherit;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.55);
  cursor: pointer;
}
.up-back:hover { color: #FFFFFF; }

/* --- Phone ------------------------------------------------------------------------------ */
@media (max-width: 760px) {
  .up-overlay { padding: 0; align-items: flex-end; }
  .up-modal {
    grid-template-columns: 1fr;
    width: 100%;
    max-height: 94vh;
    overflow-y: auto;
    border-radius: 22px 22px 0 0;
    animation-name: up-sheet;
  }
  .up-hero { padding: 30px 22px 24px; }
  .up-hero-candles { width: 150px; opacity: 0.16; }
  .up-title { font-size: 24px; margin-top: 14px; }
  .up-sub { font-size: 14px; margin-bottom: 20px; }
  .up-wins { gap: 12px; }
  .up-side { padding: 22px 18px 26px; overflow: visible; }
  .up-plan-lines { grid-template-columns: 1fr; }
  /* The button stays in reach while the plans scroll past - the sheet is taller than a
     phone, and a button below the fold is a button nobody presses. */
  .up-cta {
    position: sticky;
    bottom: 14px;
    z-index: 2;
  }
}

@keyframes up-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes up-rise { from { opacity: 0; transform: translateY(14px) scale(0.985); } to { opacity: 1; transform: none; } }
@keyframes up-sheet { from { transform: translateY(40px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes up-breathe { 0%, 100% { opacity: 0.75; transform: scale(1); } 50% { opacity: 1; transform: scale(1.08); } }
@keyframes up-shine { 0%, 55% { left: -60%; } 85%, 100% { left: 130%; } }

@media (prefers-reduced-motion: reduce) {
  .up-overlay, .up-modal, .up-win { animation: none; }
  .up-hero-glow, .up-cta::after { animation: none; }
}

/* The one-line answer after Connect Whop, at the top of the app for a few seconds. */
.app-notice {
  position: fixed;
  top: 54px;
  left: 50%;
  z-index: 3100;
  transform: translateX(-50%);
  max-width: calc(100vw - 32px);
  padding: 11px 16px;
  border-radius: 12px;
  font-family: var(--font-ui);
  font-size: 13.5px;
  font-weight: 600;
  color: #FFFFFF;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
  cursor: pointer;
  animation: up-rise 0.3s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.app-notice.ok { background: linear-gradient(135deg, #7C3AED, #D946EF); }
.app-notice.bad { background: #B42318; }
.consent {
  position: fixed;
  left: 16px;
  bottom: 16px;
  z-index: 2900;
  width: min(360px, calc(100vw - 32px));
  padding: 14px 16px;
  border-radius: 14px;
  background: #1C1D21;
  color: #F5F5F7;
  font-family: var(--font-ui);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08), 0 14px 40px rgba(0, 0, 0, 0.45);
  animation: consent-in 0.3s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.consent-text {
  margin: 0 0 12px;
  font-size: 12.5px;
  line-height: 1.5;
  color: rgba(245, 245, 247, 0.82);
}
.consent-buttons {
  display: flex;
  gap: 8px;
}
/* Same size, side by side - Decline is as easy to reach as Accept. */
.consent-btn {
  flex: 1;
  padding: 9px 12px;
  border: none;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.1);
  color: #FFFFFF;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.consent-btn:hover { background: rgba(255, 255, 255, 0.16); }
.consent-btn-accept { background: #FFFFFF; color: #0B0B0B; }
.consent-btn-accept:hover { background: #E5E5EA; }
.consent-text strong { color: #FFFFFF; font-weight: 650; }

@media (max-width: 768px) {
  /* Above the phone's bottom bar. */
  .consent { bottom: calc(76px + env(safe-area-inset-bottom, 0px)); left: 12px; }
}

@keyframes consent-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .consent { animation: none; } }
/* The first-run guide (Guide.jsx): the welcome and finish screens, the spotlight, and the
   card beside it. Everything is scoped under .gd-root. The chart's theme lives on the chart
   container, so the guide reads it and sets .dark on itself - the same way the tour does. */

.gd-root {
  --gd-bg: #FFFFFF;
  --gd-text: #0B0B0B;
  --gd-text-2: #4A4A50;
  --gd-text-3: #8E8E93;
  --gd-line: rgba(0, 0, 0, 0.08);
  --gd-fill: rgba(0, 0, 0, 0.04);
  --gd-fill-hover: rgba(0, 0, 0, 0.07);
  /* Chartify's purple (index.css --brand), the same as the Swift Algo walkthrough
     (TourGuide.css), never the system blue. */
  --gd-accent: var(--brand, #4C29E9);
  --gd-accent-hover: var(--brand-hover, #3D20DC);
  --gd-accent-line: var(--brand, #4C29E9);
  --gd-accent-line-rgb: var(--brand-rgb, 76, 41, 233);
  --gd-good: #1E9E5F;
  --gd-shadow: 0 20px 50px rgba(0, 0, 0, 0.20), 0 2px 8px rgba(0, 0, 0, 0.06);
  font-family: var(--font-ui);
  color: var(--gd-text);
}
.gd-root.dark {
  --gd-bg: #151619;
  --gd-text: #F7F7F7;
  --gd-text-2: #C2C2C8;
  --gd-text-3: #7C7C82;
  --gd-line: rgba(255, 255, 255, 0.09);
  --gd-fill: rgba(255, 255, 255, 0.05);
  --gd-fill-hover: rgba(255, 255, 255, 0.09);
  --gd-shadow: 0 20px 50px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(255, 255, 255, 0.07);
  /* The brand purple is too dark to read against black as a thin line: the ring and the
     marks on the card use the lighter one the walkthrough uses in dark mode. */
  --gd-accent-line: #8B6DFF;
  --gd-accent-line-rgb: 139, 109, 255;
}
.gd-root *, .gd-root *::before, .gd-root *::after { box-sizing: border-box; }
.gd-root button { font-family: inherit; }
.gd-root.leaving .gd-modal, .gd-root.leaving .gd-card, .gd-root.leaving .gd-dim, .gd-root.leaving .gd-ring { animation: gd-out 200ms ease both; }

@keyframes gd-fade { from { opacity: 0 } to { opacity: 1 } }
@keyframes gd-rise { from { opacity: 0; transform: translateY(10px) } to { opacity: 1; transform: none } }
@keyframes gd-out { to { opacity: 0 } }
@keyframes gd-pop { from { transform: scale(.4); opacity: 0 } to { transform: none; opacity: 1 } }

/* ── Buttons and text ──────────────────────────────────────────────────────────────────── */
.gd-primary, .gd-secondary {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; width: 100%;
  min-height: 40px; padding: 0 14px; border: none; border-radius: 11px; cursor: pointer;
  font-size: 14px; font-weight: 600; transition: background .15s ease, opacity .15s ease;
}
.gd-primary { background: var(--gd-accent); color: #FFFFFF; }
.gd-primary:hover:not(:disabled) { background: var(--gd-accent-hover); }
.gd-primary.big { min-height: 48px; font-size: 15.5px; border-radius: 13px; }
.gd-secondary { background: var(--gd-fill); color: var(--gd-text); box-shadow: inset 0 0 0 1px var(--gd-line); }
.gd-secondary:hover:not(:disabled) { background: var(--gd-fill-hover); }
.gd-primary:disabled, .gd-secondary:disabled { opacity: .5; cursor: default; }
.gd-link { border: none; background: transparent; padding: 6px 4px; cursor: pointer; color: var(--gd-text-3); font-size: 12.5px; font-weight: 500; }
.gd-link:hover { color: var(--gd-text-2); }
.gd-link.center { display: block; margin: 8px auto 0; }
.gd-lead { margin: 6px 0 0; color: var(--gd-text-2); font-size: 14.5px; line-height: 1.5; }
.gd-text { margin: 0; color: var(--gd-text-2); font-size: 13.5px; line-height: 1.45; }
.gd-muted { margin: 0; color: var(--gd-text-3); font-size: 12.5px; line-height: 1.45; }
.gd-error { margin: 0; color: #D93A44; font-size: 12.5px; }

/* ── Welcome and finish: a card over the frosted chart ────────────────────────────────── */
.gd-modal { position: fixed; inset: 0; z-index: 1000000; display: grid; place-items: center; padding: 16px; }
.gd-frost {
  position: absolute; inset: 0; background: rgba(8, 8, 10, 0.45);
  /* The app turns glass off everywhere on purpose; this one blur says "your chart is here". */
  backdrop-filter: blur(6px) !important; -webkit-backdrop-filter: blur(6px) !important;
  animation: gd-fade 240ms ease both;
}
.gd-frost.light { background: rgba(8, 8, 10, 0.30); }
.gd-modal-card {
  position: relative; width: min(470px, 100%); max-height: calc(100vh - 32px); overflow-y: auto;
  padding: 26px 24px 18px; border-radius: 22px; background: var(--gd-bg); box-shadow: var(--gd-shadow);
  animation: gd-rise 280ms cubic-bezier(.2, .8, .2, 1) both;
}
.gd-modal-card.center { text-align: center; }
.gd-modal-card h2 { margin: 0; font-size: 24px; font-weight: 700; letter-spacing: -0.02em; }

.gd-tools { list-style: none; margin: 18px 0 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.gd-tools li { display: flex; align-items: center; gap: 12px; font-size: 14px; color: var(--gd-text-2); line-height: 1.35; }
.gd-tools b { color: var(--gd-text); font-weight: 650; }
.gd-tool-icon {
  display: grid; place-items: center; flex: 0 0 34px; width: 34px; height: 34px; border-radius: 10px;
  background: var(--gd-fill); box-shadow: inset 0 0 0 1px var(--gd-line); font-size: 17px;
}

.gd-chart-box { margin: 20px 0 18px; padding: 14px; border-radius: 14px; background: var(--gd-fill); box-shadow: inset 0 0 0 1px var(--gd-line); }
.gd-chart-line { display: flex; align-items: center; gap: 10px; font-size: 14px; }
.gd-chart-line span { color: var(--gd-text-3); }
.gd-chart-line b { flex: 1; font-weight: 650; }
.gd-label { margin: 0 0 8px; font-size: 12.5px; font-weight: 600; color: var(--gd-text-3); }
.gd-chips + .gd-label { margin-top: 14px; }
.gd-chips { display: flex; flex-wrap: wrap; gap: 7px; }
.gd-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 8px 12px; border: none; border-radius: 999px; cursor: pointer;
  font-size: 13.5px; font-weight: 600; background: var(--gd-bg); color: var(--gd-text); box-shadow: inset 0 0 0 1px var(--gd-line);
}
.gd-chip:hover { box-shadow: inset 0 0 0 1px var(--gd-text-3); }
.gd-chip.on { background: var(--gd-accent); color: #FFFFFF; box-shadow: none; }
.gd-chip-sub { font-weight: 500; opacity: .65; }

.gd-finish-emoji { font-size: 44px; line-height: 1; margin-bottom: 10px; animation: gd-pop 420ms cubic-bezier(.2, 1.6, .4, 1) both; }
.gd-tip { margin: 16px 0 20px; padding: 12px 14px; border-radius: 12px; background: var(--gd-fill); color: var(--gd-text-2); font-size: 13.5px; line-height: 1.45; }

/* ── Spotlight: dimmed panels around the control; the hole lets the click through ─────── */
.gd-dim { position: fixed; z-index: 1000000; background: rgba(0, 0, 0, 0.45); transition: all .18s ease; animation: gd-fade 200ms ease both; }
/* On a near-black chart a light dim is invisible - dark mode needs a lot more of it for the
   lit-up control to stand out. */
.gd-root.dark .gd-dim { background: rgba(0, 0, 0, 0.72); }
.gd-ring {
  position: fixed; z-index: 1000001; border-radius: 10px; pointer-events: none;
  box-shadow: 0 0 0 2px var(--gd-accent-line), 0 0 0 6px rgba(var(--gd-accent-line-rgb), 0.25);
  transition: all .18s ease; animation: gd-pulse 1.6s ease-in-out infinite;
}
@keyframes gd-pulse {
  0%, 100% { box-shadow: 0 0 0 2px var(--gd-accent-line), 0 0 0 6px rgba(var(--gd-accent-line-rgb), 0.25); }
  50% { box-shadow: 0 0 0 2px var(--gd-accent-line), 0 0 0 11px rgba(var(--gd-accent-line-rgb), 0.10); }
}

/* ── The card beside the lit-up control ───────────────────────────────────────────────── */
.gd-card {
  position: fixed; z-index: 1000002; padding: 14px 16px 8px; border-radius: 18px;
  background: var(--gd-bg); box-shadow: var(--gd-shadow);
  display: flex; flex-direction: column; gap: 10px;
  transition: top .2s ease, left .2s ease;
  animation: gd-rise 240ms cubic-bezier(.2, .8, .2, 1) both;
}
.gd-card-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.gd-card-step { font-size: 11.5px; font-weight: 650; letter-spacing: .02em; color: var(--gd-accent-line); text-transform: uppercase; }
.gd-dots { display: flex; gap: 4px; }
.gd-dots span { width: 16px; height: 4px; border-radius: 3px; background: var(--gd-line); transition: background .2s ease, width .2s ease; }
.gd-dots span.done { background: rgba(var(--gd-accent-line-rgb), 0.55); }
.gd-dots span.on { background: var(--gd-accent-line); width: 22px; }
.gd-part-title { font-size: 17px; font-weight: 700; letter-spacing: -0.01em; line-height: 1.25; }
.gd-great { display: flex; align-items: center; gap: 8px; font-size: 17px; font-weight: 700; letter-spacing: -0.01em; line-height: 1.25; }
.gd-check {
  display: inline-grid; place-items: center; flex: 0 0 24px; width: 24px; height: 24px; border-radius: 50%;
  background: var(--gd-good); color: #FFFFFF; font-size: 13px; font-weight: 700;
  animation: gd-pop 360ms cubic-bezier(.2, 1.6, .4, 1) both;
}
.gd-spinner {
  display: inline-block; flex: 0 0 15px; width: 15px; height: 15px; margin-right: 8px; vertical-align: -2px;
  border-radius: 50%; border: 2px solid var(--gd-line); border-top-color: var(--gd-accent-line);
  animation: gd-spin .8s linear infinite;
}
@keyframes gd-spin { to { transform: rotate(360deg) } }
.gd-card-foot { display: flex; justify-content: space-between; margin: 0 -4px; }
.gd-card-foot .gd-link:only-child { margin-left: auto; }

/* Slim: one line over the app's top bar, while a tool's panel fills a phone screen. */
.gd-card.slim {
  flex-direction: row; align-items: center; gap: 8px; min-height: 46px;
  padding: 6px 6px 6px 14px; border-radius: 14px;
}
.gd-card.slim .gd-spinner { margin-right: 0; }
.gd-card.slim .gd-check { flex-basis: 22px; width: 22px; height: 22px; font-size: 12px; }
.gd-slim-title {
  flex: 1; min-width: 0; font-size: 14.5px; font-weight: 700; letter-spacing: -0.01em; line-height: 1.25;
  overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.gd-primary.gd-slim-btn { width: auto; min-height: 34px; padding: 0 14px; border-radius: 10px; font-size: 13.5px; flex: none; }
.gd-slim-close {
  flex: none; width: 30px; height: 30px; border: none; border-radius: 8px; cursor: pointer;
  background: transparent; color: var(--gd-text-3); font-size: 13px;
}
.gd-slim-close:hover { background: var(--gd-fill); color: var(--gd-text-2); }

.gd-levels { display: flex; flex-direction: column; gap: 6px; }
.gd-level {
  display: grid; grid-template-columns: auto auto 1fr auto; align-items: center; gap: 8px; padding: 9px 10px;
  border-radius: 10px; cursor: pointer; background: var(--gd-fill); box-shadow: inset 0 0 0 1px var(--gd-line); font-size: 13px;
}
.gd-level.on { box-shadow: inset 0 0 0 2px var(--gd-accent); }
.gd-level input { width: 15px; height: 15px; margin: 0; accent-color: var(--gd-accent); }
.gd-level b { font-variant-numeric: tabular-nums; }
.gd-level .up { color: var(--gd-good); }
.gd-level .down { color: #D93A44; }

/* ── Phone: sheets from the bottom; the card sits at the top ──────────────────────────── */
@media (max-width: 768px), (max-height: 500px) and (orientation: landscape) {
  .gd-modal { place-items: end center; padding: 0; }
  .gd-modal-card { width: 100%; max-height: 92vh; border-radius: 22px 22px 0 0; padding: 22px 18px calc(16px + env(safe-area-inset-bottom)); }
  .gd-modal-card h2 { font-size: 22px; }
  .gd-chip { font-size: 15px; }
}
