/* TradeNeon portal — dark-first global component + shell layer.
 *
 * Phase 12 (2026-07-03), finalized Phase 20 (2026-07-04). The ONLY global
 * sheets are tokens.css + this file — the legacy override layer is gone. Load
 * order (base.html / base_auth.html / base_checkout.html):
 *   fonts -> tokens.css -> portal.css -> {% block extra_css %} (page CSS)
 *
 * Page CSS is the last layer and wins cleanly for page-specific layout — no
 * override sheet, no deeper-scoping trick needed for new work.
 *
 * Rules here fall into two groups:
 *   1. Namespaced components (.card, .tn-btn, .badge--*, .alert--*, .input,
 *      .toggle, .popover, .tn-* typography, .card-grid).
 *   2. Shell chrome (body/.main-content/.main-header, sidebar + .main-nav,
 *      language switcher, .page-header, the Django-messages toast strip,
 *      content dark-defaults, flatpickr) — relocated here from the DELETED
 *      portal_dark.css / main.css / sidebar.css / page-header.css, tokenized,
 *      output-identical, single-owner.
 *
 * Tokens only — no raw hex except where no token exists (add a token rather
 * than a literal). The legacy variables.css tokens are deleted; never
 * reference --primary-color / --highlight-color* / --text-color / --bg-color
 * / --default-* / --*-font.
 */

/* ---------------------------------------------------------------------------
 * Fonts. Inter (body face) is loaded from Google Fonts in the base
 * templates. Montserrat is the button face (button-regeln.md): 700 + 800,
 * vendored woff2, font-display: swap so text paints immediately.
 * (Montserrat 400/700 are also declared in main.css; the 700 redecl here is
 * harmless — same URL, browser downloads once.)
 * ------------------------------------------------------------------------- */

