/* =====================================================================
   NEXUS DASHBOARD — shared chrome
   Design tokens here MUST match the ones inlined in dashboard/calendar/
   index.html so a CSS edit in one place doesn't break the other.

   THEMING
   -------------------------------------------------------------------
   Three modes:
     - auto   (default): follow the OS via prefers-color-scheme
     - light  (manual)
     - dark   (manual)

   Theme is applied by setting data-theme="light" or "dark" on the
   <html> element. dashboard.js does this before paint (Nexus.applyTheme)
   reading nexus_theme from localStorage. If unset or "auto", the
   prefers-color-scheme media query controls it.

   The surface/text/line tokens swap with the theme. Brand accent
   (purple), event colours (blue/green/yellow/...), and semantic
   colours (success/danger) intentionally do NOT swap — they read
   correctly on both backgrounds and switching them would change
   the calendar's visual identity.
   ===================================================================== */

:root {
  /* Brand accents + semantic colours — same in both themes */
  --accent:        #B34DB4;
  --accent-soft:   rgba(179,77,180,0.18);
  --accent-hover:  #C661C7;
  --info:          #2F95FF;
  --danger:        #F87171;
  --success:       #34D399;
  --warning:       #FBBF24;

  /* Radii */
  --r-sm: 6px;
  --r:    10px;
  --r-lg: 16px;

  /* Font */
  --font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Display",
               "Inter", system-ui, "Segoe UI", Roboto, sans-serif;

  /* Layout */
  --nav-width: 220px;
}

/* DARK THEME — explicit + the prefers-color-scheme fallback */
:root,
:root[data-theme="dark"] {
  color-scheme: dark;

  /* Surfaces */
  --bg:            #0E0E10;
  --bg-elev:       #16161a;
  --bg-elev-2:     #1c1c21;
  --bg-input:      rgba(255,255,255,0.04);
  --nav-pill-bg:   rgba(28,28,34,0.82);   /* frosted mobile nav pill (dark) */

  /* Lines */
  --line:          rgba(255,255,255,0.10);
  --line-soft:     rgba(255,255,255,0.06);
  --line-strong:   rgba(255,255,255,0.18);

  /* Text */
  --text:          #ffffff;
  --text-soft:     rgba(255,255,255,0.68);
  --text-muted:    rgba(255,255,255,0.42);
  --text-dim:      rgba(255,255,255,0.28);

  /* Shadows — heavier in dark mode where ambient light is low */
  --shadow-soft:
    0 6px 18px rgba(0,0,0,0.32),
    0 0 0 1px rgba(255,255,255,0.04);
  --shadow-pop:
    0 24px 48px rgba(0,0,0,0.55),
    0 0 0 1px rgba(255,255,255,0.04),
    inset 0 1px 0 rgba(255,255,255,0.04);

  /* Overlay scrim — the modal/popover backdrop */
  --scrim:         rgba(0,0,0,0.55);
}

/* LIGHT THEME — the same tokens, different values.
   Apple's macOS light Calendar uses near-white surfaces with subtle
   gray separators; text is true-ish black at high contrast.
   The brand purple is unchanged — it pops on white the same way it
   pops on near-black. */
:root[data-theme="light"] {
  color-scheme: light;

  /* Surfaces — soft off-white tiers (NOT pure white) so cards on
     top can still feel raised via a slightly whiter elev tone. */
  --bg:            #F5F5F7;     /* page background */
  --bg-elev:       #FFFFFF;     /* cards, nav, popovers */
  --bg-elev-2:     #F9F9FB;     /* nested cards / selected segment */
  --bg-input:      rgba(0,0,0,0.03);
  --nav-pill-bg:   rgba(255,255,255,0.90);  /* frosted mobile nav pill (light) */

  /* Lines — black with low alpha so they sit on any surface */
  --line:          rgba(0,0,0,0.10);
  --line-soft:     rgba(0,0,0,0.06);
  --line-strong:   rgba(0,0,0,0.18);

  /* Text — true black tier for primary; alpha-blacks for hierarchy */
  --text:          #1a1a1c;
  --text-soft:     rgba(0,0,0,0.65);
  --text-muted:    rgba(0,0,0,0.45);
  --text-dim:      rgba(0,0,0,0.30);

  /* Shadows — much lighter, since they read on white */
  --shadow-soft:
    0 4px 12px rgba(0,0,0,0.08),
    0 0 0 1px rgba(0,0,0,0.04);
  --shadow-pop:
    0 16px 40px rgba(0,0,0,0.14),
    0 0 0 1px rgba(0,0,0,0.06);

  /* Scrim stays dark — it has to read as "behind" the modal */
  --scrim:         rgba(0,0,0,0.35);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; }

