/* base_skin.css — the shared, skin-agnostic component layer (was proposal8.css + ftg.css).
 *
 * This file holds the STRUCTURE of the Flowtech GEO design system: canvas, app shell,
 * sidebar, topbar, page header, buttons, cards, KPI plates, charts, data tables, tags,
 * inputs, modals and the `ug-*` console rows, plus the Tailwind neutral/brand remaps.
 *
 * It references ONLY CSS custom properties — never a literal color — so the actual
 * look is supplied by the active skin's `theme.css` (see frontend/skins/<skin>/).
 * The "soft meadow" day palette lives in `day/theme.css`; a dark one in `night/theme.css`.
 *
 * Loading order (base.html / shell.html): Tailwind first, then this base layer, then
 * the skin theme, so the Tailwind remaps below win over the utility classes and the
 * skin theme's variables resolve for every rule here.
 */

/* ---- ftg token aliases -------------------------------------------------- */
/* The `ftg-*` / `ug-*` layer is themed by the `--m-*` palette for free. */
:root {
  --ftg-accent: var(--m-forest);
  --ftg-accent-hover: var(--m-forest-d);
  --ftg-accent-soft: var(--m-forest-soft);
  --ftg-danger: var(--m-danger);
  --ftg-danger-hover: var(--m-danger-d);
  --ftg-danger-soft: var(--m-danger-soft);
  --ftg-ink: var(--m-ink);
  --ftg-text: var(--m-text);
  --ftg-muted: var(--m-muted);
  --ftg-faint: var(--m-faint);
  --ftg-border: var(--m-border);
  --ftg-soft: var(--m-soft);
  --ftg-input-border: var(--m-border-d);
  --ftg-card: var(--m-card);
  --ftg-radius: var(--r-md);
}

/* ==================================================================
   CANVAS
   ================================================================== */
/* Responsive root size: every rem-based text/measure scales smoothly with
   the viewport, so fonts grow slightly on larger screens (clamped bounds). */
html {
  font-size: clamp(16px, 1vw + 3px, 19px);
}

body {
  font-family: var(--font-sans);
  background: linear-gradient(180deg, var(--m-canvas-top) 0%, var(--m-canvas-bot) 100%);
  background-attachment: fixed;
  color: var(--m-text);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}

/* Subtle paper grain (no halos on corners) */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  background: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.025'/%3E%3C/svg%3E");
  pointer-events: none;
  z-index: 0;
}

/* ==================================================================
   APP SHELL — sidebar + topbar + content
   ================================================================== */
.app-shell {
  display: flex;
  align-items: stretch;
  min-height: 100vh;
  position: relative;
  z-index: 1;
}

.ft-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  /* Anchor for the shared wait modal (.ftg-wait), which covers the whole
     working area below the topbar (see ftg_wait.js). */
  position: relative;
}

.content {
  padding: 28px 32px;
}

/* Standalone auth/onboarding pages (no sidebar, no topbar, centered card).
   Padding is rem so it follows the page root size: on the onboarding steps
   the root is larger (ONBOARDING SCALE below) and the gutters grow too. */
body.auth-standalone .app-shell { align-items: center; justify-content: center; }
body.auth-standalone #ftSidebar, body.auth-standalone .topbar { display: none !important; }
body.auth-standalone .ft-main { width: 100%; align-items: center; }
body.auth-standalone .content { width: 100%; padding: 2rem 1rem; display: flex; justify-content: center; }

/* ==================================================================
   ONBOARDING SCALE
   ------------------------------------------------------------------
   The wizard steps (backend/projects/templates/projects/onboarding/
   step1..8.html) tag the document with .ftg-onboarding through the
   `html_class` block of frontend/shell.html. On those pages only, the
   root font-size is raised and made more responsive than the console
   one at the top of this file: the wizard is a single centered card on
   a big monitor, so it was leaving most of the screen empty and its
   text looked small. Because the whole step layout is built with
   rem-based Tailwind utilities (type scale, paddings, gaps, icon
   boxes) plus the rem `max-w-5xl` card measure, raising the root
   scales every element proportionally to the screen width.

     console (above)  clamp(16px,  1vw + 3px, 19px)
     onboarding       clamp(17px, .62vw + 10px, 26px)
       => 1024px: 17px   1440px: 19px   1920px: 22px   2560px: 26px

   One clamp drives the whole wizard; the floor keeps phones/tablets at
   a sane size and the ceiling keeps 4K/ultrawide readable.
   ================================================================== */
html.ftg-onboarding {
  font-size: clamp(17px, 0.62vw + 10px, 26px);
}

/* The few wizard components that are px-sized (they were measured against
   the 16px console root) are re-expressed in rem here, at the same ratio,
   so they scale together with everything else instead of staying small.
   Only the classes the steps actually use are listed. */
.ftg-onboarding .field-input {
  font-size: 0.875rem;
  padding: 0.625rem 0.875rem;
}
.ftg-onboarding .ftg-nav-btn {
  font-size: 0.875rem;
  padding: 0.5625rem 1.375rem;
  min-width: 8.25rem;
  min-height: 2.75rem;
  border-radius: 0.75rem;
}
.ftg-onboarding .ftg-btn-cancel {
  font-size: 0.875rem;
  padding: 0.5625rem 1.375rem;
  min-width: 8.25rem;
  min-height: 2.75rem;
  border-radius: 0.75rem;
}
.ftg-onboarding .ftg-toad-img { width: 5.75rem; height: 4rem; }
.ftg-onboarding .ftg-toad-bubble { padding: 0.75rem 1rem; }

/* Arbitrary px font sizes used across the steps (text-[9px] .. text-[13px],
   mostly the stepper captions and the inline hints): px-locked, so map them
   to the equivalent rem to keep them in the same rhythm as text-xs/sm. */
.ftg-onboarding .text-\[9px\]  { font-size: 0.5625rem; }
.ftg-onboarding .text-\[10px\] { font-size: 0.625rem; }
.ftg-onboarding .text-\[11px\] { font-size: 0.6875rem; }
.ftg-onboarding .text-\[12px\] { font-size: 0.75rem; }
.ftg-onboarding .text-\[13px\] { font-size: 0.8125rem; }

/* Deliberately NOT scaled: hairlines and decorations that must stay thin
   (step connector w-[2px], the brand heart icon, the ftg-favicon max box). */

/* ==================================================================
   SIDEBAR
   ================================================================== */
#ftSidebar,
.sidebar {
  width: 260px;
  flex: 0 0 260px;
  min-height: 100vh;
  background: linear-gradient(180deg, var(--m-card) 0%, var(--m-sidebar-bot) 100%);
  border-right: 1px solid var(--m-border);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  z-index: 10;
  overflow-y: auto;
  flex-shrink: 0;
}

.sidebar-inner {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.sidebar-brand {
  padding: 24px 20px;
  border-bottom: 1px solid var(--m-border);
  display: flex;
  align-items: center;
  gap: 12px;
}

.sidebar-brand-icon {
  width: 36px;
  height: 36px;
  border-radius: var(--r-sm);
  background: linear-gradient(135deg, var(--m-emerald), var(--m-aqua));
  color: var(--m-on-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 16px;
  box-shadow: 2px 2px 0 var(--m-ink);
}

.sidebar-brand-text {
  font-weight: 700;
  font-size: 15px;
  color: var(--m-ink);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.sidebar-brand-text span {
  background: linear-gradient(135deg, var(--m-forest), var(--m-lime));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.sidebar-brand-img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 57px;
  object-fit: contain;
  border-radius: var(--r-sm);
}

.sidebar-brand-name {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-align: left;
  white-space: nowrap;
  line-height: 1;
  padding-left: 10px;
  color: var(--m-forest);
}

.sidebar-brand-name span {
  color: var(--m-lime);
}

.sidebar-nav {
  flex: 1;
  padding: 16px 12px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* Brand tagline at the bottom of the sidebar, above the footer divider:
   small but visible, matching the shared ftg-brand-tagline phrasing. Margin
   top keeps it clear of the logout button above it. */
.sidebar-tagline {
  font-size: 11px;
  line-height: 1.4;
  color: var(--m-muted);
  text-align: center;
  padding: 6px 12px;
  margin-top: 10px;
}

/* Section labels with colored marker dots */
.sidebar-section {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--m-faint);
  padding: 16px 12px 6px;
}

.sidebar-section .dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: 0 0 auto;
}

.sidebar-section.dot-aqua .dot     { background: var(--m-aqua); }
.sidebar-section.dot-lavender .dot { background: var(--m-lavender); }
.sidebar-section.dot-amber .dot    { background: var(--m-amber); }
.sidebar-section.dot-rose .dot     { background: var(--m-rose); }
.sidebar-section.dot-sky .dot      { background: var(--m-sky); }

.sidebar-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  border-radius: var(--r-md);
  font-size: 14px;
  font-weight: 500;
  color: var(--m-muted);
  text-decoration: none;
  transition: all 0.15s ease;
  cursor: pointer;
  position: relative;
}

.sidebar-item i { color: var(--m-faint); width: 20px; text-align: center; font-size: 15px; transition: color 0.15s ease; }

.sidebar-item:hover { color: var(--m-ink); background: var(--m-hover); text-decoration: none; }
.sidebar-item:hover i { color: var(--m-forest); }

.sidebar-item.active {
  background: var(--m-ink);
  color: var(--m-on-ink);
  font-weight: 600;
  border: none;
}

.sidebar-item.active i { color: var(--m-sage); }

.sidebar-item.active::before {
  content: '';
  position: absolute;
  left: 6px;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 16px;
  border-radius: 3px;
  background: linear-gradient(180deg, var(--m-forest), var(--m-lime), var(--m-amber));
}

/* Project switcher card inside the sidebar */
.sidebar-card {
  margin: 0 12px 8px;
  border: var(--border-w) var(--border-style) var(--m-border-d);
  border-radius: var(--r-md);
  background: var(--m-card);
  padding: 10px 12px;
  box-shadow: 2px 2px 0 var(--m-border-d);
}

.sidebar-card-label {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--m-faint);
}

.sidebar-card-value {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
  font-size: 13px;
  font-weight: 600;
  color: var(--m-ink);
  min-width: 0;
}

/* Project switcher dropdown (replaces the old sideways card link) */
.sidebar-project {
  position: relative;
  margin: 0 12px 8px;
  z-index: 20;
}

.sidebar-project-btn {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  border: var(--border-w) var(--border-style) var(--m-border-d);
  border-radius: var(--r-md);
  background: var(--m-card);
  padding: 10px 12px;
  box-shadow: 2px 2px 0 var(--m-border-d);
  cursor: pointer;
  text-align: left;
  font-family: var(--font-sans);
  color: var(--m-ink);
  transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.sidebar-project-btn:hover {
  box-shadow: 3px 3px 0 var(--m-border-d);
  transform: translate(-1px, -1px);
}

.sidebar-project-main {
  flex: 1;
  min-width: 0;
}

.sidebar-project-caret {
  color: var(--m-faint);
  font-size: 11px;
  transition: transform 0.15s ease;
}

.sidebar-project.open .sidebar-project-caret {
  transform: rotate(180deg);
}

.sidebar-project-menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 50;
  display: none;
  padding: 4px;
  background: var(--m-card);
  border: var(--border-w) var(--border-style) var(--m-ink);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-x) var(--shadow-y) 0 var(--m-shadow);
}