@font-face {
  font-family: 'Montserrat';
  src: url('../fonts/montserrat/Montserrat-700.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Montserrat';
  src: url('../fonts/montserrat/Montserrat-800.woff2') format('woff2');
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}

/* Montserrat 400 (body-weight) + Bebas Neue display face relocated from
 * main.css in Phase 20 (main.css dissolved). Montserrat 400 backs FI's
 * --fi-font-body; Bebas Neue backs tutorials.css's --secondary-font. */
@font-face {
  font-family: 'Montserrat';
  src: url('../fonts/montserrat/Montserrat-regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Bebas Neue';
  src: url('../fonts/bebas_neue/BebasNeue-Regular.woff2') format('woff2');
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

/* ---------------------------------------------------------------------------
 * Base shell (moved from portal_dark.css). Overrides main.css's legacy
 * white surfaces to the dark base. On base_auth.html the auth shell's own
 * inline <style> loads later and keeps its full-bleed layout; on
 * base_checkout.html the inline checkout block loads later and keeps that
 * shell light (page styles win by order).
 * ------------------------------------------------------------------------- */

body {
  background-color: var(--bg);
  color: var(--text);
  font-family: var(--font);
  margin: 0;
  padding: 0;
}

.main-content {
  background-color: var(--bg);
  color: var(--text);
}

.main-header {
  background-color: transparent;
}

/* Soft right-cast shadow + thin edge so the (dark) sidebar reads as a
 * distinct surface against the (also-dark) main panel. Base .sidebar
 * geometry/background stays in main.css. */
.sidebar {
  box-shadow: 5px 0 15px rgba(0, 0, 0, 0.15);
  border-right: 1px solid var(--card-border);
}

/* ---------------------------------------------------------------------------
 * Sidebar expandable menu (moved from sidebar.css; base.html no longer
 * links sidebar.css). Structural rules; the one theme color (white) is
 * tokenized to --text (identical value).
 * ------------------------------------------------------------------------- */

.expandable-menu {
  position: relative;
  width: 100%;
}

.submenu {
  display: none;
  list-style: none;
  padding-left: 15px;
  margin: 0;
}

.nav-item {
  display: flex;
  align-items: center;
  padding: 12px 20px;
  color: var(--text);
  text-decoration: none;
  font-size: 14px;
  width: auto;
}

.toggle-submenu {
  position: relative;
}

.menu-text {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.arrow-icon {
  width: 24px;
  height: 24px;
  margin-left: 5px;
  transition: transform 0.3s;
}

.arrow-rotate {
  transform: rotate(180deg);
}

.expandable-menu.active > .submenu {
  display: block;
}

.submenu-icon {
  width: 20px;
  height: 20px;
  margin-right: 10px;
  object-fit: contain;
}

.submenu .nav-item {
  padding: 8px 20px 8px 25px;
  font-size: 13px;
}

.submenu .submenu .nav-item {
  padding-left: 30px;
}

/* ---------------------------------------------------------------------------
 * Page header (moved from page-header.css + portal_dark.css overrides,
 * collapsed into one dark-first block). base.html no longer links
 * page-header.css and the 11 per-page links were removed; portal.css now
 * owns it. FI dashboard/detail keep their own .page-header layout overrides
 * (they load in extra_css, after portal.css). Output matches the previous
 * composite: transparent bg, white h1 @28px, muted h2 @14px.
 * ------------------------------------------------------------------------- */

.page-header {
  padding: 0 30px 20px;
  background-color: transparent;
}

/* h1/h2 are scoped under .main-content (raising specificity to 0,2,1) so they
 * beat portal_dark.css's surviving generic `.main-content h1..h6 { color:#fff }`
 * rule — which still loads LAST until Phase 20 — as well as any per-page
 * `.page-header h2 { color:white }` inline (e.g. the FI dashboard). This
 * restores the muted 70%-white subtitle. The base `.page-header` rule above
 * stays at 0,1,0 so FI detail.css's `.page-header` padding override still wins.
 * All .page-header markup lives inside .main-content on base.html pages. */
.main-content .page-header h1 {
  margin: 0;
  font-size: 28px;
  color: var(--text);
}

.main-content .page-header h2 {
  margin: 0;
  font-size: 14px;
  color: var(--text-muted);
}

/* ---------------------------------------------------------------------------
 * Shell chrome — sidebar geometry, top header, nav, language switcher
 * (relocated from main.css in Phase 20; main.css dissolved). Tokenized
 * dark: main.css painted the sidebar with the legacy --primary-color
 * (#090D56 ≡ rgb(9,13,86) ≡ --bg) and text white ≡ --text, so these render
 * byte-identical. Only base.html carries `.app-container`, so nothing here
 * leaks to the auth/checkout shells. .sidebar box-shadow/border-right and
 * the .main-content/.main-header dark backgrounds live in the base-shell
 * block above; this adds the geometry those rules didn't carry.
 * ------------------------------------------------------------------------- */

.app-container {
  display: flex;
  min-height: 100vh;
}

.sidebar {
  width: var(--sidebar-width);
  background-color: var(--bg);
  color: var(--text);
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  height: 100vh;
  position: fixed;
  overflow-y: auto;
}

.main-content {
  flex: 1;
  margin-left: var(--sidebar-width);
}

.full-width {
  width: 100%;
}

.main-content.full-width {
  width: 100%;
  margin-left: 0;
}

.logo-container {
  padding: 20px;
  text-align: center;
}

.logo {
  max-width: 100%;
}

.main-nav ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.menu-icon {
  width: 25px;
  height: auto;
  margin-right: 10px;
  vertical-align: middle;
}

.main-nav .nav-item {
  display: flex;
  align-items: center;
  padding: 12px 20px;
  color: var(--text);
  text-decoration: none;
  font-size: 14px;
}

.main-nav .nav-item:hover {
  background-color: rgba(255, 255, 255, 0.1);
}

.main-nav .nav-item.active {
  background-color: var(--fi-blue);
  cursor: default;
  pointer-events: none;
}

.main-nav .nav-item.active:hover {
  background-color: var(--fi-blue);
  text-decoration: none;
}

.sidebar-footer {
  margin-top: auto;
  padding: 20px;
  text-align: center;
}

.copyright {
  font-size: 12px;
  opacity: 0.7;
}

.footer-links {
  display: flex;
  justify-content: center;
  margin-top: 10px;
}

.policy-link {
  margin: 0 10px;
  font-size: 0.5rem;
  color: var(--text);
}

.policy-link:hover {
  color: var(--accent);
}

.main-header {
  display: flex;
  justify-content: end;
  align-items: center;
  padding: 5px 30px;
}

.language-selector {
  display: flex;
  gap: 10px;
}

.lang-btn {
  font-size: 20px;
  padding: 5px;
  text-decoration: none;
}

.language_switcher_icon {
  width: 30px;
}

/* Unread-messages dot on the Messages nav item. */
.notification-dot {
  position: relative;
}

.notification-dot::after {
  content: '';
  position: absolute;
  top: 8px;
  right: 8px;
  width: 8px;
  height: 8px;
  background-color: var(--accent);
  border-radius: 50%;
  border: 2px solid var(--bg);
}

/* ---------------------------------------------------------------------------
 * Content dark-defaults for legacy pages (relocated from portal_dark.css in
 * Phase 20). main.css defaulted headings to the dark-blue --primary-color and
 * links to periwinkle; on the navy shell those are invisible/off-brand, so
 * scope white headings + pink links under .main-content. Rebuilt pages
 * (.dash-page/.mf-shop/.loi2/.fi-*) set their own colors at higher
 * specificity and are unaffected. Auth/checkout shells have no .main-content.
 * ------------------------------------------------------------------------- */

.main-content h1,
.main-content h2,
.main-content h3,
.main-content h4,
.main-content h5,
.main-content h6 {
  color: var(--text);
}

.main-content a {
  color: var(--accent);
}

.main-content a:hover {
  color: var(--text);
}

/* ---------------------------------------------------------------------------
 * Global toast / Django messages strip rendered from base.html (relocated
 * from portal_dark.css in Phase 20). Scoped via direct-child chain so it
 * styles only the toast stack, never the Messages page's reused
 * `.messages-container` layout wrapper.
 * ------------------------------------------------------------------------- */

.app-container > .main-content > .messages-container {
  padding: 10px 30px 0;
}

.app-container > .main-content > .messages-container > .message {
  background: rgba(255, 255, 255, 0.10);
  border: 1px solid var(--card-border);
  border-radius: 8px;
  color: var(--text);
  padding: 12px 16px;
  margin-top: 12px;
  text-align: left;
}

.app-container > .main-content > .messages-container > .message-success {
  background: rgba(255, 60, 141, 0.12);
  border-color: var(--danger-border);
  color: var(--accent);
}

.app-container > .main-content > .messages-container > .message-error,
.app-container > .main-content > .messages-container > .message-warning {
  background: rgba(255, 60, 141, 0.12);
  border-color: var(--danger-border);
  color: var(--danger-text);
}

.app-container > .main-content > .messages-container > .message-info {
  background: var(--info-bg);
  border-color: var(--info-border);
  color: var(--info-text);
}

/* ===========================================================================
 * NEW COMPONENTS (namespaced, consumed from Phase 15). Inert on today's
 * pages — no bare element selectors that could restyle un-rebuilt pages.
 * =========================================================================== */

/* ---------------------------------------------------------------------------
 * Typography scale (design-system §3). Hierarchy comes from weight +
 * white-opacity, never gray hues. Opt-in classes so legacy headings are
 * untouched. Buttons override to Montserrat 800 (see .tn-btn).
 * ------------------------------------------------------------------------- */

.tn-hero-num     { font-size: 3rem;    font-weight: 900; line-height: 1; color: var(--text); }
.tn-section-title{ font-size: 2.4rem;  font-weight: 900; text-transform: uppercase; letter-spacing: 2px; color: var(--text); }
.tn-card-heading { font-size: 1.6rem;  font-weight: 700; color: var(--text); }
.tn-subtitle     { font-size: 1.2rem;  font-weight: 700; color: var(--accent); }
.tn-body         { font-size: 0.95rem; font-weight: 400; color: var(--text-on-card); }
.tn-label        { font-size: 0.85rem; font-weight: 600; letter-spacing: 0.3px; color: var(--text-muted); }
.tn-microcopy    { font-size: 0.8rem;  font-weight: 300; color: var(--text-tertiary); }

/* ---------------------------------------------------------------------------
 * Cards — frosted-glass surfaces (design-system §5). Depth from
 * translucency; hover = lift + border brighten, never a flat repaint.
 * ------------------------------------------------------------------------- */

.card {
  background: var(--card-surface);
  border: 1px solid var(--card-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  color: var(--text-on-card);
  padding: 40px 32px;
  transition: transform var(--transition), border-color var(--transition),
              box-shadow var(--transition);
}

.card:hover {
  transform: translateY(-4px);
  border-color: var(--card-border-hover);
}

.card__header {
  border-bottom: 1px solid var(--hairline);
  padding-bottom: 16px;
  margin-bottom: 20px;
  color: var(--text);
}

.card--featured {
  background: var(--card-surface-bright);
  border-radius: var(--radius-lg);
}

/* ---------------------------------------------------------------------------
 * Buttons (button-regeln.md 2026-06-29). 14px radius (NOT pills),
 * Montserrat 800 uppercase, lift on hover. Per-context color via
 * --btn-from/--btn-to/--btn-glow/--btn-text. The shine sweep is opt-in via
 * .tn-btn--shine ONLY (never on the base class) — reserved for
 * purchase/checkout CTAs + the highlighted pricing-card CTA.
 * ------------------------------------------------------------------------- */

.tn-btn {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  font-family: 'Montserrat', system-ui, sans-serif;
  font-weight: 800;
  font-size: 14px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  border-radius: 14px;
  border: 1px solid transparent;
  transition: transform 0.25s ease, box-shadow 0.25s ease, filter 0.25s ease,
              border-color 0.25s ease, background-color 0.25s ease;
}

/* Primary = filled gradient (per-context via tokens). */
.tn-btn--primary {
  padding: 15px 26px;
  color: var(--btn-text);
  background: linear-gradient(120deg, var(--btn-from), var(--btn-to) 50%);
  box-shadow: 0 10px 30px var(--btn-glow);
}

.tn-btn--primary:hover {
  transform: translateY(-3px);
  filter: brightness(1.04);
  box-shadow: 0 16px 40px var(--btn-glow);
}

/* Ghost = transparent + outline (secondary). */
.tn-btn--ghost {
  padding: 15px 24px;
  color: #fff;
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(23, 248, 224, 0.40);
}

.tn-btn--ghost:hover {
  transform: translateY(-3px);
  border-color: rgba(23, 248, 224, 0.70);
  background: rgba(23, 248, 224, 0.08);
}

/* Google sign-in — white surface, dark text, normal case (design-system §5). */
.tn-btn--google {
  padding: 13px 22px;
  color: #1f1f1f;
  background: #fff;
  border-color: var(--card-border);
  font-family: var(--font);
  font-weight: 700;
  text-transform: none;
  letter-spacing: 0;
}

.tn-btn--google:hover {
  transform: translateY(-3px);
  background: #f2f2f2;
}

/* Disabled state. */
.tn-btn:disabled,
.tn-btn.is-disabled {
  opacity: 0.55;
  pointer-events: none;
}

/* Shine sweep (opt-in). Left -> right on hover. NOT on the base class. */
.tn-btn--shine::after {
  content: "";
  position: absolute;
  top: 0;
  left: -120%;
  width: 60%;
  height: 100%;
  background: linear-gradient(120deg, transparent, rgba(255, 255, 255, 0.35), transparent);
  transform: skewX(-20deg);
  transition: left 0.6s ease;
  pointer-events: none;
}

.tn-btn--shine:hover::after {
  left: 140%;
}

/* ---------------------------------------------------------------------------
 * Inputs & labels (design-system §5).
 * ------------------------------------------------------------------------- */

.label {
  display: block;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.3px;
  color: var(--text-muted);
  margin-bottom: 8px;
}

.input {
  width: 100%;
  padding: 12px 14px;
  background: var(--input-bg);
  border: 1px solid var(--input-border);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-family: var(--font);
  transition: border-color var(--transition), background var(--transition);
}

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

.input:focus {
  outline: none;
  border-color: var(--input-border-focus);
  background: var(--input-bg-focus);
}

.input--readonly {
  background: rgba(255, 255, 255, 0.04);
  color: var(--text-tertiary);
}

/* ---------------------------------------------------------------------------
 * Badges / pills. Pills STAY pills here (button-regeln: status badges,
 * savings labels, market chips are not buttons).
 * ------------------------------------------------------------------------- */

.badge {
  display: inline-block;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.badge--accent  { background: rgba(255, 60, 141, 0.18); color: var(--accent); }
.badge--savings { background: #fff;                      color: var(--accent-deep); }
.badge--success { background: var(--success-bg);         color: var(--success-text); }
.badge--info    { background: var(--info-bg);            color: var(--info-text); }
.badge--ghost   { background: rgba(255, 255, 255, 0.10); color: var(--text-muted); }

/* ---------------------------------------------------------------------------
 * Alerts. Success is pink-tinted / brand-forward (green is reserved for the
 * compact status badges above), matching the portal toast styling.
 * ------------------------------------------------------------------------- */

.alert {
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: 12px 16px;
  color: var(--text);
}

.alert--success {
  background: rgba(255, 60, 141, 0.12);
  border-color: var(--danger-border);
  color: var(--accent);
}

.alert--error,
.alert--warning {
  background: rgba(255, 60, 141, 0.12);
  border-color: var(--danger-border);
  color: var(--danger-text);
}

.alert--info {
  background: var(--info-bg);
  border-color: var(--info-border);
  color: var(--info-text);
}

/* ---------------------------------------------------------------------------
 * Toggle switch (pill track + sliding knob, design-system §5). Segmented
 * plan toggles stay pills per button-regeln.
 * ------------------------------------------------------------------------- */

.toggle {
  position: relative;
  width: 70px;
  height: 36px;
  background: var(--btn-bg);
  border: none;
  border-radius: var(--radius-pill);
  cursor: pointer;
}

.toggle::after {
  content: '';
  position: absolute;
  width: 28px;
  height: 28px;
  background: var(--text);
  border-radius: 50%;
  top: 4px;
  left: 4px;
  transition: transform var(--transition);
}

.toggle.is-on::after {
  transform: translateX(34px);
}

/* ---------------------------------------------------------------------------
 * Popover / dropdown surface + flatpickr calendar (flatpickr rules moved
 * from portal_dark.css:751ff, rewritten against tokens, output-identical).
 * ------------------------------------------------------------------------- */

.popover {
  background: var(--surface-dropdown);
  border: 1px solid var(--card-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-pop);
  color: var(--text);
}

.flatpickr-calendar {
  background: var(--surface-dropdown);
  border: 1px solid var(--card-border);
  border-radius: 10px;
  box-shadow: var(--shadow-pop);
  color: var(--text);
}

.flatpickr-calendar.arrowTop::before,
.flatpickr-calendar.arrowBottom::before {
  border-bottom-color: var(--card-border);
  border-top-color: var(--card-border);
}

.flatpickr-calendar.arrowTop::after {
  border-bottom-color: var(--surface-dropdown);
}

.flatpickr-calendar.arrowBottom::after {
  border-top-color: var(--surface-dropdown);
}

.flatpickr-months,
.flatpickr-month,
.flatpickr-current-month {
  background: transparent;
  color: var(--text);
}

/* Default flatpickr renders the month label at 135% — too dominant in a
 * compact portal calendar. Drop back to the calendar base size and force
 * white so labels read against the dark surface. */
.flatpickr-current-month {
  font-size: 100%;
}

.flatpickr-current-month .flatpickr-monthDropdown-months,
.flatpickr-current-month input.cur-year,
.flatpickr-current-month input.cur-year[disabled],
.flatpickr-current-month input.cur-year[disabled]:hover {
  background: transparent;
  color: var(--text);
}

.flatpickr-current-month .flatpickr-monthDropdown-months .flatpickr-monthDropdown-month {
  background: var(--surface-dropdown);
  color: var(--text);
}

.flatpickr-prev-month,
.flatpickr-next-month {
  color: var(--text);
  fill: var(--text);
}

.flatpickr-prev-month svg,
.flatpickr-next-month svg {
  fill: var(--text);
}

.flatpickr-prev-month:hover,
.flatpickr-next-month:hover,
.flatpickr-prev-month:hover svg,
.flatpickr-next-month:hover svg {
  color: var(--text);
  fill: var(--accent);
}

.flatpickr-weekdays,
span.flatpickr-weekday {
  background: transparent;
  color: var(--text-tertiary);
}

.flatpickr-days {
  border: 0;
}

.flatpickr-day {
  background: transparent;
  border: 1px solid transparent;
  color: var(--text);
}

.flatpickr-day:hover,
.flatpickr-day:focus {
  background: rgba(255, 255, 255, 0.10);
  border-color: var(--card-border);
  color: var(--text);
}

.flatpickr-day.today {
  border-color: rgba(255, 60, 141, 0.55);
  color: var(--text);
}

.flatpickr-day.today:hover {
  background: rgba(255, 60, 141, 0.18);
  border-color: var(--accent);
  color: var(--text);
}

.flatpickr-day.selected,
.flatpickr-day.selected:hover,
.flatpickr-day.selected:focus {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--text);
}

.flatpickr-day.prevMonthDay,
.flatpickr-day.nextMonthDay {
  color: rgba(255, 255, 255, 0.30);
}

.flatpickr-day.flatpickr-disabled,
.flatpickr-day.flatpickr-disabled:hover,
.flatpickr-day.notAllowed,
.flatpickr-day.notAllowed.prevMonthDay,
.flatpickr-day.notAllowed.nextMonthDay {
  background: transparent;
  border-color: transparent;
  color: rgba(255, 255, 255, 0.20);
  cursor: not-allowed;
}

.numInputWrapper:hover {
  background: rgba(255, 255, 255, 0.06);
}

.numInputWrapper span.arrowUp::after {
  border-bottom-color: var(--text-muted);
}

.numInputWrapper span.arrowDown::after {
  border-top-color: var(--text-muted);
}

/* ---------------------------------------------------------------------------
 * Responsive grid utility (design-system §6). Namespaced so it never
 * touches legacy page grids. 4-col -> 2-col @1024 -> 1-col @768/600.
 * ------------------------------------------------------------------------- */

.card-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
}

@media (max-width: 1024px) {
  .card-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 768px) {
  .card-grid { grid-template-columns: 1fr; }
}

@media (max-width: 600px) {
  .card-grid {
    grid-template-columns: 1fr;
    max-width: 320px;
    margin-left: auto;
    margin-right: auto;
  }
}

/* ============================================================
   Walkthrough tour (Phase 18)
   Shared component layer for the LOI + FI guided tours. The engine
   (static/js/portal_tour.js) creates .wt-tip / .wt-modal at runtime and
   appends them to <body>; the spotlight class .wt-highlight lands on the
   in-page anchor. --tour-accent is set per page by the engine
   (LOI -> --loi-pink, FI -> --fi-accent); the fallback keeps the spotlight
   visible even if init() omits it.
   z-index stack sits above the app chrome and the Phase-11 consent popups
   (max 1000): highlight 1002 < tip 1004 < modal 1006. While a popup is open
   the tour pauses (hides itself), so the two overlays never fight.
   ============================================================ */
:root { --tour-accent: var(--accent); }

/* Spotlight: ring in the product accent + a full-viewport scrim punched out
   around the anchor. */
.wt-highlight {
  position: relative;
  z-index: 1002;
  border-radius: var(--radius-lg);
  box-shadow: 0 0 0 3px var(--tour-accent), 0 0 0 9999px rgba(4, 6, 40, 0.86);
  transition: box-shadow 0.18s ease;
}

/* Anchored coachmark. Hidden until the engine adds .is-open. */
.wt-tip {
  position: fixed;
  z-index: 1004;
  top: 0;
  left: 0;
  display: none;
  width: min(346px, 88vw);
  padding: 18px 18px 14px;
  background: var(--surface-dropdown);
  border: 1px solid var(--card-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-pop);
  color: var(--text);
}
.wt-tip.is-open { display: block; }

.wt-step {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--tour-accent);
  margin-bottom: 6px;
}
.wt-tip-title {
  font-size: 16px;
  font-weight: 700;
  line-height: 1.3;
  margin-bottom: 6px;
}
.wt-tip-body {
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text-on-card);
  margin-bottom: 14px;
}

.wt-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.wt-spacer { flex: 1 1 auto; }

/* Centered modal for the Welcome / End steps. */
.wt-modal {
  position: fixed;
  inset: 0;
  z-index: 1006;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(4, 6, 40, 0.74);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}
.wt-modal.is-open { display: flex; }

.wt-modal-card {
  width: min(440px, 92vw);
  padding: 30px 28px 22px;
  text-align: center;
  background: var(--surface-dropdown);
  border: 1px solid var(--card-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop);
  color: var(--text);
}
.wt-modal-ic { font-size: 40px; line-height: 1; margin-bottom: 12px; }
.wt-modal-title { font-size: 21px; font-weight: 700; margin-bottom: 10px; }
.wt-modal-body {
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--text-on-card);
  margin-bottom: 22px;
}
.wt-modal-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
}

/* Shared buttons. Primary uses the product accent; ghost/skip are quiet. */
.wt-btn {
  appearance: none;
  border: 0;
  cursor: pointer;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  padding: 9px 16px;
  border-radius: var(--radius-pill);
  transition: filter 0.15s ease, background 0.15s ease, border-color 0.15s ease;
}
.wt-btn--primary {
  background: var(--tour-accent);
  color: #080B14;
}
.wt-btn--primary:hover { filter: brightness(1.08); }
.wt-btn--ghost {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--card-border);
}
.wt-btn--ghost:hover { border-color: var(--card-border-hover); }
.wt-skip {
  appearance: none;
  border: 0;
  background: transparent;
  cursor: pointer;
  font: inherit;
  font-size: 12.5px;
  color: var(--text-tertiary);
  padding: 6px 4px;
}
.wt-skip:hover { color: var(--text); }