/* ---------------------------------------------------------------------
   APP SHELL — sidebar + main grid
   --------------------------------------------------------------------- */

.app-shell {
  display: grid;
  grid-template-columns: var(--nav-width) 1fr;
  min-height: 100vh;
  transition: grid-template-columns 0.22s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Collapsed nav state — triggered by JS toggling .nav-collapsed on .app-shell */
.app-shell.nav-collapsed {
  grid-template-columns: 64px 1fr;
}
.app-shell.nav-collapsed .nav {
  padding: 20px 8px;
  /* Don't set overflow:hidden here — it clips the account menu popup */
}
/* Hide text labels when collapsed */
.app-shell.nav-collapsed .nav-brand-text,
.app-shell.nav-collapsed .nav-account-info,
.app-shell.nav-collapsed .nav-item-label {
  display: none;
}
/* Center items when collapsed */
.app-shell.nav-collapsed .nav-item {
  justify-content: center;
  padding: 10px;
}
.app-shell.nav-collapsed .nav-brand {
  justify-content: center;
  padding: 4px 4px 20px;
  gap: 0;
}
/* When collapsed, drop the top profile photo — the collapse/expand chevron
   is all that's needed up top, and the account avatar stays at the bottom. */
.app-shell.nav-collapsed .nav-brand-avatar {
  display: none;
}
.app-shell.nav-collapsed .nav-collapse-btn {
  margin-left: 0;
}
.app-shell.nav-collapsed .nav-collapse-btn svg {
  transform: rotate(180deg);
}
.app-shell.nav-collapsed .nav-account-row {
  justify-content: center;
  padding: 8px 4px;
}
/* Collapse button */
.nav-collapse-btn {
  width: 26px; height: 26px;
  border: none; background: transparent;
  color: var(--text-muted); cursor: pointer;
  border-radius: 6px; display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; margin-left: auto;
  transition: background 0.12s, color 0.12s;
}
.nav-collapse-btn:hover { background: var(--line-soft); color: var(--text); }
.nav-collapse-btn svg { transition: transform 0.22s cubic-bezier(0.4,0,0.2,1); }

/* ---------------------------------------------------------------------
   SIDEBAR NAV
   --------------------------------------------------------------------- */

.nav {
  background: var(--bg-elev);
  border-right: 1px solid var(--line-soft);
  padding: 20px 14px;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  /* overflow: hidden was clipping the account menu popup.
     Use overflow: visible so the menu can escape the nav bounds.
     The collapse animation uses width transition, not overflow. */
  overflow: visible;
  transition: padding 0.22s cubic-bezier(0.4, 0, 0.2, 1);
  min-width: 0;
}

.nav-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 8px 20px;
  border-bottom: 1px solid var(--line-soft);
  margin-bottom: 14px;
  min-width: 0;
}
/* Avatar in the top-left brand area — shows the artist's profile photo
   when available (loaded async via /sync/pull). Until the photo arrives
   we show initials in a coloured circle so the layout doesn't flicker. */
.nav-brand-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-weight: 600;
  font-size: 13px;
  overflow: hidden;
  flex-shrink: 0;
}
.nav-brand-avatar img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.nav-brand-text {
  color: var(--text);
  font-weight: 600;
  font-size: 15px;
  letter-spacing: 0.005em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
  flex: 1;
}
/* Share button in the top-left brand header — copies the artist's public
   page link (flash / availability / waitlist) to the clipboard. */