.sidebar-project.open .sidebar-project-menu {
  display: block;
}

.sidebar-project-option {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 10px;
  border: none;
  border-radius: var(--r-sm);
  background: transparent;
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 500;
  color: var(--m-text);
  text-align: left;
  cursor: pointer;
  min-width: 0;
}

.sidebar-project-option:hover {
  background: var(--m-hover);
  color: var(--m-ink);
}

.sidebar-project-option .opt-icon {
  flex: 0 0 auto;
  width: 14px;
  text-align: center;
  font-size: 12px;
  color: var(--m-faint);
}

.sidebar-project-option .opt-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar-project-option .opt-check {
  flex: 0 0 auto;
  font-size: 11px;
  color: var(--m-amber);
  visibility: hidden;
}

.sidebar-project-option.active {
  color: var(--m-amber-fg);
  font-weight: 600;
}

.sidebar-project-option.active .opt-check {
  visibility: visible;
}

.sidebar-project-option.is-empty {
  color: var(--m-faint);
  cursor: default;
}

.sidebar-project-footer {
  margin-top: 4px;
  padding-top: 4px;
  border-top: var(--border-w) var(--border-style) var(--m-border);
}

/* Scroll wrapper inside the menu: the scrollbar lives here, inset from the
   menu border by its 4px padding, so the track (and any arrow buttons) stay
   fully inside the rounded card. Slim thumb, transparent track, native arrow
   buttons hidden (Firefox gets the same via scrollbar-width: thin). */
.sidebar-project-scroll {
  max-height: 55vh;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--m-border) transparent;
}

.sidebar-project-scroll::-webkit-scrollbar {
  width: 8px;
}

.sidebar-project-scroll::-webkit-scrollbar-track {
  background: transparent;
}

.sidebar-project-scroll::-webkit-scrollbar-thumb {
  background: var(--m-border);
  border-radius: 4px;
}

.sidebar-project-scroll::-webkit-scrollbar-button {
  display: none;
}

/* Filter + sort bar of the project switcher: sticky inside the scroll wrapper
   so it stays visible while the option list scrolls. The wrapper carries no
   padding, so the bar spans its full width and pins flush to the top (no row
   ever peeks above it). */
.sidebar-project-filter {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0 0 4px;
  padding: 8px 8px 6px;
  background: var(--m-card);
}

.sidebar-project-filter-icon {
  flex: 0 0 auto;
  font-size: 11px;
  color: var(--m-faint);
}

.sidebar-project-filter-input {
  flex: 1;
  min-width: 0;
  padding: 4px 6px;
  border: var(--border-w) var(--border-style) var(--m-border);
  border-radius: var(--r-sm);
  background: var(--m-soft);
  color: var(--m-text);
  font-family: var(--font-sans);
  font-size: 12px;
}

.sidebar-project-filter-input:focus {
  outline: none;
  border-color: var(--m-amber);
}

.sidebar-project-filter-clear {
  flex: 0 0 auto;
  padding: 2px;
  border: none;
  background: transparent;
  color: var(--m-faint);
  font-size: 11px;
  cursor: pointer;
}

.sidebar-project-filter-clear:hover {
  color: var(--m-text);
}

/* Two small icon buttons (radio-style: exactly one active). */
.sidebar-project-sort {
  flex: 0 0 auto;
  display: inline-flex;
  gap: 2px;
}

.sidebar-project-sortbtn {
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: var(--border-w) var(--border-style) var(--m-border);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--m-faint);
  font-size: 10px;
  cursor: pointer;
}

.sidebar-project-sortbtn:hover {
  color: var(--m-text);
}

.sidebar-project-sortbtn.active {
  color: var(--m-amber-fg);
  border-color: var(--m-amber);
  background: var(--m-hover);
}

/* Letter-avatar badge: favicon-less project fallback in the switcher (colored
   badge + initial; the text color is flipped inline in api.js by the badge
   luminance). The border keeps light badges readable on the light card. */
.ftg-proj-avatar {
  width: 14px;
  height: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  border-radius: 4px;
  border: var(--border-w) var(--border-style) var(--m-border);
  font-size: 8px;
  font-weight: 700;
  line-height: 1;
}

.ftg-proj-avatar-lg {
  width: 16px;
  height: 16px;
  font-size: 9px;
}

.sidebar-project-placeholder {
  font-weight: 500;
  color: var(--m-faint);
}

.sidebar-footer {
  padding: 16px 12px;
  border-top: 1px solid var(--m-border);
}

.sidebar-user {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: var(--r-md);
  cursor: pointer;
}

.sidebar-user:hover { background: var(--m-hover); }

/* Wrench button in the sidebar user card (self credentials modal). Same
   footprint as the decorative dots it replaced; only rendered when the
   session profile holds the Profiles write bit. */
.sidebar-user-gear {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 4px 6px;
  border: none;
  background: none;
  cursor: pointer;
  color: var(--m-faint);
  font-size: 12px;
  border-radius: 6px;
}
.sidebar-user-gear:hover { color: var(--m-ink); }
.sidebar-user-gear:focus-visible { outline: 2px solid var(--m-aqua); outline-offset: 2px; }

/* Show/hide-password toggle (eye / eye-slash) inside password inputs. Global
   so both the auth pages and the shared credentials modal can use it (plain
   CSS so no Tailwind rebuild is needed). */
.pwd-wrap { position: relative; }
.pwd-wrap .field-input,
.pwd-wrap .ftg-input { padding-right: 44px; }
.pwd-toggle {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  display: inline-flex; padding: 4px; border: none; background: none;
  cursor: pointer; color: var(--m-faint); border-radius: 6px;
}
.pwd-toggle:hover { color: var(--m-ink); }

.sidebar-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--m-lime), var(--m-aqua));
  color: var(--m-on-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 13px;
  flex: 0 0 auto;
}

.sidebar-user-info { flex: 1; min-width: 0; }

.sidebar-user-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--m-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sidebar-user-role {
  font-size: 11px;
  color: var(--m-faint);
  display: inline-flex;
  align-items: center;
  gap: 4px;
  width: fit-content;
  cursor: help;
}

/* Tooltip on the sidebar badges (contract / active project). The sidebar is a
   sticky, overflow-scrolling container, so the tooltip is fixed-positioned
   above the badge and centered on it. */
.ft-tip { position: relative; }

.ft-tip::after {
  content: attr(data-tip);
  position: fixed;
  left: var(--tip-x, 50%);
  top: var(--tip-y, 0px);
  transform: translate(-50%, -100%);
  max-width: 220px;
  padding: 6px 10px;
  border: var(--border-w) var(--border-style) var(--m-ink);
  border-radius: var(--r-sm);
  background: var(--m-ink);
  color: var(--m-on-ink);
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 500;
  line-height: 1.35;
  text-align: center;
  white-space: normal;
  opacity: 0;
  visibility: hidden;
  transition: opacity .12s ease;
  pointer-events: none;
  z-index: 100001;
}

.ft-tip:hover::after,
.ft-tip:focus-visible::after {
  opacity: 1;
  visibility: visible;
}

/* Flipped variant applied by placeTip() (api.js) when the anchor sits too
   close to the viewport top: the bubble opens below the anchor instead of
   above it, so it never crosses the top edge. */
.ft-tip.ft-tip-below::after {
  transform: translate(-50%, 0);
}

/* ==================================================================
   TOPBAR
   ================================================================== */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 32px;
  border-bottom: 1px solid var(--m-border);
  background: var(--m-topbar-bg);
  backdrop-filter: blur(16px);
  position: sticky;
  top: 0;
  /* The topbar must stay above any scrolling page content (widget overlays,
     lock CTAs, chart tooltips, etc.), so its z-index sits above every
     content-level value (up to 1000) while remaining below the shared
     overlay layer (modals / toasts / run-progress dock, 90000+). */
  z-index: 5000;
}

.topbar-title {
  font-size: 19px;
  font-weight: 700;
  color: var(--m-ink);
  letter-spacing: -0.01em;
}

/* Mobile navigation toggle (hamburger): hidden on desktop, shown in the
   topbar below 768px where the sidebar collapses into an off-canvas drawer. */
.ftg-nav-toggle {
  display: none;
  appearance: none;
  -webkit-appearance: none;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  flex: 0 0 auto;
  background: var(--m-card);
  color: var(--m-ink);
  border: var(--border-w) var(--border-style) var(--m-ink);
  border-radius: var(--r-lg);
  font-size: 16px;
  cursor: pointer;
  box-shadow: 2px 2px 0 var(--m-ink);
  transition: box-shadow 0.15s ease, transform 0.15s ease;
}
.ftg-nav-toggle i { font-size: 16px; }
.ftg-nav-toggle:hover { box-shadow: 2px 2px 0 var(--m-ink); transform: translate(-1px, -1px); }
.ftg-nav-toggle:focus-visible { outline: none; box-shadow: 2px 2px 0 var(--m-emerald); }

.topbar-actions {
  display: flex;
  align-items: center;
  gap: 14px;
}

.topbar-logo {
  display: block;
  width: auto;
  height: auto;
  max-height: 52px;
  max-width: 60px;
  object-fit: contain;
  border-radius: var(--r-sm);
  margin-left: 14px;
}

/* ==================================================================
   PAGE HEADER — gradient "rule" accent
   ================================================================== */
.page-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 28px;
}

.page-header h1 {
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.15;
  color: var(--m-ink);
  margin: 0;
}

.page-header h1 .rule {
  display: inline-block;
  width: 34px;
  height: 5px;
  background: linear-gradient(90deg, var(--m-forest), var(--m-lime), var(--m-amber));
  margin-right: 10px;
  vertical-align: middle;
  border-radius: 3px;
}

.page-header p {
  font-size: 13px;
  color: var(--m-muted);
  margin: 4px 0 0;
}

/* Data-count chip next to a console page title (filled by the console JS
   once the list data arrives; starts hidden). Soft forest pill matching the
   page-header rule accent. The .hidden guard keeps Tailwind's utility
   effective (this layer loads after tailwind, same trap as .tag.hidden). */
.page-header .page-count {
  display: inline-flex;
  align-items: center;
  margin-left: 10px;
  padding: 2px 10px;
  border-radius: 9999px;
  background: var(--m-forest-soft);
  color: var(--m-forest);
  border: 1.5px solid var(--m-forest);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0;
  line-height: 1.4;
  vertical-align: middle;
  white-space: nowrap;
}
.page-header .page-count.hidden { display: none; }