/* Hero restart control (top-right of the LOI / FI hero). Ghost text button. */
.hero-main, .fi-hero-main { position: relative; }
.wt-restart {
  position: absolute;
  top: 0;
  right: 0;
  z-index: 3;
  appearance: none;
  cursor: pointer;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-muted);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--card-border);
  border-radius: var(--radius-pill);
  padding: 6px 13px;
  transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}
.wt-restart:hover {
  color: var(--text);
  border-color: var(--card-border-hover);
  background: rgba(255, 255, 255, 0.10);
}

@media (max-width: 600px) {
  .wt-restart { position: static; margin-bottom: 12px; }
}

/* ---------------------------------------------------------------------------
   Impersonation banner ("Login as" support mode — accounts.impersonation).
   Sticky strip above the app shell; deliberately loud (danger tint) so an
   admin can never mistake a support session for their own account.
--------------------------------------------------------------------------- */
.imp-banner {
  position: sticky;
  top: 0;
  z-index: 1200;               /* above sidebar/header chrome */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 10px 20px;
  background: var(--danger-bg);
  border-bottom: 1px solid var(--danger-border);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.imp-banner__info {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  min-width: 0;
}
.imp-banner__label {
  font-weight: 800;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--danger-text);
  border: 1px solid var(--danger-border);
  border-radius: var(--radius-pill);
  padding: 3px 10px;
  white-space: nowrap;
}
.imp-banner__who {
  color: var(--text);
  font-size: 14px;
}
.imp-banner__who strong { font-weight: 700; }
.imp-banner__status {
  color: var(--text-muted);
  font-size: 13px;
}
.imp-banner__exit { margin: 0; }
.imp-banner__exit .tn-btn { padding: 7px 16px; font-size: 12.5px; }