.nav-brand-share {
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 8px;
  color: var(--text-soft);
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background 0.15s, transform 0.06s;
}
.nav-brand-share svg { width: 15px; height: 15px; }
.nav-brand-share:hover { color: var(--text); border-color: var(--accent); }
.nav-brand-share:active { transform: scale(0.92); }
.nav-brand-share.copied {
  color: #fff;
  background: var(--accent);
  border-color: var(--accent);
}

.nav-items {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: 8px;
  color: var(--text-soft);
  font-size: 13px;
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease;
}
.nav-item:hover {
  background: var(--bg-input);
  color: var(--text);
}
.nav-item.is-active {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
}
.nav-item.is-active .nav-item-label { font-weight: 600; }
.nav-item-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}
.nav-item-label {
  font-weight: 500;
}

.nav-account {
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid var(--line-soft);
}
.nav-account-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 8px;
  cursor: pointer;
  position: relative;
}
.nav-account-row:hover { background: var(--bg-input); }
.nav-account-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: #3a3a3f;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text);
  font-size: 11px;
  font-weight: 600;
  flex-shrink: 0;
  overflow: hidden;
}
.nav-account-avatar img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.nav-account-info {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1;
}
.nav-account-name {
  font-size: 12px;
  color: var(--text);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.nav-account-meta {
  font-size: 10px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Account dropdown */
.nav-account-menu {
  position: fixed;
  /* JS sets top/left at open time via setAccountMenuPos() */
  min-width: 180px;
  width: max-content;
  background: var(--bg-elev-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: var(--shadow-pop);
  padding: 6px;
  display: none;
  z-index: 9999;
}
.nav-account-menu.is-open { display: block; }
.nav-account-menu button {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  background: transparent;
  border: none;
  padding: 8px 10px;
  color: var(--text-soft);
  font-size: 13px;
  text-align: left;
  border-radius: 6px;
}
.nav-account-menu button:hover { background: var(--bg-input); color: var(--text); }
.nav-account-menu button.danger:hover { color: var(--danger); }

/* ---------------------------------------------------------------------
   MAIN CONTENT AREA
   --------------------------------------------------------------------- */

.main {
  min-width: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
}
.main-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 22px 28px;
  border-bottom: 1px solid var(--line-soft);
  background: var(--bg);
}
.main-title {
  margin: 0;
  font-size: 20px;
  font-weight: 600;
  color: var(--text);
}
.main-body {
  padding: 24px 28px;
  flex: 1;
  min-width: 0;
  width: 100%;
}

/* =====================================================================
   MOBILE — sidebar -> bottom tab bar
   ---------------------------------------------------------------------
   The default desktop grid puts a 220px sidebar to the left of the main
   content. On phones (<= 720px viewport) we:
     * collapse the grid to a single column
     * pin .nav to the BOTTOM of the screen as a horizontal tab bar
     * rearrange .nav internals so the brand + account row hide (the
       account row is reachable via the Settings tab) and only the
       nav items show, equally distributed
     * pad the main content's bottom by the height of the tab bar so
       page content doesn't slide under it
     * shrink page padding from 24/28 to 14/14 — desktop padding is
       too generous on narrow screens
   ===================================================================== */

:root {
  /* Used in the .main padding-bottom calc below; bumping the bar height
     here is the single source of truth. */
  --mobile-tabbar-height: 82px;
}

@media (max-width: 720px) {
  /* MOBILE LAYOUT — two-row grid: scrollable .main on top, nav as a real
     bottom row (NOT position:fixed). The DOM is:
        .app-shell > #nexus-nav > .nav   (the nav)
        .app-shell > .main               (the page)
     So we target #nexus-nav (the actual grid child), not .nav, when
     placing it into the grid track. Earlier rules used `.app-shell > .nav`
     which never matched because .nav is a grand-child, not a child. */
  html, body {
    height: 100%;
    overflow: hidden;          /* scroll inside .main, not the page */
    /* Belt-and-braces: nothing should ever push the viewport wider. */
    max-width: 100vw;
    overflow-x: hidden;
  }
  .app-shell {
    position: relative;             /* anchor for the floating nav overlay */
    grid-template-columns: 1fr;
    grid-template-rows: 1fr auto;   /* main, then nav */
    height: 100dvh;            /* dvh handles iOS address-bar resize */
    min-height: 100dvh;
    max-height: 100dvh;        /* hard cap so .main can't push the nav off */
    max-width: 100vw;
    overflow-x: hidden;
  }
  /* nav-collapsed adds 64px 1fr on desktop — override back to 1fr on mobile */
  .app-shell.nav-collapsed {
    grid-template-columns: 1fr;
  }
  /* main is the scroll container — page content scrolls here, nav stays put.
     overflow-x is ONLY clipped at the body/app-shell level, not here, because
     inner sections (.flash-cats) need horizontal scroll of their own. */
  .app-shell > .main {
    grid-row: 1;
    grid-column: 1;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    min-height: 0;             /* required for overflow inside a grid track */
    min-width: 0;              /* required so children can't expand it */
    width: 100%;
    max-width: 100vw;
  }
  /* The #nexus-nav wrapper floats OVER the scrolling content (not a solid
     row), so the frosted pill actually has page content behind it to blur.
     The transparent padding zone around the pill passes taps through to the
     content underneath. */
  .app-shell > #nexus-nav {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    z-index: 90;
    pointer-events: none;
  }
  .app-shell > #nexus-nav .nav-items { pointer-events: auto; }

  /* Calendar is full-bleed and height-sensitive: keep the bar as a solid row
     BENEATH it (not a floating overlay), so it can never cover the grid —
     the way it worked before the overlay change. Everywhere else the bar
     floats over content as frosted glass. */
  body.calendar-active .app-shell > #nexus-nav {
    position: static;
    grid-row: 2;
    grid-column: 1;
    z-index: auto;
    pointer-events: auto;
  }
  /* nav itself — a floating glass pill sitting in its own grid row */
  #nexus-nav > .nav {
    position: static;          /* override desktop sticky */
    height: auto;
    width: 100%;
    flex-direction: row;
    align-items: stretch;
    border-right: none;
    border-top: none;
    background: transparent;    /* the pill is the visual, not the whole row */
    padding: 8px
             max(18px, env(safe-area-inset-right, 0px))
             calc(16px + env(safe-area-inset-bottom, 0px))
             max(18px, env(safe-area-inset-left, 0px));
    z-index: 90;
  }

  /* Brand + account row are dead weight at the bottom of the screen.
     Brand identity belongs in the page header; account actions live
     inside Settings. Hide both. */
  .nav-brand,
  .nav-account {
    display: none !important;
  }

  /* Frosted floating pill holding the tabs */
  .nav-items {
    flex: 1;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 2px;
    height: 58px;
    padding: 0 8px;
    background: var(--nav-pill-bg);
    -webkit-backdrop-filter: blur(16px);
    backdrop-filter: blur(16px);
    border: 1px solid var(--line-soft);
    border-radius: 20px;
    overflow: hidden;   /* never let a long active label push past the screen */
    box-shadow: 0 14px 30px -14px rgba(40, 20, 60, 0.30),
                0 2px 6px rgba(20, 18, 30, 0.05);
  }
  .nav-item {
    flex: 0 0 auto;
    flex-direction: row;
    align-items: center;
    gap: 0;
    padding: 10px 6px;
    border-radius: 13px;
    min-width: 0;
    color: var(--text-muted);
    transition: padding 0.24s cubic-bezier(0.4, 0, 0.2, 1),
                color 0.2s ease,
                box-shadow 0.24s ease;
  }
  .nav-item:hover {
    background: transparent;  /* hover is meaningless on touch devices */
    color: var(--text-soft);
  }
  .nav-item.is-active {
    flex: 0 1 auto;
    background: linear-gradient(135deg, #E85BC4 0%, #B34DB4 48%, #7B3FD0 100%);
    color: #fff;
    padding: 10px 12px;
    box-shadow: 0 8px 16px -8px rgba(179, 77, 180, 0.6);
  }
  .nav-item-icon {
    width: 22px;
    height: 22px;
    flex-shrink: 0;
  }
  /* Label slides open on activation instead of popping in */
  .nav-item-label {
    max-width: 0;
    margin-left: 0;
    opacity: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: 12.5px;
    font-weight: 700;
    line-height: 1;
    transition: max-width 0.26s cubic-bezier(0.4, 0, 0.2, 1),
                margin-left 0.26s cubic-bezier(0.4, 0, 0.2, 1),
                opacity 0.2s ease;
  }
  .nav-item.is-active .nav-item-label {
    max-width: 82px;
    margin-left: 6px;
    opacity: 1;
  }
  @media (prefers-reduced-motion: reduce) {
    .nav-item,
    .nav-item-label { transition: none; }
  }

  /* (no extra padding needed at bottom — nav is now its own grid row,
     not a fixed overlay) */
  .main-header {
    padding: 14px 16px;
  }
  .main-title {
    font-size: 17px;
  }
  .main-body {
    padding: 16px 14px;
    min-width: 0;
    max-width: 100%;
  }
  /* Clear the floating nav so the last content can scroll above it.
     Calendar sets its own fixed height below, so it's excluded. */
  body:not(.calendar-active) .main-body {
    padding-bottom: calc(var(--mobile-tabbar-height) + env(safe-area-inset-bottom, 0) + 10px);
  }

  /* Calendar route: main-body should fill the grid row above the tab bar.
     Use flex:1 + the dvh cap rather than a calculated height — this is
     robust at every viewport size including iPad/small-laptop breakpoints. */
  body.calendar-active .main-body {
    height: calc(100dvh - var(--mobile-tabbar-height) - env(safe-area-inset-bottom, 0));
    max-height: calc(100dvh - var(--mobile-tabbar-height) - env(safe-area-inset-bottom, 0));
    flex: 1;
    min-height: 0;
  }
  body.calendar-active .app-shell {
    height: 100dvh;
    max-height: 100dvh;
    min-height: 0;
  }

  /* =====================================================================
     Tighter page furniture on mobile — the existing components default to
     comfortable desktop spacing; these overrides keep them usable when
     real estate is scarce.

     NOTE on cascade: per-component overrides for things defined in
     dashboard/index.html's inline <style> block (.wl-*, .flash-*,
     .client-*, .reply-*, etc.) live in that file, not here, because
     the inline block loads AFTER dashboard.css and would clobber any
     rules here without !important. We keep this file responsible for
     the shell-level concerns (nav, main, page padding, modals, forms).
     ===================================================================== */

  /* Top-of-view action rows (e.g. "+ New booking", search). Stack instead
     of overflowing the right edge. */
  .action-toolbar,
  .page-toolbar {
    flex-wrap: wrap;
    gap: 10px;
  }
  .action-toolbar .btn,
  .page-toolbar .btn {
    /* Full-width buttons read as primary CTAs on mobile and don't get
       truncated. Search inputs already use flex:1 so they expand. */
    width: 100%;
    justify-content: center;
  }
  /* Flash vault action toolbar gets denser treatment — four buttons stacked
     full-width is too much vertical chrome. Pair them up two-per-row. */
  .flash-action-toolbar .btn {
    width: calc(50% - 5px);
    flex: 0 0 calc(50% - 5px);
  }
  .flash-action-toolbar .spacer { display: none; }
  /* Exception: tab-style toggles should stay inline — they're a single
     control, not multiple actions. */
  .tab-group {
    width: 100%;
    overflow-x: auto;
  }

  /* Modals (booking edit, client detail, etc.) — give them more of the
     screen and let the body scroll. Without this they get clipped by
     the viewport on phones because they default to max-height: 80vh
     centered, leaving content inaccessible. */
  .modal-backdrop .modal,
  #modal-backdrop > div:not(#modal-close) {
    max-width: calc(100vw - 20px);
    width: calc(100vw - 20px);
    max-height: calc(100vh - 80px);
  }

  /* Forms: bigger inputs/touch targets and slightly smaller labels */
  .form-input,
  .form-select,
  .form-textarea {
    font-size: 16px;   /* prevents iOS Safari zoom on focus */
    padding: 12px;
  }
}