/* ==================================================================
   BUTTONS — press effect
   ================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 9px 18px;
  border-radius: var(--r-md);
  font-size: 13px;
  font-weight: 600;
  font-family: var(--font-sans);
  border: none;
  cursor: pointer;
  transition: all 0.15s ease;
  text-decoration: none;
  white-space: nowrap;
  line-height: 1.2;
}

.btn-sm {
  padding: 5px 12px;
  font-size: 12px;
  border-radius: 10px;
}

.btn-primary {
  background: linear-gradient(135deg, var(--m-emerald), var(--m-forest));
  color: var(--m-on-accent);
  box-shadow: 3px 3px 0 var(--m-ink);
}

.btn-primary:hover {
  background: linear-gradient(135deg, var(--m-forest), var(--m-forest-d));
  color: var(--m-on-accent);
  box-shadow: 1px 1px 0 var(--m-ink);
  transform: translate(2px, 2px);
  text-decoration: none;
}

.btn-secondary {
  background: var(--m-card);
  color: var(--m-ink);
  border: var(--border-w) var(--border-style) var(--m-ink);
  box-shadow: 3px 3px 0 var(--m-border-d);
}

.btn-secondary:hover {
  color: var(--m-ink);
  box-shadow: 1px 1px 0 var(--m-border-d);
  transform: translate(2px, 2px);
  text-decoration: none;
}

.btn-ghost {
  background: transparent;
  color: var(--m-muted);
  padding: 8px 12px;
}

.btn-ghost:hover { color: var(--m-forest); background: var(--m-hover); text-decoration: none; }

.btn[disabled], .btn.disabled { opacity: .55; cursor: not-allowed; }

/* ==================================================================
   CARDS — ink outline + hard offset shadow
   ================================================================== */
.card {
  background: var(--m-card);
  border: var(--border-w) var(--border-style) var(--m-ink);
  border-radius: var(--r-lg);
  position: relative;
  box-shadow: var(--shadow-x) var(--shadow-y) 0 var(--m-shadow);
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 20px;
  border-bottom: 1px dashed var(--m-border-d);
}

.card-title {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--m-ink);
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
}

.card-title .ic-aqua     { color: var(--m-aqua); }
.card-title .ic-amber    { color: var(--m-amber); }
.card-title .ic-coral    { color: var(--m-coral); }
.card-title .ic-lavender { color: var(--m-lavender); }
.card-title .ic-forest   { color: var(--m-forest); }

.card-title i { font-size: 12px; }

.card-body { padding: 20px; }

.card-body.no-pad { padding: 0; }

.card-empty {
  text-align: center;
  padding: 28px 20px;
  color: var(--m-muted);
  font-size: 13px;
}

/* ==================================================================
   KPI CARDS — value plates
   ================================================================== */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
  margin-bottom: 30px;
}

.kpi {
  background: var(--m-card);
  border: var(--border-w) var(--border-style) var(--m-ink);
  border-radius: var(--r-lg);
  padding: 20px 20px 18px;
  position: relative;
  box-shadow: var(--shadow-x) var(--shadow-y) 0 var(--m-border-d);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.kpi:hover {
  transform: translate(-2px, -2px);
  box-shadow: 6px 6px 0 var(--m-border);
}

.kpi-plate {
  font-family: var(--font-mono);
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -0.02em;
  padding: 10px 14px;
  margin: 10px 0 14px;
  display: inline-block;
  line-height: 1;
  border-radius: var(--r-sm);
}

.kpi-plate.emerald  { background: var(--m-forest); color: var(--m-on-accent); }
.kpi-plate.aqua     { background: var(--m-aqua-soft); color: var(--m-aqua-fg); }
.kpi-plate.amber    { background: var(--m-amber-soft); color: var(--m-amber-fg); }
.kpi-plate.coral    { background: var(--m-coral-soft); color: var(--m-coral-fg); }
.kpi-plate.lavender { background: var(--m-lavender-soft); color: var(--m-lavender-fg); }
.kpi-plate.ink      { background: var(--m-ink); color: var(--m-on-ink); }

.kpi-label {
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--m-faint);
  font-family: var(--font-mono);
  margin-bottom: 2px;
}

.kpi-change {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  font-weight: 600;
  font-family: var(--font-mono);
  padding: 2px 9px;
  border: 1px dashed currentColor;
  border-radius: var(--r-sm);
}

.kpi-change.up { color: var(--m-success); }
.kpi-change.down { color: var(--m-danger); }

/* ==================================================================
   CHARTS
   ================================================================== */
.charts-grid {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 18px;
  margin-bottom: 24px;
}

.chart-container { position: relative; height: 280px; }

/* Chart.js sizes the canvas on its own resize pass; the guard keeps the
   initial 300px-default canvas from ever widening the layout (e.g. a chart
   card on a phone), even for the moment before the responsive resize lands. */
.chart-container canvas { max-width: 100%; }

/* ==================================================================
   DATA TABLE
   ================================================================== */
.data-table { width: 100%; border-collapse: separate; border-spacing: 0; }

.data-table th {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--m-faint);
  text-align: left;
  padding: 12px 16px;
  border-bottom: var(--border-w) var(--border-style) var(--m-ink);
}

.data-table td {
  font-size: 13px;
  padding: 11px 16px;
  border-bottom: 1px dashed var(--m-border);
  color: var(--m-text);
}

.data-table tbody tr:hover td { background: var(--m-row-hover); }

.data-table .mono {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
}

/* Rank plates cycle the palette */
.rank-plate {
  display: inline-block;
  min-width: 26px;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  padding: 3px 6px;
  border-radius: var(--r-sm);
}

.rank-plate.r1 { background: linear-gradient(135deg, var(--m-emerald), var(--m-forest)); color: var(--m-on-accent); }
.rank-plate.r2 { background: var(--m-aqua-soft); color: var(--m-aqua-fg); }
.rank-plate.r3 { background: var(--m-amber-soft); color: var(--m-amber-fg); }
.rank-plate.r4 { background: var(--m-coral-soft); color: var(--m-coral-fg); }
.rank-plate.r5 { background: var(--m-lavender-soft); color: var(--m-lavender-fg); }

.brand-row td {
  background: var(--m-brand-row);
}

.data-table tbody tr.brand-row:hover td {
  background: var(--m-row-brand-hover, var(--m-brand-row));
}

/* ==================================================================
   TAGS & BADGES — rounded rubber-stamps
   ================================================================== */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 10px;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  border: var(--border-w) dashed currentColor;
  background: transparent;
  font-family: var(--font-mono);
  border-radius: 20px;
  white-space: nowrap;
}
/* Keep Tailwind's .hidden effective on .tag (this layer loads after tailwind). */
.tag.hidden { display: none; }

.tag-forest   { color: var(--m-forest); }
.tag-aqua     { color: var(--m-aqua-fg); }
.tag-amber    { color: var(--m-amber-fg); }
.tag-coral    { color: var(--m-coral-fg); }
.tag-lavender { color: var(--m-lavender-fg); }

/* ==================================================================
   Cited-brands review popup (shared FtgBrandReview gadget)
   ================================================================== */
.brv-modal .brv-lead { font-size: 13px; line-height: 1.55; color: var(--m-text); margin-bottom: 14px; }
.brv-modal .brv-meta { display: flex; align-items: center; gap: 10px; margin: 0 0 10px; }
.brv-chip {
  display: inline-flex; align-items: center; gap: 6px; background: var(--m-forest-soft);
  color: var(--m-forest); border: 1px solid var(--m-forest); font-size: 11px; font-weight: 700;
  padding: 2px 10px; border-radius: 999px;
}
.brv-ignore-rest {
  margin-left: auto; background: none; border: none; color: var(--m-muted); font-size: 12px;
  text-decoration: underline; cursor: pointer; padding: 2px 4px;
}
.brv-ignore-rest:hover { color: var(--m-forest); }
.brv-ignore-rest:disabled { opacity: .5; cursor: default; }
.brv-list { max-height: 264px; overflow: auto; border: var(--border-w) var(--border-style) var(--m-border); border-radius: 12px; }
.brv-row { display: flex; align-items: center; gap: 12px; padding: 9px 12px; cursor: pointer; }
.brv-row + .brv-row { border-top: var(--border-w) var(--border-style) var(--m-border); }
.brv-check { width: 16px; height: 16px; accent-color: var(--m-forest); cursor: pointer; }
.brv-fav {
  width: 30px; height: 30px; border-radius: 8px; flex: 0 0 auto; display: flex;
  align-items: center; justify-content: center; overflow: hidden; background: var(--m-soft);
  border: 1px solid var(--m-border); color: var(--m-forest); font-weight: 800; font-size: 13px;
}
.brv-fav img { width: 100%; height: 100%; object-fit: contain; }
.brv-name { font-size: 13.5px; font-weight: 600; color: var(--m-ink); }
.brv-count { margin-left: auto; color: var(--m-muted); font-size: 11.5px; background: var(--m-soft); border: 1px solid var(--m-border); padding: 1px 8px; border-radius: 999px; white-space: nowrap; }
.brv-hint { margin: 12px 0 4px; font-size: 11.5px; color: var(--m-muted); }

/* ==================================================================
   INPUTS
   ================================================================== */
.input-group {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--m-card);
  border: var(--border-w) var(--border-style) var(--m-ink);
  border-radius: var(--r-md);
  padding: 0 14px;
  transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.input-group:focus-within {
  box-shadow: 3px 3px 0 var(--m-emerald);
  transform: translate(-1px, -1px);
}

.input-group i { color: var(--m-faint); font-size: 13px; }

.input-group input {
  flex: 1;
  background: transparent;
  border: none;
  outline: none;
  color: var(--m-text);
  font-size: 13px;
  font-family: var(--font-sans);
  padding: 10px 0;
  box-shadow: none;
}

.input-group input::placeholder { color: var(--m-faint); }

/* Plain form fields (login / account / onboarding). */
.field-input {
  width: 100%;
  background: var(--m-card);
  border: var(--border-w) var(--border-style) var(--m-ink);
  border-radius: var(--r-md);
  padding: 10px 14px;
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--m-text);
  transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.field-input:focus {
  outline: none;
  box-shadow: 3px 3px 0 var(--m-emerald);
  transform: translate(-1px, -1px);
}

.field-input::placeholder { color: var(--m-faint); }

.field-input.has-error { border-color: var(--m-danger); }

/* Language / skin switch pill (topbar). The chevron is a data-URI so its stroke
   color is fixed here; a dark skin overrides the background-image in its theme. */