@media (max-width: 600px) {
  .imp-banner { padding: 10px 12px; }
}

/* ============================================================
   Collapsible + responsive navigation (Phase-1 mobile/UX sweep)
   ------------------------------------------------------------
   Desktop (>=769px): the burger in the sidebar head toggles a slim
   icon-only rail; the choice persists via UserProfile.ui_state
   (nav/collapsed), so base.html server-renders `.nav-collapsed` with no
   flash. While slim, hovering the NAV-ITEMS area only (not the burger or
   the logout) "peeks" the full menu back as an overlay that does NOT
   reflow the page; leaving collapses it again (portal_nav.js adds/removes
   `.nav-peek`).
   Mobile (<=768px): the sidebar is off-canvas (translateX(-100%)); a
   floating burger slides it in full-width from the left over a scrim;
   tapping a link, the scrim, or the header burger closes it
   (`body.nav-mobile-open`).
   Motion: --nav-duration (400ms) / --nav-ease (decelerating).
   ============================================================ */

/* Sidebar head: logo + collapse burger on one row. */
.sidebar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding-right: 8px;
}
.sidebar-head .logo-container { flex: 1 1 auto; min-width: 0; }

/* Clip labels while the rail narrows so nothing bleeds past the slim edge. */
.sidebar { overflow-x: hidden; transition: width var(--nav-duration) var(--nav-ease); }
.main-content { transition: margin-left var(--nav-duration) var(--nav-ease); }
.main-nav .nav-item { white-space: nowrap; }