/* ---------------------------------------------------------------------
   BUTTONS
   --------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 14px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 500;
  border: 1px solid transparent;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
  white-space: nowrap;
}
.btn-primary {
  background: var(--accent);
  color: #fff;
}
.btn-primary:hover { background: var(--accent-hover); }
.btn-primary:disabled { background: #5a3a5b; cursor: not-allowed; }

.btn-secondary {
  background: transparent;
  border-color: var(--line);
  color: var(--text-soft);
}
.btn-secondary:hover {
  background: var(--bg-input);
  color: var(--text);
  border-color: var(--line-strong);
}

.btn-ghost {
  background: transparent;
  color: var(--text-soft);
}
.btn-ghost:hover { color: var(--text); }

.btn-block {
  width: 100%;
}

/* ---------------------------------------------------------------------
   FORM ELEMENTS
   --------------------------------------------------------------------- */

.form-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 14px;
}
.form-label {
  font-size: 12px;
  font-weight: 500;
  color: var(--text-soft);
  letter-spacing: 0.02em;
}
.form-input {
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 10px 12px;
  color: var(--text);
  font-size: 14px;
  font-family: inherit;
  transition: border-color 0.12s, background 0.12s;
}
.form-input:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--line-soft);
}
.form-input:disabled { opacity: 0.5; cursor: not-allowed; }