.lang-select {
  appearance: none;
  -webkit-appearance: none;
  background: var(--m-card) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%233a5440' stroke-width='1.5'/%3E%3C/svg%3E") no-repeat right 10px center;
  border: var(--border-w) var(--border-style) var(--m-ink);
  border-radius: var(--r-md);
  color: var(--m-ink);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  padding: 7px 28px 7px 12px;
  cursor: pointer;
  transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.lang-select:hover { box-shadow: 2px 2px 0 var(--m-border-d); transform: translate(-1px, -1px); }
.lang-select:focus { outline: none; box-shadow: 2px 2px 0 var(--m-emerald); }

/* Topbar dropdown switcher (language / skin — see ftg_switcher.js).
   Closed: trigger shows the active option's icon only; open: a menu of
   icon + label rows. The chevron is a data-URI (fixed stroke color);
   a dark skin overrides the background-image in its theme. */
.ftg-switcher { position: relative; display: inline-flex; }

.ftg-switcher-btn {
  appearance: none;
  -webkit-appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--m-card) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%233a5440' stroke-width='1.5'/%3E%3C/svg%3E") no-repeat right 10px center;
  border: var(--border-w) var(--border-style) var(--m-ink);
  border-radius: var(--r-lg);
  padding: 12px 38px 12px 14px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  box-shadow: 2px 2px 0 var(--m-ink);
  transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.ftg-switcher-btn:hover { box-shadow: 2px 2px 0 var(--m-ink); transform: translate(-1px, -1px); }
.ftg-switcher-btn:focus-visible { outline: none; box-shadow: 2px 2px 0 var(--m-emerald); }

/* Topbar switcher triggers (kickstart rocket, language flag) are uniform
   with the Dashboard badge pills (.ftg-unlock-badge / .ftg-report-btn):
   same 13px content + 9px vertical padding -> same height and proportions.
   The 34px right padding keeps the data-URI chevron gutter (chevron sits at
   right: 10px). The flag keeps its 26:18 ratio at the shrunk size. */
.topbar-actions .ftg-switcher-btn { padding: 9px 34px 9px 14px; }
.topbar-actions .ftg-switcher-btn .ftg-switcher-icon { width: 13px; height: 13px; }
.topbar-actions .ftg-switcher-btn .ftg-switcher-flag { width: 19px; height: 13px; }

.ftg-switcher-flag {
  width: 26px; height: 18px;
  object-fit: cover;
  border-radius: 2px;
  border: 1px solid var(--m-border);
  display: block;
}

.ftg-switcher-icon { width: 18px; height: 18px; display: block; color: var(--m-ink); }

.ftg-switcher-list {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 1000;
  min-width: 200px;
  /* Never wider than the viewport (minus margins) on mobile. */
  max-width: calc(100vw - 16px);
  max-height: min(60vh, 320px);
  overflow-y: auto;
  overscroll-behavior: contain;
  /* Horizontal viewport containment applied by ftg_switcher.js via FtgFit:
     the menu is right-anchored, so a trigger near the left edge would push
     it off-screen; the shift pulls it back inside the viewport. */
  transform: translateX(var(--ftg-sw-shift, 0px));
  background: var(--m-card);
  border: var(--border-w) var(--border-style) var(--m-ink);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-x) var(--shadow-y) 0 var(--m-shadow);
  padding: 4px;
}

/* Opens upward when the menu does not fit below the trigger (short screens);
   ftg_switcher.js also caps max-height to the free space above. */
.ftg-switcher.open-up .ftg-switcher-list {
  top: auto;
  bottom: calc(100% + 6px);
}

.ftg-switcher.open .ftg-switcher-list { display: block; }

.ftg-switcher-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 9px 12px;
  border: 0;
  background: transparent;
  border-radius: var(--r-sm);
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--m-ink);
  text-align: left;
  cursor: pointer;
}

.ftg-switcher-item:hover,
.ftg-switcher-item:focus { background: var(--m-hover); outline: none; }

.ftg-switcher-item[aria-current="true"] { background: var(--m-amber-soft); }

/* Kickstart / first-adoption dropdown (topbar): the same pill + menu as the
   language/skin switchers, but its menu is an informational checklist instead
   of submit items. The red dot on the trigger marks pending tasks
   (`data-done="0"`). See frontend/kickstart_switch.html + ftg_switcher.js. */
.ftg-kickstart-btn { position: relative; }
.ftg-kickstart-list { min-width: 250px; }
.ftg-kickstart-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--m-ink);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 9px 12px 7px;
}
.ftg-kickstart-items { display: flex; flex-direction: column; gap: 2px; }
.ftg-kickstart-item {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 7px 12px;
  font-size: 13px;
  line-height: 1.35;
  color: var(--m-muted);
}
.ftg-kickstart-item i { margin-top: 2px; }
.ftg-kickstart-ok { color: #16a34a; }
.ftg-kickstart-todo { color: #eab308; }
.ftg-switcher-dot {
  position: absolute;
  top: -4px;
  right: -4px;
  display: block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--m-danger);
  border: 2px solid var(--m-card);
}
.ftg-switcher-dot.hidden { display: none; }

.field-label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--m-ink);
  margin-bottom: 6px;
}

/* ==================================================================
   SENTIMENT & TREND
   ================================================================== */
.sentiment-dot {
  width: 11px; height: 11px;
  border-radius: 50%;
  display: inline-block;
  border: 2px solid var(--m-card);
  box-shadow: 0 0 0 1.5px currentColor;
}

.sentiment-dot.positive { background: var(--m-success); color: var(--m-success); }
.sentiment-dot.neutral  { background: var(--m-warning); color: var(--m-warning); }
.sentiment-dot.negative { background: var(--m-danger);  color: var(--m-danger); }

.trend-up   { color: var(--m-success); }
.trend-down { color: var(--m-danger); }
.trend-flat { color: var(--m-faint); }

.mono { font-family: var(--font-mono); }

.divider {
  height: var(--border-w);
  background: repeating-linear-gradient(90deg, var(--m-ink) 0 6px, transparent 6px 12px);
  margin: 24px 0;
  border: none;
}

/* ==================================================================
   TAILWIND NEUTRAL RECOLOR — keep the grey scale on the theme tint
   (classes are redefined here because several components are rendered
   dynamically in JS with Tailwind utilities).
   ================================================================== */
.text-gray-900 { color: var(--m-ink) !important; }
.text-gray-800 { color: var(--m-ink) !important; }
.text-gray-700 { color: var(--m-text) !important; }
.text-gray-600, .text-gray-500 { color: var(--m-muted) !important; }
.text-gray-400, .text-gray-300 { color: var(--m-faint) !important; }

.border-gray-100, .border-gray-200 { border-color: var(--m-border) !important; }
.divide-gray-100, .divide-gray-200 { border-color: var(--m-border) !important; }

/* brand-* sky scale → theme green family */
.text-brand-500, .text-brand-600, .text-brand-400, .hover\:text-brand-600:hover { color: var(--m-emerald) !important; }
.text-brand-300 { color: var(--m-lime) !important; }
.text-brand-700 { color: var(--m-forest-d) !important; }
.text-brand-800 { color: var(--m-ink) !important; }
.text-brand-200 { color: var(--m-sage) !important; }
.bg-brand-50 { background: var(--m-brand-tint-08) !important; }
.bg-brand-100 { background: var(--m-brand-tint-12) !important; }
.bg-brand-400 { background: var(--m-brand-tint-85) !important; }
.bg-brand-500 { background: var(--m-forest) !important; }
.bg-brand-600 { background: var(--m-forest-d) !important; }
.hover\:bg-brand-400:hover { background: var(--m-brand-tint-85) !important; }
.hover\:bg-brand-500:hover { background: var(--m-forest) !important; }
.hover\:bg-brand-600:hover { background: var(--m-forest-d) !important; }
.peer:checked ~ .peer-checked\:bg-brand-400 { background: var(--m-brand-tint-85) !important; }
.peer:checked ~ .peer-checked\:bg-brand-500 { background: var(--m-forest) !important; }
.peer:checked ~ .peer-checked\:bg-brand-600 { background: var(--m-forest-d) !important; }
.border-brand-100 { border-color: var(--m-brand-tint-25) !important; }
.border-brand-400, .border-brand-500 { border-color: var(--m-brand-tint-55) !important; }
.focus\:ring-brand-300:focus, .focus\:ring-brand-400:focus, .focus\:ring-brand-500:focus { --tw-ring-color: var(--m-brand-tint-45) !important; }

/* Soft grey fills → faint forest tint */
.bg-gray-50 { background: var(--m-brand-tint-05) !important; }
.bg-gray-100 { background: var(--m-brand-tint-08) !important; }

/* LLM selector rows (onboarding step3) */
.llm-row { background: var(--m-canvas-top); border: 2px solid var(--m-border-d); border-radius: 16px; }
.llm-row:hover { border-color: var(--m-ink); }

/* ==================================================================
   ONBOARDING STEPPER SIDEBAR — the wizard's dark-green panel
   (the sidebar `<aside>` gets the `ftg-stepper` class; tokens come
   from the per-skin `--m-stepper-*` variables in day/ & night/theme.css).
   All Neutral/Brand utility colors used *inside* the aside are remapped
   so the light text keeps an AA-comfortable contrast on the deep green.
   ================================================================== */
.ftg-stepper {
  background: var(--m-stepper-bg);
  color: var(--m-stepper-fg);
  border-right: 1px solid var(--m-border);
}

.ftg-stepper h3 { color: var(--m-stepper-fg) !important; }

.ftg-stepper :is(.text-gray-400, .text-gray-300, .text-gray-500, .text-gray-600) {
  color: var(--m-stepper-muted) !important;
}

.ftg-stepper .bg-gray-200 { background: var(--m-stepper-track) !important; }
.ftg-stepper .border-gray-200 { border-color: var(--m-stepper-ring) !important; }
.ftg-stepper .border-brand-400,
.ftg-stepper .border-brand-500 { border-color: var(--m-stepper-fg) !important; }
.ftg-stepper .bg-brand-400 { background: var(--m-emerald) !important; }
/* Completed-step circles: light mint fill (pops on the deep panel) with a
   dark checkmark — beats Tailwind's emerald-500/text-white for contrast. */
.ftg-stepper .bg-emerald-500 {
  background: var(--m-stepper-done) !important;
  color: var(--m-stepper-done-ink) !important;
}
.ftg-stepper .bg-emerald-400 { background: var(--m-stepper-done) !important; }

/* Icon-only affordance for the wizard bottom buttons (Cancel / Back / Next /
   Finish): hidden by default, shown below 768px by the narrow-device media
   query further down. The text label does the opposite. */
.ftg-onboarding .ftg-nav-icon { display: none; }
.ftg-onboarding .ftg-nav-label { display: inline; }
.ftg-onboarding-foot { display: none; }
.ftg-onboarding-foot .ftg-brand-tagline { font-size: 0.6875rem; color: var(--m-muted); }

/* Narrow-only wizard bubble addition: the numeric "1/5" step counter that
   renders under the toad mascot (left of the speech bubble) is hidden on
   desktop, where the worded step counter in the header keeps its place. */
.ftg-onboarding .ftg-step-count { display: none; }

/* ==================================================================
   ONBOARDING NARROW LAYOUT — phones (below the md breakpoint, <768px)
   ------------------------------------------------------------------
   Only the narrow case is restyled here; the desktop wizard keeps its
   two-column card untouched. On a phone the dark-green stepper sidebar
   becomes a horizontal row of the 5 stage circles with just the step
   names (no descriptions), sitting BELOW the main step window (the card
   stacks and the stepper is re-ordered after the main content), the
   "ToadLLM · made with…" tagline leaves the box and moves onto the page
   background under the card, and the bottom Cancel / Back / Next /
   Finish buttons collapse to icon-only square controls.
   ================================================================== */