/* Burger buttons (in-sidebar collapse toggle + floating mobile toggle). */
.nav-toggle,
.nav-mobile-toggle {
  appearance: none;
  background: transparent;
  border: 0;
  color: var(--text);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 8px;
  border-radius: 10px;
  flex: 0 0 auto;
  transition: background var(--transition);
}
.nav-toggle:hover,
.nav-mobile-toggle:hover { background: rgba(255, 255, 255, 0.10); }

/* Floating mobile burger — hidden on desktop, revealed at the mobile bp.
   z-index above the impersonation banner (1200) so it stays tappable. */
.nav-mobile-toggle {
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 1310;
  display: none;
  background: var(--card-surface);
  border: 1px solid var(--card-border);
  box-shadow: var(--shadow-card);
}
/* Burger morphs to an X while the drawer is open (clear "close" affordance). */
.nav-mobile-toggle__close { display: none; }
body.nav-mobile-open .nav-mobile-toggle__burger { display: none; }
body.nav-mobile-open .nav-mobile-toggle__close { display: inline; }

/* Scrim behind the mobile drawer (a body-level sibling of .app-container). */
.nav-scrim {
  position: fixed;
  inset: 0;
  z-index: 1290;
  background: rgba(0, 0, 0, 0.55);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--nav-duration) var(--nav-ease), visibility var(--nav-duration);
}