.form-error {
  font-size: 12px;
  color: var(--danger);
  margin-top: 4px;
  min-height: 16px;
}
.form-help {
  font-size: 12px;
  color: var(--text-muted);
}
.form-help a { color: var(--text-soft); text-decoration: underline; }
.form-help a:hover { color: var(--text); }

/* ---------------------------------------------------------------------
   TOAST
   --------------------------------------------------------------------- */

.toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  background: var(--bg-elev-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 12px 18px;
  font-size: 13px;
  color: var(--text);
  box-shadow: var(--shadow-pop);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s, transform 0.2s;
  z-index: 1000;
  max-width: 90vw;
}
.toast.is-show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
.toast.is-err { border-color: var(--danger); }
.toast.is-ok  { border-color: var(--success); }

/* ---------------------------------------------------------------------
   AUTH PAGES (login / signup / password)
   --------------------------------------------------------------------- */

.auth-page {
  min-height: 100vh;            /* fallback for browsers without dvh */
  min-height: 100dvh;           /* dynamic viewport — correct height under the iOS toolbar */
  display: flex;
  /* Centre the card with margin:auto (on .auth-card) rather than
     align-items:center. When the card is taller than the screen, flex
     centring would clip it at BOTH ends and trap content below the fold
     (the iOS "can't scroll to the button" bug). margin:auto centres when
     there's room and lets the page scroll when there isn't. */
  justify-content: center;
  padding: 40px 20px;
  padding-bottom: calc(40px + env(safe-area-inset-bottom));  /* clear the home indicator */
  background: var(--bg);
}
.auth-card {
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 36px 32px;
  width: 100%;
  max-width: 380px;
  margin: auto;                 /* scroll-safe vertical+horizontal centring */
  box-shadow: var(--shadow-soft);
}
.auth-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  justify-content: center;
  margin-bottom: 24px;
}
.auth-brand-mark {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  background: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-weight: 700;
  font-size: 16px;
}
.auth-brand-text {
  font-size: 18px;
  font-weight: 600;
  color: var(--text);
}
.auth-title {
  font-size: 22px;
  font-weight: 600;
  text-align: center;
  margin: 0 0 6px;
}
.auth-subtitle {
  font-size: 13px;
  color: var(--text-muted);
  text-align: center;
  margin: 0 0 28px;
}
.auth-footer {
  text-align: center;
  margin-top: 18px;
  font-size: 13px;
  color: var(--text-muted);
}
.auth-footer a {
  color: var(--text-soft);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.auth-footer a:hover { color: var(--text); }

/* ---------------------------------------------------------------------
   AUTH GATE (overlay on /dashboard/* pages when JWT is missing)
   --------------------------------------------------------------------- */

.auth-gate {
  position: fixed;
  inset: 0;
  background: rgba(14,14,16,0.92);
  backdrop-filter: blur(8px);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 9999;
}
.auth-gate.is-active { display: flex; }
.auth-gate-msg {
  text-align: center;
  padding: 28px;
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: 14px;
  max-width: 320px;
}
.auth-gate-msg h2 { margin: 0 0 8px; font-size: 18px; font-weight: 600; }
.auth-gate-msg p  { margin: 0 0 18px; color: var(--text-muted); font-size: 13px; }

/* =====================================================================
   ACCOUNT SETTINGS MODAL
   ---------------------------------------------------------------------
   Opened from the bottom-left account dropdown's "Account settings"
   item. Contains: Change password, Sign out, Delete account.
   Used to live in Settings → Account; moved here so account-level
   actions are reachable from every page without navigating away.
   ===================================================================== */
#nexus-acct-modal-bg {
  position: fixed; inset: 0;
  background: var(--scrim);
  backdrop-filter: blur(6px);
  display: flex; align-items: center; justify-content: center;
  z-index: 9999;
  padding: 20px;
  animation: nexus-acct-fadein 0.16s ease-out;
}
@keyframes nexus-acct-fadein {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.nexus-acct-modal {
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: 14px;
  width: 100%;
  max-width: 480px;
  max-height: 90vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow-pop);
}
.nexus-acct-modal-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 18px;
  border-bottom: 1px solid var(--line-soft);
  flex-shrink: 0;
}
.nexus-acct-modal-head h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: var(--text);
}
.nexus-acct-modal-close {
  width: 28px; height: 28px;
  border: none;
  background: transparent;
  color: var(--text-muted);
  font-size: 20px;
  cursor: pointer;
  border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
}
.nexus-acct-modal-close:hover {
  background: var(--line-soft);
  color: var(--text);
}
.nexus-acct-modal-body {
  padding: 16px 18px;
  overflow-y: auto;
  flex: 1;
}
.nexus-acct-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--line-soft);
}
.nexus-acct-row:last-child { border-bottom: none; }
.nexus-acct-row-text {
  flex: 1;
  min-width: 0;
}
.nexus-acct-row-text strong {
  display: block;
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 2px;
}
.nexus-acct-row-text span {
  display: block;
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.4;
}
.nexus-acct-btn {
  flex-shrink: 0;
  padding: 8px 14px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--bg-input);
  color: var(--text);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  font-family: inherit;
  transition: background 0.12s, border-color 0.12s;
}
.nexus-acct-btn:hover {
  background: var(--bg-elev-2);
  border-color: var(--line-strong);
}
.nexus-acct-btn-danger {
  flex-shrink: 0;
  padding: 8px 14px;
  border-radius: 8px;
  border: 1px solid rgba(248,113,113,0.3);
  background: transparent;
  color: var(--danger);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  font-family: inherit;
  transition: background 0.12s;
}
.nexus-acct-btn-danger:hover {
  background: rgba(248,113,113,0.08);
}
.nexus-acct-danger {
  margin-top: 18px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
}
.nexus-acct-danger-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--danger);
  margin-bottom: 4px;
}
@media (max-width: 480px) {
  .nexus-acct-row { flex-wrap: wrap; }
  .nexus-acct-btn, .nexus-acct-btn-danger { width: 100%; }
}