@media (max-width: 767.98px) {
  /* Stepper strip below the step content: in the stacked column the <main>
     keeps the top spot and the stepper <aside> moves after it, so the
     horizontal stage bar sits right under the step window (any extra card
     height stays below the strip, not between them). */
  html.ftg-onboarding .card { flex-direction: column; }
  html.ftg-onboarding .card > main { order: 1; }
  html.ftg-onboarding .card > aside { order: 2; }

  /* The wizard tagline now lives on the canvas background, under the card:
     the standalone content wrapper stacks the card and the footer tagline.
     Scoped to the wizard (html.ftg-onboarding) so the login/account pages
     keep their existing mobile layout untouched. */
  html.ftg-onboarding body.auth-standalone .content { flex-direction: column; align-items: center; }

  /* Stepper sidebar -> compact horizontal stage bar. */
  .ftg-stepper {
    border-right: none;
    border-top: 1px solid var(--m-border);
    justify-content: center;
    padding: 0.75rem 0.5rem 0.85rem;
  }
  /* Intro line ("Complete these steps…") and the sidebar tagline: only the
     horizontal stage bar remains inside the strip. */
  .ftg-stepper > div:first-child > p { display: none; }
  .ftg-stepper > div:last-child { display: none; }

  .ftg-stepper nav {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    justify-content: space-between;
    gap: 2px;
  }
  .ftg-stepper nav > div {
    flex: 1 1 0;
    min-width: 0;
    flex-direction: column;
    align-items: center;
    padding-bottom: 0;
  }
  .ftg-stepper nav > div > div.absolute { display: none; }   /* vertical connector */
  .ftg-stepper nav > div > div.relative { margin-right: 0; } /* stage circle */
  .ftg-stepper nav > div > div:last-child { text-align: center; }
  .ftg-stepper nav p { display: none; }                      /* step descriptions */
  .ftg-stepper nav h3 {
    font-size: 0.625rem;
    font-weight: 600;
    line-height: 1.25;
    margin-top: 0.25rem;
  }

  /* Tagline moved to the page background, below the card. */
  .ftg-onboarding-foot {
    display: flex;
    justify-content: center;
    margin-top: 1.25rem;
  }

  /* Bottom action buttons -> icon-only squares. */
  .ftg-onboarding .ftg-nav-btn,
  .ftg-onboarding .ftg-btn-cancel {
    width: 2.75rem;
    min-width: 2.75rem;
    height: 2.75rem;
    padding: 0;
  }
  .ftg-onboarding .ftg-btn-cancel {
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .ftg-onboarding .ftg-nav-label { display: none; }
  .ftg-onboarding .ftg-nav-icon { display: inline-block; font-size: 1rem; }

/* (End of the first ONBOARDING NARROW LAYOUT media query — the step
     header and toad rules moved to the dedicated query below.) */
}
@media (max-width: 767.98px) {
  /* Step header on narrow: only the title stays on top. The worded step
     counter (.ftg-step-num) is hidden; the bare "1/5" renders under the
     toad mascot, to the left of the speech bubble, in a smaller font. */
  html.ftg-onboarding .card > main > div:first-child > div:first-child .ftg-step-num {
    display: none;
  }

  /* Toad + bubble side by side again: image left, speech bubble right.
     The image keeps its enlarged size; the step number sits under it; the
     bubble is shadowless and its comic tail points at the image. */
  html.ftg-onboarding .card .ftg-toad {
    gap: 8px;
    align-items: center;
  }
  html.ftg-onboarding .card .ftg-toad-img {
    width: 2.5rem;
    height: 1.75rem;
  }
  html.ftg-onboarding .card .ftg-toad-fig .ftg-toad-img {
    width: 3rem;
    height: 2rem;
  }
  html.ftg-onboarding .card .ftg-toad-fig {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.375rem;
    flex: 0 0 auto;
  }
  html.ftg-onboarding .card .ftg-step-count {
    display: block;
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.2;
    color: var(--m-muted);
    white-space: nowrap;
  }
  html.ftg-onboarding .card .ftg-toad-bubble {
    flex: 1 1 auto;
    box-shadow: none;
  }
  /* On the standard wizard steps (image + step number in the fig) the
     mascot top-aligns with the bubble so its middle sits at the tail. */
  html.ftg-onboarding .card:has(.ftg-toad-fig) .ftg-toad {
    align-items: flex-start;
  }
  html.ftg-onboarding .card:has(.ftg-toad-fig) .ftg-toad-bubble::before {
    top: calc(1rem - 7px);
  }
}
/* ==================================================================
   TOAD ASSISTANT BUBBLE — the wizard mascot explains each step
   (image: a brand/toad*.webp variant + a comic speech-bubble with a left tail).
   ================================================================== */
.ftg-toad {
  display: flex;
  align-items: center;
  gap: 14px;
}

/* flat image, no circle/border/shadow. The box is wider than tall so the
   full artwork is visible (contain) instead of being cropped at the sides.
   Every toad variant shares this fixed box, so switching image (toadllm /
   toad_smile / toad_big_smile) never changes the rendered size. */
.ftg-toad-img {
  width: 92px;
  height: 64px;
  object-fit: contain;
  flex: 0 0 auto;
}

.ftg-toad-bubble {
  position: relative;
  flex: 1;
  background: var(--m-toad-bubble);
  border: var(--border-w) var(--border-style) var(--m-toad-border);
  border-radius: var(--r-lg);
  padding: 12px 16px;
  color: var(--m-toad-ink);
  font-size: 0.9rem;
  line-height: 1.6;
  box-shadow: 3px 3px 0 var(--m-toad-border);
}

.ftg-toad-bubble::before {
  content: '';
  position: absolute;
  left: -9px;
  top: 22px;
  width: 14px;
  height: 14px;
  background: var(--m-toad-bubble);
  border-left: var(--border-w) var(--border-style) var(--m-toad-border);
  border-bottom: var(--border-w) var(--border-style) var(--m-toad-border);
  transform: rotate(45deg);
}

/* ==================================================================
   UNIFIED NOTIFICATION LAYER (ftg_alert.js) — one toast stack + one
   blocking alert modal, same UX on every page. The kind is carried by
   the accent tokens (--m-danger / --m-warning / --m-success /
   --m-emerald) so both skins render correctly (plain CSS).
   ================================================================== */

/* ---- TOAST: compact, transient, top-center stack ---------------------- */
/* Top-center because the bottom-right is occupied by the run-progress
   dock; one predictable place for all transient feedback. */
.ftg-alert-stack {
  position: fixed;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 100001;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: min(480px, calc(100vw - 32px));
  pointer-events: none;
}
.ftg-alert {
  pointer-events: auto;
  opacity: 0;
  transform: translateY(-10px);
  transition: opacity .25s ease, transform .25s ease;
  border-left: 4px solid var(--m-toad-border);
  border-radius: var(--r-lg);
}
.ftg-alert.is-visible { opacity: 1; transform: translateY(0); }
.ftg-alert .ftg-toad { gap: 10px; }                      /* compact horizontal row */
.ftg-alert .ftg-toad-img { width: 48px; height: 40px; }  /* SMALL toad, artwork ratio */
.ftg-alert .ftg-toad-bubble {
  box-shadow: 3px 3px 0 var(--m-toad-border);
  font-size: 0.85rem;
  padding: 10px 14px;
}
/* Tail anchored to the SMALL toad's mouth: the base 22px is tuned for the
   64px full-size toad. The row centers toad and bubble on the same axis and
   the mouth sits ~5px above the artwork center, so the 14px diamond is
   placed with its center on the mouth line. */
.ftg-alert .ftg-toad-bubble::before { top: calc(50% - 9px); }
/* Kind accents (toast). */
.ftg-alert--danger  { border-left-color: var(--m-danger); }
.ftg-alert--danger  .ftg-toad-bubble { border-color: var(--m-danger); box-shadow: 3px 3px 0 var(--m-danger); }
.ftg-alert--warning { border-left-color: var(--m-warning); }
.ftg-alert--warning .ftg-toad-bubble { border-color: var(--m-warning); box-shadow: 3px 3px 0 var(--m-warning); }
.ftg-alert--success { border-left-color: var(--m-success); }
.ftg-alert--success .ftg-toad-bubble { border-color: var(--m-success); box-shadow: 3px 3px 0 var(--m-success); }
.ftg-alert--emerald { border-left-color: var(--m-emerald); }
.ftg-alert--emerald .ftg-toad-bubble { border-color: var(--m-emerald); box-shadow: 3px 3px 0 var(--m-emerald); }

/* ---- ALERT MODAL: large, blocking, centered, accent header band ------- */
/* Vertical layout: big toad ABOVE the bubble — unmistakably not a toast. */
.ftg-alert-modal .ftg-toad--stack {
  flex-direction: column;
  align-items: center;
  gap: 12px;
  text-align: center;
}
.ftg-alert-modal .ftg-toad--stack .ftg-toad-img { width: 92px; height: 64px; }  /* LARGE toad */
.ftg-alert-modal .ftg-toad--stack .ftg-toad-bubble { flex: 0 1 auto; }
.ftg-alert-modal .ftg-toad--stack .ftg-toad-bubble::before { display: none; }    /* no side tail */
/* Accent header band on the modal header (FtgModal renders .ftg-modal-header). */
.ftg-alert-modal .ftg-modal-header { border-bottom: 3px solid var(--m-danger); }
.ftg-alert-modal .ftg-modal-header > i { color: var(--m-danger); }
.ftg-alert-modal--warning .ftg-modal-header { border-bottom-color: var(--m-warning); }
.ftg-alert-modal--warning .ftg-modal-header > i { color: var(--m-warning); }
.ftg-alert-modal--success .ftg-modal-header { border-bottom-color: var(--m-success); }
.ftg-alert-modal--success .ftg-modal-header > i { color: var(--m-success); }
.ftg-alert-modal--emerald .ftg-modal-header { border-bottom-color: var(--m-emerald); }
.ftg-alert-modal--emerald .ftg-modal-header > i { color: var(--m-emerald); }

/* ---- UPGRADE CTA: any element that opens the shared PRO modal ----------- */
/* Applied to plan notes, locked model cards, the prompts plan banner, the
   Dashboard "Free version" / "Unlock Pro" badges, the leaderboard and models
   lock CTAs and the reduced widget banners (see frontend/static/js/
   ftg_upgrade.js). Plain pointer + focus ring: no hover override so the
   badges' own hover shadows keep working. */
.ftg-upgrade-cta { cursor: pointer; }
.ftg-upgrade-cta:focus-visible { outline: 2px solid var(--m-emerald); outline-offset: 2px; }

/* Heart icon inside the footer tagline: brand green by default; inside the
   dark stepper sidebar it flips to the light mint so it still pops. */
.ftg-brand-heart {
  display: inline-block;
  width: 12px;
  height: 12px;
  margin: 0 2px;
  vertical-align: -1px;
  color: var(--m-emerald);
}
.ftg-stepper .ftg-brand-heart { color: var(--m-stepper-done) !important; }

/* ==================================================================
   QUICKSTART TOUR — the post-onboarding toad guide on the Dashboard
   (a fixed popup with the mascot next to a speech bubble + a pointer
   aimed at the targeted widget; dim overlay + glow ring focus the
   stepped-through component). Driven by token variables so both skins
   keep the same look.
   ================================================================== */
.qs-ovl {
  position: fixed;
  inset: 0;
  background: var(--m-overlay);
  z-index: 100001;
}

/* Spotlight mode: the fixed dim is lifted and the glow's huge box-shadow
   darkens everything AROUND the target instead, so the highlighted widget
   keeps its normal colors and contrasts with the rest of the page. */
.qs-ovl.qs-ovl-spot {
  background: transparent;
}

.qs-glow {
  position: fixed;
  z-index: 100002;
  pointer-events: none;
  border: 3px solid var(--m-emerald);
  border-radius: var(--r-md);
  box-shadow: 0 0 0 6px rgba(21, 153, 115, 0.15), 0 0 0 9999px var(--m-overlay);
  transition: top .2s ease, left .2s ease, width .2s ease, height .2s ease;
}

.qs-pop {
  position: fixed;
  z-index: 100002;
  width: min(480px, calc(100vw - 48px));
  background: var(--m-card);
  border: 3px solid var(--m-emerald);
  border-radius: var(--r-lg);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.35), 5px 5px 0 var(--m-shadow);
  padding: 22px 26px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* Wider bubbles for specific steps: ~1.5x (leaderboard) and ~2x (timeline +
   closing). Same height — only the width grows, capped by the viewport. */
.qs-pop-1_5x { width: min(630px, calc(100vw - 48px)); }
.qs-pop-2x   { width: min(840px, calc(100vw - 48px)); }

.qs-head {
  display: flex;
  align-items: center;
  gap: 14px;
}

/* Reuses the same fixed image box as the wizard toad so every variant sizes
   identically inside the popup. */
.qs-img {
  width: 92px;
  height: 64px;
  object-fit: contain;
  flex: 0 0 auto;
}

.qs-bubble {
  position: relative;
  flex: 1;
  background: var(--m-toad-bubble);
  border: var(--border-w) var(--border-style) var(--m-toad-border);
  border-radius: var(--r-lg);
  padding: 12px 16px;
  color: var(--m-toad-ink);
  font-size: 0.9rem;
  line-height: 1.6;
  box-shadow: 3px 3px 0 var(--m-toad-border);
}

/* Comic speech-bubble tail pointing at the toad beside it, mirroring the
   wizard bubble (.ftg-toad-bubble::before) but vertically centred so it always
   touches the mascot's middle for any bubble height. */
.qs-bubble::before {
  content: '';
  position: absolute;
  left: -9px;
  top: 50%;
  margin-top: -7px;
  width: 14px;
  height: 14px;
  background: var(--m-toad-bubble);
  border-left: var(--border-w) var(--border-style) var(--m-toad-border);
  border-bottom: var(--border-w) var(--border-style) var(--m-toad-border);
  transform: rotate(45deg);
}

/* Pointer aimed at the targeted widget: a rotated square on the popup edge
   facing the target, matching the thick emerald border of the card. */
.qs-pop::before {
  content: '';
  position: absolute;
  width: 16px;
  height: 16px;
  background: var(--m-card);
}
.qs-pop.qs-arrow-left::before {
  left: -11px;
  top: 50%;
  margin-top: -8px;
  transform: rotate(45deg);
  border-left: 3px solid var(--m-emerald);
  border-bottom: 3px solid var(--m-emerald);
}
.qs-pop.qs-arrow-right::before {
  right: -11px;
  top: 50%;
  margin-top: -8px;
  transform: rotate(45deg);
  border-right: 3px solid var(--m-emerald);
  border-top: 3px solid var(--m-emerald);
}
.qs-pop.qs-arrow-top::before {
  top: -11px;
  left: 50%;
  margin-left: -8px;
  transform: rotate(45deg);
  border-top: 3px solid var(--m-emerald);
  border-left: 3px solid var(--m-emerald);
}
.qs-pop.qs-arrow-bottom::before {
  bottom: -11px;
  left: 50%;
  margin-left: -8px;
  transform: rotate(45deg);
  border-bottom: 3px solid var(--m-emerald);
  border-right: 3px solid var(--m-emerald);
}

.qs-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.qs-count {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--m-muted);
}