/* Logout icon rides alongside the label; only shown when the rail is slim. */
.nav-logout { display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
.nav-logout__icon { display: none; flex: 0 0 auto; }

/* ===================== Desktop: slim rail ===================== */
@media (min-width: 768px) {
  .app-container.nav-collapsed .sidebar { width: var(--sidebar-width-slim); }
  .app-container.nav-collapsed .main-content { margin-left: var(--sidebar-width-slim); }

  /* Slim (and NOT peeking): hide text, center icons, drop chrome. */
  .app-container.nav-collapsed:not(.nav-peek) .sidebar-head { justify-content: center; padding-right: 0; }
  .app-container.nav-collapsed:not(.nav-peek) .logo-container { display: none; }
  .app-container.nav-collapsed:not(.nav-peek) .nav-label,
  .app-container.nav-collapsed:not(.nav-peek) .main-nav .menu-text,
  .app-container.nav-collapsed:not(.nav-peek) .main-nav .arrow-icon,
  .app-container.nav-collapsed:not(.nav-peek) .sidebar-footer .copyright,
  .app-container.nav-collapsed:not(.nav-peek) .sidebar-footer .footer-links { display: none; }
  .app-container.nav-collapsed:not(.nav-peek) .submenu { display: none !important; }
  .app-container.nav-collapsed:not(.nav-peek) .main-nav .nav-item { justify-content: center; padding-left: 0; padding-right: 0; }
  .app-container.nav-collapsed:not(.nav-peek) .menu-icon { margin-right: 0; }
  .app-container.nav-collapsed:not(.nav-peek) .nav-logout { padding-left: 0; padding-right: 0; }
  .app-container.nav-collapsed:not(.nav-peek) .nav-logout .nav-label { display: none; }
  .app-container.nav-collapsed:not(.nav-peek) .nav-logout__icon { display: inline-flex; }

  /* Peek: hovering the nav items re-expands the rail as an OVERLAY (the
     page does not reflow — main-content margin stays slim). */
  .app-container.nav-collapsed.nav-peek .sidebar {
    width: var(--sidebar-width);
    z-index: 1101;
    box-shadow: 10px 0 28px rgba(0, 0, 0, 0.45);
  }
  .app-container.nav-collapsed.nav-peek .main-content { margin-left: var(--sidebar-width-slim); }
}

/* ===================== Mobile: off-canvas drawer ===================== */
@media (max-width: 767.98px) {
  .nav-mobile-toggle { display: inline-flex; }
  /* Reserve the top-left corner so page content never sits under the burger. */
  .main-header { padding-left: 52px; min-height: 44px; }

  /* Sidebar becomes a full-width panel that slides in from the left.
     z-index above the impersonation banner (1200) so the drawer isn't
     partially covered by it during a mobile support session. */
  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    max-width: 100%;
    height: 100vh;
    height: 100dvh;
    transform: translateX(-100%);
    z-index: 1300;
    transition: transform var(--nav-duration) var(--nav-ease);
  }
  body.nav-mobile-open .sidebar { transform: translateX(0); }
  body.nav-mobile-open .nav-scrim { opacity: 1; visibility: visible; }

  /* Content always reclaims the full width on mobile — the desktop
     collapsed/peek states are irrelevant here. */
  .main-content,
  .app-container.nav-collapsed .main-content { margin-left: 0 !important; }
  .app-container.nav-collapsed .sidebar { width: 100%; }

  /* The full drawer always shows labels/logo/submenus (never the slim rail). */
  .app-container.nav-collapsed:not(.nav-peek) .logo-container,
  .app-container.nav-collapsed:not(.nav-peek) .nav-label,
  .app-container.nav-collapsed:not(.nav-peek) .main-nav .menu-text,
  .app-container.nav-collapsed:not(.nav-peek) .main-nav .arrow-icon,
  .app-container.nav-collapsed:not(.nav-peek) .sidebar-footer .copyright,
  .app-container.nav-collapsed:not(.nav-peek) .sidebar-footer .footer-links { display: revert; }
  .app-container.nav-collapsed:not(.nav-peek) .main-nav .nav-item { justify-content: flex-start; }
  .app-container.nav-collapsed:not(.nav-peek) .nav-logout .nav-label { display: inline; }
  .app-container.nav-collapsed:not(.nav-peek) .nav-logout__icon { display: none; }
  .app-container.nav-collapsed:not(.nav-peek) .menu-icon { margin-right: 10px; }

  /* The floating burger toggles the drawer, so the in-drawer header burger is
     redundant on mobile — hide it and center the logo (clear of the floating
     burger at top-left). */
  .nav-toggle { display: none; }
  .sidebar-head { justify-content: center; padding: 16px 16px 6px; }
}

/* Honor reduced-motion: no slide/width animation. */
@media (prefers-reduced-motion: reduce) {
  .sidebar, .main-content, .nav-scrim { transition: none; }
}

/* ===================== Mobile "best on desktop" notice ===================== */
.desktop-tool-notice { display: none; }
@media (max-width: 767.98px) {
  .desktop-tool-notice {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin: 12px 12px 16px;
    padding: 12px 14px;
    background: var(--info-bg);
    border: 1px solid var(--info-border);
    border-radius: var(--radius-md);
    color: var(--text-on-card);
    font-size: 0.86rem;
    line-height: 1.4;
  }
  .desktop-tool-notice__icon { flex: 0 0 auto; font-size: 1.1rem; line-height: 1.2; }
}