/* ==================================================================
   RESPONSIVE
   ================================================================== */
@media (max-width: 1024px) {
  .kpi-grid { grid-template-columns: repeat(2, 1fr); }
  .charts-grid { grid-template-columns: 1fr; }
  .content { padding: 22px 20px; }
}

@media (max-width: 768px) {
  #ftSidebar, .sidebar { display: none; }
  /* Topbar: a single row on phones — hamburger, title (shrinks with an
     ellipsis) and the action controls share one line; the switcher pill and
     the logo compact down so the row never forces a horizontal page scroll. */
  .topbar {
    flex-wrap: nowrap;
    gap: 10px;
    padding: 12px 16px;
  }
  .topbar-title {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .topbar-actions {
    flex: 0 0 auto;
    flex-wrap: nowrap;
    justify-content: flex-end;
    gap: 10px;
    margin-left: 0;
  }
  .topbar-actions .ftg-switcher-btn { padding: 8px 26px 8px 12px; }
  .topbar-logo { max-height: 40px; max-width: 48px; margin-left: 4px; }
  .ftg-nav-toggle { display: inline-flex; }
  .content { padding: 20px 16px; }
  .kpi-grid { grid-template-columns: 1fr; }
  .page-header { flex-direction: column; align-items: flex-start; }
}

/* Mobile sidebar drawer: the shared sidebar (hidden above) slides in from the
   left as a fixed overlay when the hamburger toggles `sidebar-open` on it. */
@media (max-width: 768px) {
  .sidebar-open,
  #ftSidebar.sidebar-open {
    display: flex;
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 280px;
    max-width: 85vw;
    min-height: 100vh;
    height: 100vh;
    z-index: 6000;
    border-right: 1px solid var(--m-border);
    box-shadow: 4px 0 24px rgba(0, 0, 0, 0.25);
  }
}

/* Dimmed backdrop behind the open mobile drawer. */
.ftg-nav-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  z-index: 5999;
}
body.ftg-nav-open .ftg-nav-backdrop { display: block; }

/* ==================================================================
   FTG PRIMITIVES — shared cards, FABs, sectioned modals, buttons,
   filter bar, tabs and the `ug-*` console rows (was ftg.css).
   ================================================================== */

/* ---- Cards -------------------------------------------------------------- */
/* A card is a flex row: an optional colored bar + a main column (row + body). */
.ftg-card { display: flex; align-items: stretch; background: var(--ftg-card);
  border: var(--border-w) var(--border-style) var(--ftg-ink); border-radius: 16px;
  box-shadow: 3px 3px 0 var(--m-shadow); }
/* Keep Tailwind's .hidden effective on ftg-card (this layer loads after tailwind). */
.ftg-card.hidden { display: none; }
.ftg-cardbar { width: 4px; flex: 0 0 auto; align-self: stretch; border-radius: 2px;
  background: var(--ftg-accent); }
.ftg-cardmain { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
/* Header row of a card: icon / name / chip on the left, actions on the right. */
.ftg-row { display: flex; align-items: center; gap: 12px; padding: 12px 16px;
  border-bottom: 1px dashed var(--ftg-input-border); }
.ftg-ic { color: var(--ftg-muted); width: 18px; text-align: center; flex: 0 0 auto; }
.ftg-name { font-size: 14px; color: var(--ftg-ink); font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ftg-chip { padding: 4px 10px; border-radius: 8px; border: 1px solid var(--m-border);
  font-size: 13px; color: var(--ftg-ink); white-space: nowrap; }
.ftg-tag { padding: 2px 8px; border-radius: 9999px; font-size: 11px; font-weight: 600; }
.ftg-tag.active { background: var(--ftg-accent-soft); color: var(--ftg-accent); }
.ftg-tag.warn { background: var(--m-amber-soft); color: var(--m-amber-fg); }
.ftg-tag.danger { background: var(--ftg-danger-soft); color: var(--ftg-danger); }
.ftg-tag.ok { color: var(--ftg-accent); }
/* Read-only banner when the session contract is outside its validity
   window (contract lifecycle plan §4). */
.ftg-contract-banner { display: flex; align-items: center; gap: 8px;
  margin: 0 0 14px; padding: 9px 14px; border-radius: 10px;
  font-size: 13px; font-weight: 600; }
.ftg-contract-banner-expired { background: var(--ftg-danger-soft); color: var(--ftg-danger); }
.ftg-contract-banner-pending { background: var(--m-amber-soft); color: var(--m-amber-fg); }
.ftg-tag-linked { display: inline-block; max-width: 220px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; }
/* Collapsible body below the header row. */
.ftg-body { border-top: 1px solid var(--ftg-soft); padding: 14px 16px; }
.ftg-pre { font-family: var(--font-mono); font-size: 12px; color: var(--ftg-muted);
  background: var(--ftg-soft); border: 1px solid var(--ftg-border); border-radius: 8px; padding: 10px; }
.ftg-empty { text-align: center; color: var(--ftg-faint); font-size: 14px; padding: 20px 0; }

/* ---- Row action buttons -------------------------------------------------- */
/* Green square primary action (edit). */
.ftg-edit { width: 38px; height: 38px; border-radius: 10px; display: flex; align-items: center;
  justify-content: center; color: var(--m-on-accent); background: linear-gradient(135deg, var(--ftg-accent), var(--m-forest-d));
  box-shadow: 2px 2px 0 var(--ftg-ink); cursor: pointer; }
.ftg-edit:hover { background: var(--ftg-accent-hover); box-shadow: 1px 1px 0 var(--ftg-ink); }
/* Small ghost action (activate / key). */
.ftg-act { background: none; border: none; font-size: 14px; color: var(--ftg-muted);
  cursor: pointer; padding: 6px 8px; }
.ftg-act:hover { color: var(--ftg-ink); }
.ftg-act.danger { color: var(--ftg-muted); }
.ftg-act.danger:hover { color: var(--ftg-danger); }

/* ---- Floating action buttons (FABs) --------------------------------------- */
.ftg-fab { width: 48px; height: 48px; border-radius: 9999px; display: flex; align-items: center;
  justify-content: center; color: var(--m-on-accent); border: var(--border-w) var(--border-style) var(--ftg-ink);
  box-shadow: 3px 3px 0 var(--m-shadow); cursor: pointer; }
/* Keep Tailwind's .hidden effective on ftg-fab (this layer loads after tailwind). */
.ftg-fab.hidden { display: none; }
.ftg-fab:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--m-shadow); }
.ftg-fab.green { background: linear-gradient(135deg, var(--ftg-accent), var(--m-forest-d)); }
.ftg-fab.green:hover { background: var(--ftg-accent-hover); }
.ftg-fab.red { background: var(--ftg-danger); }
.ftg-fab.red:hover { background: var(--ftg-danger-hover); }
.ftg-fab.gray { background: var(--m-fab-gray); color: var(--ftg-muted); }
.ftg-fab.gray:hover { background: var(--m-fab-gray-hover); }
.ftg-fab.orange { background: var(--m-amber); }
.ftg-fab.orange:hover { background: var(--m-amber-d); }
.ftg-fab i { font-size: 17px; }

/* ---- Console pager bar (shared FtgPager gadget) ---------------------------- */
.ftg-pager { display: flex; align-items: center; justify-content: center; gap: 6px;
  margin: 14px 0 8px; flex-wrap: wrap; }
.ftg-page { min-width: 32px; height: 32px; padding: 0 8px; border-radius: 8px; display: inline-flex;
  align-items: center; justify-content: center; color: var(--m-text); background: var(--m-card);
  border: 1.5px solid var(--m-border); cursor: pointer; font-size: 13px; }
.ftg-page:hover:not(:disabled) { color: var(--m-ink); border-color: var(--m-amber); }
.ftg-page.active { background: var(--m-forest); color: #fff; border-color: var(--m-forest); }
.ftg-page:disabled { opacity: .4; cursor: not-allowed; }
.ftg-page-info { margin-left: 8px; font-size: 12px; color: var(--m-muted); font-family: var(--font-mono); }

/* ---- Sectioned modal (fixed header / fixed footer) ------------------------ */
.ftg-modal-overlay { position: fixed; inset: 0; background: var(--m-overlay);
  display: flex; align-items: center; justify-content: center; padding: 16px; z-index: 100000; }
.ftg-modal { position: relative; display: flex; flex-direction: column;
  background: var(--ftg-card); border: var(--border-w) var(--border-style) var(--ftg-ink);
  border-radius: 16px; box-shadow: 5px 5px 0 var(--m-shadow);
  max-height: 90vh; overflow: hidden; }
.ftg-modal-header { flex: 0 0 auto; display: flex; align-items: center; gap: 8px;
  padding: 16px 52px 12px 24px; border-bottom: 1px solid var(--ftg-border);
  background: var(--ftg-card); }
.ftg-modal-header > i { color: var(--ftg-faint); width: 18px; text-align: center; flex: 0 0 auto; }
.ftg-modal-title { font-size: 15px; font-weight: 600; color: var(--ftg-ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ftg-modal-body { flex: 1 1 auto; min-height: 0; overflow-y: auto;
  overscroll-behavior: contain; padding: 18px 24px; }
.ftg-modal-footer { flex: 0 0 auto; display: flex; flex-wrap: wrap; align-items: center;
  justify-content: flex-end; gap: 10px; padding: 12px 24px 16px;
  border-top: 1px solid var(--ftg-border); background: var(--ftg-card); }
/* Inline modal footer error: small surprised toad + message on one row
   (the FtgAlert.toadHtml markup rendered by ctx.fail). */
.ftg-modal-err { flex: 1 1 100%; font-size: 12px; color: var(--m-danger); }
.ftg-modal-err .ftg-toad { gap: 8px; }
.ftg-modal-err .ftg-toad-img { width: 40px; height: 30px; }
/* Same mouth anchoring as the toast, scaled to the 30px toad. */
.ftg-modal-err .ftg-toad-bubble::before { top: calc(50% - 7px); }
.ftg-modal-err .ftg-toad-bubble {
  font-size: 12px;
  line-height: 1.45;
  padding: 6px 10px;
  border-color: var(--m-danger);
  box-shadow: 2px 2px 0 var(--m-danger);
}
.ftg-modal-err.hidden { display: none; }
.ftg-modal-actions { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }
.ftg-modal-close { position: absolute; top: 10px; right: 10px; z-index: 1; width: 30px; height: 30px;
  border-radius: 8px; border: 1px solid var(--ftg-input-border); background: var(--ftg-card);
  color: var(--ftg-faint); cursor: pointer; display: flex; align-items: center; justify-content: center; }
.ftg-modal-close:hover { background: var(--ftg-soft); color: var(--ftg-muted); }
.ftg-sec { display: flex; align-items: center; gap: 8px; font-size: 15px; font-weight: 600;
  color: var(--ftg-muted); text-transform: uppercase; letter-spacing: .02em;
  border-bottom: 1px solid var(--ftg-border); padding-bottom: 6px; margin: 22px 0 14px; }
.ftg-sec:first-child { margin-top: 0; }
.ftg-sec > i { color: var(--ftg-faint); width: 18px; text-align: center; }
.ftg-label { font-style: italic; font-size: 11px; text-transform: uppercase; letter-spacing: .03em;
  color: var(--ftg-faint); margin-bottom: 4px; }
.ftg-input { width: 100%; padding: 9px 12px; border: var(--border-w) var(--border-style) var(--ftg-ink);
  border-radius: 10px; font-size: 14px; font-family: var(--font-sans);
  background: var(--ftg-card); color: var(--ftg-text); }
.ftg-input:focus { outline: none; border-color: var(--ftg-ink); box-shadow: 2px 2px 0 var(--ftg-accent); }
.ftg-help { font-size: 11px; color: var(--ftg-muted); margin: 4px 0 12px; line-height: 1.35; }
.ftg-help:last-child { margin-bottom: 0; }

/* ---- Buttons -------------------------------------------------------------- */
.ftg-btn-save { padding: 9px 22px; border-radius: 12px; font-size: 14px; font-weight: 600; color: var(--m-on-accent);
  background: linear-gradient(135deg, var(--ftg-accent), var(--m-forest-d));
  border: none; box-shadow: 3px 3px 0 var(--ftg-ink); cursor: pointer;
  font-family: var(--font-sans); transition: all .15s ease; }
.ftg-btn-save:hover { background: var(--ftg-accent-hover); box-shadow: 1px 1px 0 var(--ftg-ink);
  transform: translate(2px, 2px); }
.ftg-btn-save:disabled { opacity: .5; cursor: not-allowed; }
/* Cancel: neutral gray (was the danger red) — coherent with the theme grays.
   Shares the exact same box metrics as .ftg-nav-btn so every bottom button
   in the onboarding windows matches in size. */
.ftg-btn-cancel { padding: 9px 22px; min-width: 132px; min-height: 44px; border-radius: 12px; font-size: 14px; font-weight: 600; color: var(--m-muted);
  background: var(--ftg-card); border: var(--border-w) var(--border-style) var(--m-muted); box-shadow: 3px 3px 0 var(--m-border-d);
  cursor: pointer; font-family: var(--font-sans); transition: all .15s ease; }
.ftg-btn-cancel:hover { background: var(--m-soft); box-shadow: 1px 1px 0 var(--m-border-d);
  transform: translate(2px, 2px); }

/* Uniform bottom-action buttons for the onboarding wizard: Back, Next, Finish.
   Defined after the .btn rules with equal specificity, so padding/radius/font
   always match across Cancel · Back · Next. */
.ftg-nav-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-width: 132px;
  min-height: 44px;
  padding: 9px 22px;
  border-radius: 12px;
  font-size: 14px;
  font-weight: 600;
  font-family: var(--font-sans);
  line-height: 1.2;
  cursor: pointer;
  white-space: nowrap;
}
.ftg-nav-btn:disabled { cursor: not-allowed; opacity: .55; }

/* Primary (Next / Finish) push effect: hard offset shadow while idle, the
   button sinks into it on hover and fully presses flat on click. */
.ftg-nav-btn.ftg-nav-btn-primary {
  box-shadow: 4px 4px 0 var(--m-ink);
  transition: transform .12s ease, box-shadow .12s ease;
}
.ftg-nav-btn.ftg-nav-btn-primary:hover:not(:disabled) {
  box-shadow: 2px 2px 0 var(--m-ink);
  transform: translate(2px, 2px);
}
.ftg-nav-btn.ftg-nav-btn-primary:active:not(:disabled) {
  box-shadow: 0 0 0 var(--m-ink);
  transform: translate(4px, 4px);
}

/* ---- Filter bar ------------------------------------------------------------ */
.ftg-filter { display: flex; align-items: center; gap: 10px; background: var(--ftg-card);
  border: var(--border-w) var(--border-style) var(--ftg-ink); border-radius: 12px; padding: 0 14px;
  transition: box-shadow 0.15s ease, transform 0.15s ease; }
.ftg-filter:focus-within { box-shadow: 3px 3px 0 var(--m-emerald); transform: translate(-1px, -1px); }
.ftg-filter > i { color: var(--ftg-faint); }
.ftg-filter input { flex: 1; min-width: 0; height: 38px; background: transparent;
  border: none; outline: none; font-size: 14px; font-family: var(--font-sans);
  color: var(--ftg-text); }
.ftg-filter input::placeholder { color: var(--ftg-faint); }
.ftg-filter .ftg-clear { background: none; border: none; color: var(--ftg-faint);
  cursor: pointer; padding: 0 6px; }
.ftg-filter .ftg-clear:disabled { color: var(--m-faint); cursor: not-allowed; }
.ftg-filter .ftg-clear:disabled:hover { color: var(--m-faint); }

/* ---- Console sort controls --------------------------------------------------- */
/* Shared primitives for the Projects / Users-Groups / Contracts filter bars,
   mirroring the Jobs-local .jb-select / .jb-sort-group / .jb-act so the three
   consoles share one definition (no drift). The .ftg-sortbar wrapper gives
   every control the same height, border, corner radius and font, and the same
   gap (the wrapper's gap-3 mirrored inside the sort group). */
.ftg-sortbar { --ftg-ctl-h: 40px; max-width: 760px; }
.ftg-sortbar .ftg-filter { height: var(--ftg-ctl-h); }
.ftg-sortbar .ftg-filter input { height: 100%; }
.ftg-select { height: var(--ftg-ctl-h, 40px); padding: 0 12px;
  border: var(--border-w) var(--border-style) var(--ftg-ink); border-radius: 12px;
  font-size: 14px; font-family: var(--font-sans);
  background: var(--ftg-card); color: var(--ftg-text); }
.ftg-sort-group { display: inline-flex; align-items: center; gap: 12px; }
.ftg-sortdir { width: var(--ftg-ctl-h, 40px); height: var(--ftg-ctl-h, 40px); border-radius: 12px;
  flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
  color: var(--ftg-muted); background: var(--ftg-card);
  border: var(--border-w) var(--border-style) var(--ftg-ink); cursor: pointer; }
.ftg-sortdir:hover { color: var(--ftg-ink); }

/* ---- Tabs ----------------------------------------------------------------- */
.ftg-tabs { display: flex; gap: 8px; border-bottom: 1px solid var(--ftg-border); padding-bottom: 8px; }
.ftg-tab { padding: 8px 16px; border-radius: 10px; font-size: 14px; font-weight: 500;
  color: var(--ftg-muted); background: transparent; border: none; cursor: pointer;
  font-family: var(--font-sans); }
.ftg-tab:hover { color: var(--ftg-ink); }
.ftg-tab.active { background: var(--ftg-accent); color: var(--m-on-accent); box-shadow: 2px 2px 0 var(--ftg-ink); }

/* ---- Card list (users_groups parity) --------------------------------------- */
.ug-card { display: block; background: var(--ftg-card); border: var(--border-w) var(--border-style) var(--ftg-ink);
  border-radius: 12px; box-shadow: 3px 3px 0 var(--m-shadow); margin-bottom: 8px;
  margin-left: var(--ug-indent, 0px); }
.ug-card.closed .ug-body { display: none; }
.ug-header { display: flex; align-items: center; width: 100%; padding: 11px 14px; cursor: pointer; }
.ug-trap { width: 8px; height: 26px; margin-right: 10px; flex: 0 0 auto; border-radius: 3px; }
.ug-cb { width: 16px; height: 16px; margin-right: 12px; flex: 0 0 auto; accent-color: var(--ftg-accent); }
.ug-type-ic { color: var(--ftg-muted); width: 18px; text-align: center; flex: 0 0 auto; }
.ug-spacer { width: 2rem; flex: 0 0 auto; }
.ug-mid { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 6px; padding-right: 12px; }
.ug-name { font-size: 14px; color: var(--ftg-ink); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ug-chip { width: 100%; padding: 4px 10px; border-radius: 8px; border: 1px solid var(--m-border);
  font-size: 13px; color: var(--ftg-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ug-right { display: flex; align-items: center; gap: 14px; flex: 0 0 auto; padding-right: 6px; }
.ug-ditem { display: flex; align-items: center; gap: 6px; }
.ug-dates { display: flex; align-items: center; gap: 10px; }
.ug-date { text-align: right; line-height: 1.1; }
.ug-date .d { font-size: 13px; color: var(--ftg-ink); font-weight: 600; }
.ug-date .tm { font-size: 10px; color: var(--ftg-faint); }
.ug-date-ic { color: var(--ftg-muted); }
.ug-edit { width: 38px; height: 38px; border-radius: 10px; display: flex; align-items: center;
  justify-content: center; color: var(--m-on-accent); flex: 0 0 auto; margin-left: 14px; cursor: pointer;
  background: linear-gradient(135deg, var(--ftg-accent), var(--m-forest-d)); box-shadow: 2px 2px 0 var(--ftg-ink); }
.ug-edit:hover { background: var(--ftg-accent-hover); }
.ug-body { border-top: 1px dashed var(--ftg-input-border); padding: 14px 16px; }
/* Mobile: the fixed-width right block (dates + action buttons) cannot shrink
   beside the name, so the header wraps and the right block flows onto its own
   second line (right-aligned, fully visible). Desktop layout is untouched.
   Tree indent (--ug-indent, set inline by the console JS) is softened to a
   third so deep rows still fit narrow screens. */
@media (max-width: 767.98px) {
  .ug-header { flex-wrap: wrap; }
  .ug-right { flex: 1 1 100%; flex-wrap: wrap; justify-content: flex-end; gap: 10px;
    padding-right: 0; margin-top: 6px; }
  .ug-card { margin-left: calc(var(--ug-indent, 0px) / 3); }
}

/* ---- Providers/Models usage & cost stats modal (.pm-stats-*) ------------- */
/* Self-contained block for the "$" stats modal (providers_stats_modal.js).
   All colors come from the skin custom properties so day/night both work. */
.pm-stats { display: flex; flex-direction: column; }
.pm-stats-summary {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px; margin: 0 0 16px;
}
.pm-stat {
  display: flex; align-items: center; gap: 10px;
  background: var(--ftg-soft); border: 1px solid var(--ftg-border);
  border-radius: 12px; padding: 10px 12px;
}
.pm-stat-ic {
  width: 34px; height: 34px; border-radius: 9px; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  background: var(--ftg-accent-soft); color: var(--ftg-accent); font-size: 15px;
}
.pm-stat-body { min-width: 0; }
.pm-stat-val {
  font-size: 16px; font-weight: 700; color: var(--ftg-ink); line-height: 1.1;
  font-variant-numeric: tabular-nums; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.pm-stat-lbl {
  font-size: 11px; color: var(--ftg-muted); text-transform: uppercase;
  letter-spacing: .03em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Scroll region: the table scrolls here while the summary stays put above it. */
.pm-stats-scroll {
  overflow: auto; max-height: min(58vh, 520px);
  border: 1px solid var(--ftg-border); border-radius: 12px;
  background: var(--ftg-card);
}
.pm-stats-table { width: 100%; min-width: 760px; border-collapse: collapse; font-size: 13px; }
.pm-stats-table thead th {
  position: sticky; top: 0; z-index: 1;
  text-align: left; font-weight: 600; color: var(--ftg-muted);
  background: var(--ftg-card);
  padding: 10px 12px; white-space: nowrap;
  border-bottom: 2px solid var(--ftg-border);
}
.pm-stats-th.sortable { cursor: pointer; user-select: none; }
.pm-stats-th.sortable:hover { color: var(--ftg-ink); background: var(--ftg-soft); }
.pm-sort-ind { display: inline-block; width: 1em; color: var(--ftg-accent); }
.pm-stats-table td {
  padding: 8px 12px; color: var(--ftg-text);
  border-bottom: 1px solid var(--ftg-soft); white-space: nowrap;
}
.pm-stats-name { display: flex; align-items: center; gap: 8px; }
.pm-stats-ic { width: 18px; height: 18px; flex: 0 0 auto; border-radius: 4px; }
.pm-stats-ic-fa { color: var(--ftg-muted); width: 18px; text-align: center; }
.pm-stats-num { text-align: right; font-variant-numeric: tabular-nums; }
/* Provider group row: emphasized band. */
.pm-stats-row-provider td {
  background: var(--ftg-accent-soft); font-weight: 600; color: var(--ftg-ink);
}
/* Model row: indented beneath its provider. */
.pm-stats-row-model .pm-stats-name { padding-left: 26px; }
.pm-stats-empty { padding: 24px; text-align: center; color: var(--ftg-faint); font-size: 14px; }

/* ---- Providers/Models usage stats explorer (.pus-*) ---------------------- */
/* Self-contained block for the line-chart modal (providers_usage_stats_modal.js).
   All colors come from the skin custom properties so day/night both work. */
.pus-wrap { display: flex; flex-direction: column; gap: 14px; }
.pus-toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
}
.pus-tabs {
  display: inline-flex; border: 1px solid var(--ftg-border); border-radius: 10px;
  overflow: hidden; background: var(--ftg-soft);
}
.pus-tab {
  border: 0; background: transparent; color: var(--ftg-muted);
  font-size: 13px; font-weight: 600; padding: 7px 14px; cursor: pointer;
}
.pus-tab + .pus-tab { border-left: 1px solid var(--ftg-border); }
.pus-tab.active { background: var(--ftg-accent); color: #fff; }
.pus-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-left: auto; }
.pus-filter { display: flex; flex-direction: column; gap: 2px; }
.pus-filter-label {
  font-size: 10px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--ftg-faint);
}
.pus-select {
  min-width: 130px; max-width: 220px; font-size: 13px;
  background: var(--ftg-card); color: var(--ftg-text);
  border: 1px solid var(--ftg-border); border-radius: 8px; padding: 6px 8px;
}
/* Multi-select user TreeMenu sized to match the sibling .pus-select dropdowns. */
.pus-user-menu { min-width: 130px; max-width: 220px; }
.pus-user-menu .tree-menu-btn {
  height: auto; padding: 6px 10px; font-size: 13px; border-radius: 8px;
  background-color: var(--ftg-card); border-color: var(--ftg-border);
  color: var(--ftg-text);
}
.pus-retention { display: flex; align-items: center; gap: 6px; }
.pus-retention input {
  width: 64px; font-size: 13px;
  background: var(--ftg-card); color: var(--ftg-text);
  border: 1px solid var(--ftg-border); border-radius: 8px; padding: 6px 8px;
}
.pus-clear {
  border: 1px solid var(--ftg-border); background: var(--ftg-soft);
  color: var(--ftg-muted); border-radius: 999px; font-size: 12px;
  padding: 5px 10px; cursor: pointer;
}
.pus-clear:hover { color: var(--ftg-ink); }
.pus-kpis {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 10px;
}
.pus-kpi {
  background: var(--ftg-card); border: 1px solid var(--ftg-border);
  border-radius: 12px; padding: 10px 12px;
  display: flex; flex-direction: column; gap: 4px;
}
.pus-kpi-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.pus-kpi-label {
  font-size: 11px; text-transform: uppercase; letter-spacing: .03em;
  color: var(--ftg-muted); white-space: nowrap;
}
.pus-kpi-val {
  font-size: 20px; font-weight: 700; color: var(--ftg-ink);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.pus-kpi-delta { font-size: 11px; font-weight: 600; white-space: nowrap; }
.pus-kpi-delta.up { color: var(--m-danger, #dc2626); }
.pus-kpi-delta.down { color: var(--m-success, #16a34a); }
.pus-kpi-delta.flat { color: var(--ftg-faint); }
.pus-kpi-spark { height: 36px; position: relative; }
.pus-panel {
  background: var(--ftg-card); border: 1px solid var(--ftg-border);
  border-radius: 12px; padding: 12px 14px;
}
.pus-panel-title {
  font-size: 14px; font-weight: 700; color: var(--ftg-ink); margin: 0 0 8px;
}
.pus-chart { position: relative; height: 260px; }
.pus-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 900px) { .pus-grid2 { grid-template-columns: 1fr; } }
.pus-users { display: flex; flex-direction: column; }
.pus-user-row {
  display: flex; align-items: center; gap: 10px; padding: 8px 4px;
  border-bottom: 1px solid var(--ftg-soft); cursor: pointer;
}
.pus-user-row:last-child { border-bottom: 0; }
.pus-user-row:hover { background: var(--ftg-soft); }
.pus-user-row.active { background: var(--ftg-accent-soft); }
.pus-avatar {
  width: 30px; height: 30px; border-radius: 50%; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  background: var(--ftg-accent-soft); color: var(--ftg-accent);
  font-size: 12px; font-weight: 700;
}
.pus-user-name { font-size: 13px; font-weight: 600; color: var(--ftg-ink); }
.pus-user-mail { font-size: 12px; color: var(--ftg-muted); }
.pus-user-nums { margin-left: auto; text-align: right; }
.pus-user-tok { font-size: 13px; font-weight: 700; color: var(--ftg-ink); font-variant-numeric: tabular-nums; }
.pus-user-cost { font-size: 12px; color: var(--ftg-muted); font-variant-numeric: tabular-nums; }
.pus-empty { padding: 18px; text-align: center; color: var(--ftg-faint); font-size: 13px; }
.pus-clickhint { font-size: 11px; color: var(--ftg-faint); font-weight: 400; margin-left: 8px; }

/* ==================================================================
   WAIT MODAL (.ftg-wait) — shared data-loading veil (ftg_wait.js)
   ------------------------------------------------------------------
   Covers the whole working area of the shell — everything except the
   sidebar and the topbar: it lives inside main.ft-main (position:
   relative above) with `top` set by JS to the measured topbar height.
   A 75%-opaque veil of the skin canvas color dims the page while the
   happy toad breathes (inflate/deflate 50% on a 1s cycle) and a
   translated "Loading…" caption sits under it.
   z-index: above the topbar (5000) but below the shared overlay layer
   (modals / toasts / run-progress dock, 90000+); the veil never
   overlaps the topbar anyway because of its top offset.
   ================================================================== */
.ftg-wait {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  /* top is set inline by ftg_wait.js (topbar height). */
  z-index: 6000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  /* Opaque fallback first; color-mix wins where supported: the veil is the
     skin canvas color at 75% opacity, so the dimmed page stays readable. */
  background: var(--m-canvas-top);
  background: color-mix(in srgb, var(--m-canvas-top) 75%, transparent);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  opacity: 0;
  transition: opacity 0.2s ease;
}
.ftg-wait--on { opacity: 1; }

/* The happy toad: inflate/deflate 50% on a 1s cycle, pure CSS. */
.ftg-wait-toad {
  width: 6rem;
  height: auto;
  object-fit: contain;
  filter: drop-shadow(0 6px 14px rgba(0, 0, 0, 0.18));
  animation: ftg-wait-breathe 1s ease-in-out infinite;
}
@keyframes ftg-wait-breathe {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.5); }
}

.ftg-wait-label {
  font-size: 1rem;
  font-weight: 600;
  color: var(--m-ink);
}

@media (prefers-reduced-motion: reduce) {
  .ftg-wait { transition: none; }
  .ftg-wait-toad { animation: none; }
}
