/* We Are Brave — dashboard theme (dark) */

/* Brand typefaces (brand book: Stardos Stencil headlines, Tw Cen MT body) */
@font-face{font-family:"Stardos Stencil";src:url("fonts/StardosStencil-Regular.ttf") format("truetype");font-weight:400}
@font-face{font-family:"Stardos Stencil";src:url("fonts/StardosStencil-Bold.ttf") format("truetype");font-weight:700}
@font-face{font-family:"Tw Cen MT";src:url("fonts/TWCenM.TTF") format("truetype");font-weight:400;font-style:normal}
@font-face{font-family:"Tw Cen MT";src:url("fonts/TWCenMI.TTF") format("truetype");font-weight:400;font-style:italic}
@font-face{font-family:"Tw Cen MT";src:url("fonts/TWCenB.TTF") format("truetype");font-weight:700;font-style:normal}
@font-face{font-family:"Tw Cen MT";src:url("fonts/TWCenBI.TTF") format("truetype");font-weight:700;font-style:italic}

:root{
  /* Navy surfaces. Cards carry no fill of their own — they sit at page colour
     and are defined by --bo. Only the header steps up, to --nav. */
  --bg:#0D1B2A; --card:#0D1B2A; --card-2:#243447;
  --nav:#162A3E;
  --bo:#1D2F45; --bo-2:#2E4052;
  --tx:#F5F4F2; --tx-2:#A8A6A0;
  /* --tx-3 was #6B6B69, below the 4.5:1 AA floor for normal text.
     #8A8A86 measures 5.02:1 on the navy --bg and keeps a visible step
     below --tx-2, so the hierarchy survives. */
  --tx-3:#8A8A86;
  --co:#ED6E57; --bl:#00A3E0; --gr:#00C085; --pu:#A84ABA; --ye:#FFE05C;
  --ac:#00A3E0; /* lead accent — Decide Brave blue */
  /* Error text. --co is a band colour and must not move between themes,
     so failure states get their own token. */
  --danger:#ED6E57; --success:#00C085; --notice:#E8A33D;
  /* Sticky action bar. Held as rgba so backdrop-filter still has something
     to blur through. A step up from the page in dark, a step down in light —
     it should read as a distinct surface in both, never as a black slab. */
  --bar:rgba(22,42,62,.94);
  --shadow:rgba(0,0,0,.35);
}

/* Light theme. Same structure as dark — cards and inputs sit at page colour
   and are defined by --bo. The four band colours are deliberately NOT
   overridden: the score scale must read identically in both themes.
   --ac drops to #0087B8 because #00A3E0 measures only 2.87:1 here. Even at
   #0087B8 it is 3.94:1 — fine for buttons, chrome and large text, NOT for
   small body copy, which stays on --tx / --tx-2. */
:root[data-theme="light"]{
  --bg:#FDFBF7; --card:#FDFBF7; --card-2:#FDFBF7;
  --nav:#FDFBF7;
  --bo:#D6D2CA; --bo-2:#B9B6AF;
  --tx:#1A1A18; --tx-2:#4A4A48; --tx-3:#6B6B69;
  --ac:#0087B8;
  --focus:#0072B2;
  /* Status colours have to be re-derived, not inherited: #ED6E57 is 2.92:1
     on this background and #00C085 is 2.29:1, both unusable for the 12px
     audit-log rows. #C63F26 is 4.91:1 and #007A55 is 5.19:1, and each still
     reads as the same red / green. */
  --danger:#C63F26; --success:#007A55; --notice:#8A5510;
  --bar:rgba(239,233,222,.94);
  /* A .35 black shadow reads as grime on a cream page. */
  --shadow:rgba(26,26,24,.14);
}

*{box-sizing:border-box}
html,body{margin:0;background:var(--bg);color:var(--tx);
  font-family:"Tw Cen MT","Century Gothic","Inter","Helvetica Neue",system-ui,sans-serif;}
#react-entry-point,#_dash-app-content{background:var(--bg)}

.wrap{max-width:1500px;margin:0 auto;padding:0 36px 56px}

/* Header — rainbow accent strip echoing the BRAVE logo fan */
.brave-header{display:flex;align-items:center;justify-content:space-between;
  height:78px;padding:0 36px;background:var(--nav);position:relative;margin-bottom:30px}
.brave-header::after{content:"";position:absolute;left:0;right:0;bottom:0;height:3px;
  background:linear-gradient(90deg,var(--ye) 0%,var(--co) 28%,var(--pu) 52%,var(--gr) 76%,var(--bl) 100%)}
.brave-logo{background:#fff;border-radius:8px;padding:8px 18px;display:flex;align-items:center;
  cursor:pointer;transition:transform .12s}
.brave-logo:hover{transform:scale(1.02)}
.brave-logo img{height:46px;width:auto;display:block}
.brave-header-meta{text-align:right}
.brave-header-meta .t1{font-size:13px;font-weight:700;letter-spacing:.16em;
  text-transform:uppercase;color:var(--tx)}
.brave-header-meta .t2{font-size:11px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--tx-3);margin-top:2px}
.brave-header-right{display:flex;align-items:center;gap:24px}
.brave-nav{display:flex;gap:16px}
.brave-nav-link{color:var(--tx-2);font-size:12px;font-weight:600;letter-spacing:.05em;
  text-transform:uppercase;text-decoration:none;cursor:pointer}
.brave-nav-link:hover{color:var(--tx)}
.brave-user .t3{font-size:11px;color:var(--tx-3);letter-spacing:.04em}
.brave-user .t3.strong{color:var(--tx);font-weight:700}

/* Login page */
.login-wrap{min-height:calc(100vh - 100px);display:flex;align-items:center;justify-content:center;padding:30px}
.login-card{background:var(--card);border:1px solid var(--bo);border-radius:10px;
  padding:32px 30px;width:340px;border-top:3px solid var(--ac)}
.login-title{font-family:"Stardos Stencil",Georgia,serif;font-size:24px;font-weight:700;
  color:var(--tx);margin-bottom:18px;text-align:center}
.login-card .lab{font-size:12px;font-weight:700;letter-spacing:.05em;
  text-transform:uppercase;color:var(--tx-2);margin-bottom:6px;display:block}
/* Same treatment as every other field in the app: no border of its own, the
   surface does the work, and only focus draws an edge. The old 1px border
   made the sign-in boxes the only outlined inputs in the product. */
.login-card .inv-input{width:100%!important;display:block!important;
  background:var(--card-2)!important;color:var(--tx)!important;
  border:1px solid transparent;
  border-radius:6px;padding:11px 13px;font-size:14px;margin-bottom:4px;box-sizing:border-box}
.login-card .inv-input:hover{border-color:var(--bo)}
.login-card .inv-input:focus{outline:none;border-color:var(--ac)}

/* User management table */
.user-table{width:100%;border-collapse:collapse;background:var(--card);
  border:1px solid var(--bo);border-radius:6px;overflow:hidden;margin:8px 0 20px}
.user-table th{text-align:left;font-size:12px;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;padding:10px 14px;color:var(--tx-3);
  border-bottom:1px solid var(--bo);background:var(--card-2)}
.user-table td{padding:11px 14px;font-size:14px;color:var(--tx);
  border-bottom:1px solid var(--bo)}
.user-table tbody tr:last-child td{border-bottom:none}
.user-table tbody tr:hover td{background:var(--card-2)}
/* The visible chip stays compact, but the hit area is padded out to meet
   WCAG 2.2 SC 2.5.8 (24x24 minimum) with room to spare — this sits in a dense
   table row and it removes someone's access. */
.del-btn{background:transparent;color:var(--co);border:1px solid var(--co);
  border-radius:4px;padding:10px 14px;font-size:11px;font-weight:700;letter-spacing:.04em;
  text-transform:uppercase;cursor:pointer;transition:all .12s;
  min-height:44px;min-width:44px}
.del-btn:hover{background:var(--co);color:#fff}
.del-btn--danger{background:var(--co);color:#fff}
.del-btn--danger:hover{filter:brightness(1.12)}

/* Tabs */
.brave-tabs{border-bottom:1px solid var(--bo)!important;margin-bottom:18px}
.brave-tab{background:transparent!important;border:none!important;color:var(--tx-3)!important;
  font-weight:700!important;font-size:13px!important;letter-spacing:.04em;padding:12px 22px!important}
.brave-tab:hover{color:var(--tx-2)!important}
.brave-tab--sel{background:transparent!important;color:var(--tx)!important;
  border:none!important;border-bottom:3px solid var(--ac)!important}

/* Send invites */
/* No 780px cap. That was from the single-column era; when Send invites became
   a two-column layout the cap stayed, squeezing the grid to 316px + 440px so
   Client / Wave / Industry stacked instead of sitting in a row. .wrap governs. */
.inv-panel{max-width:none}
.inv-help{color:var(--tx-2);font-size:14px;margin:-2px 0 18px;max-width:700px;line-height:1.6}
.inv-row{display:flex;gap:16px;margin-bottom:14px;flex-wrap:wrap}
.inv-field{display:flex;flex-direction:column;gap:6px;min-width:0}
.inv-row .lab{
  font-size:12px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;
  color:var(--tx-3);
}
/* Dark like everything else — a white field on a near-black page was the
   harshest contrast on the screen, and the Subject box didn't match the
   Message box right beside it.
   height + padding-block:0 rather than padding + min-height: the old rule
   was 12+22.5+12 = 46.5px of content inside a 44px box, so the text sat
   ~2px low in every field. Browsers centre single-line input text on their
   own once nothing fights them for the vertical space. */
.inv-input{background:var(--card-2);border:1px solid var(--bo);border-radius:6px;
  color:var(--tx);height:44px;padding:0 14px;font-size:15px;line-height:normal;
  width:100%;display:block;box-sizing:border-box;
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  -webkit-text-fill-color:var(--tx);caret-color:var(--ac)}
.inv-input::placeholder{color:var(--tx-3);-webkit-text-fill-color:var(--tx-3)}
.inv-input:hover{border-color:var(--bo-2)}
.inv-input:focus{outline:none;border-color:var(--ac)}
.inv-textarea{width:100%;min-height:120px;background:var(--card-2);border:1px solid var(--bo);
  border-radius:6px;color:var(--tx);padding:11px 13px;font-size:14px;font-family:inherit;
  line-height:1.55;margin:6px 0 12px;resize:vertical}
.inv-textarea::placeholder{color:var(--tx-3)}
.inv-textarea:hover{border-color:var(--bo-2)}
.inv-textarea:focus{outline:none;border-color:var(--ac)}
.inv-status{display:inline-block;font-size:12px;font-weight:600;letter-spacing:.02em;
  padding:6px 12px;border-radius:4px;margin:-6px 0 16px}
.inv-status.ok{background:rgba(0,192,133,0.12);color:var(--gr);border:1px solid rgba(0,192,133,0.4)}
/* Text on --tx, not --ye: #FFE05C measures 1.26:1 on the light page. The
   yellow stays as the tint and border, which carry the meaning. */
.inv-status.warn{background:rgba(255,224,92,0.10);color:var(--tx);border:1px solid rgba(255,224,92,0.4)}
.inv-preview{font-size:12px;color:var(--tx-2);margin-bottom:14px;word-break:break-all}
.inv-results{margin-top:16px;font-size:14px;line-height:1.6}

/* Controls */
.controls{display:flex;align-items:center;gap:16px;margin-bottom:8px}
.controls .lab{font-size:12px;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--tx-2)}
.dl-btn{margin-left:auto;background:var(--ac);color:#fff;border:none;
  padding:11px 22px;border-radius:6px;font-weight:700;font-size:13px;cursor:pointer;
  letter-spacing:.03em;transition:filter .15s}
.dl-btn:hover{filter:brightness(1.08)}
.dl-status{min-height:18px;font-size:12px;color:var(--tx-2);margin:6px 0 18px}

/* dcc.Dropdown. react-select ships a white box with dark text, which the app
   used to force with `.brave-dd * {color:#1a1a1a}`. That left every dropdown
   white in both themes and out of step with the designed fields beside them.
   Each react-select part is themed instead, so the control matches .inv-input
   and the menu matches the surface it sits on. Class names are hashed
   (css-1a2b3c-control), hence the [class*=] matching. */
.brave-dd.dash-dropdown{
  background:var(--card-2)!important;
  border:1px solid var(--bo)!important;
  border-radius:6px!important;
  min-height:44px!important;
  color:var(--tx)!important;
}
.brave-dd.dash-dropdown:hover{border-color:var(--bo-2)!important}
.brave-dd.dash-dropdown:focus-visible{
  outline:3px solid var(--focus);outline-offset:2px;
}
.brave-dd .dash-dropdown-value{color:var(--tx)!important}
.brave-dd .dash-dropdown-placeholder{color:var(--tx-3)!important}
.brave-dd .dash-dropdown-trigger-icon{color:var(--tx-2)!important}

/* The menu renders in a portal at the end of <body>, so it is NOT inside
   .brave-dd — these cannot be nested under it. */
.dash-dropdown-content,
.dash-options-list.dash-dropdown-options{
  background:var(--card-2)!important;
  border:1px solid var(--bo)!important;
  border-radius:6px!important;
  color:var(--tx)!important;
}
.dash-dropdown-option,
.dash-options-list-option{
  background:transparent!important;color:var(--tx)!important;
}
.dash-dropdown-option:hover,
.dash-options-list-option:hover,
.dash-options-list-option[data-highlighted],
.dash-options-list-option[aria-selected="false"]:hover{
  background:var(--bo)!important;
}
.dash-options-list-option[aria-selected="true"]{
  background:var(--ac)!important;color:#fff!important;
}
.dash-dropdown-search,
.dash-dropdown-search-container input{
  background:var(--card-2)!important;color:var(--tx)!important;
  border:1px solid var(--bo)!important;
}

/* Client context header */
.context{display:flex;align-items:baseline;gap:18px;margin:4px 0 18px;flex-wrap:wrap}
.context .ctx-name{font-family:"Stardos Stencil",Georgia,serif;font-size:30px;
  font-weight:700;color:var(--tx);letter-spacing:.01em}
.ctx-chips{display:flex;gap:8px;flex-wrap:wrap}
.chip{font-size:12px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;
  color:var(--tx-2);background:var(--card-2);border:1px solid var(--bo);
  border-radius:999px;padding:4px 12px}

/* KPI cards */
.kpis{display:flex;gap:16px;flex-wrap:wrap;margin-bottom:8px}
.kpi{flex:1;min-width:170px;background:var(--card);border:1px solid var(--bo);
  border-left:3px solid var(--ac);border-radius:6px;padding:16px 20px;
  transition:transform .12s ease, border-color .15s ease}
.kpi:hover{transform:translateY(-2px)}
/* colour-cycle the KPI accents through the brand palette */
.kpis .kpi:nth-child(1){border-left-color:var(--bl)}
.kpis .kpi:nth-child(2){border-left-color:var(--gr)}
.kpis .kpi:nth-child(3){border-left-color:var(--ye)}
.kpis .kpi:nth-child(4){border-left-color:var(--pu)}

/* Hero row: gauge + KPIs */
.hero{display:flex;gap:16px;flex-wrap:wrap;margin-bottom:8px}
.hero-gauge{flex:0 0 330px;min-width:300px}
.hero-kpis{flex:1;align-content:flex-start}
.kpi .lab{font-size:12px;font-weight:700;letter-spacing:.07em;
  text-transform:uppercase;color:var(--tx-3)}
.kpi .val{font-family:"Tw Cen MT","Century Gothic",sans-serif;font-size:32px;font-weight:700;
  margin-top:4px;line-height:1.05}
.kpi .sub{font-size:13px;color:var(--tx-2);margin-top:3px}

/* Band legend */
.band-legend{display:flex;gap:18px;flex-wrap:wrap;margin:-2px 0 12px;padding-left:11px}
.band-legend .leg{font-size:12px;color:var(--tx-2);display:flex;align-items:center;gap:7px}
.band-legend .dot{width:9px;height:9px;border-radius:2px;display:inline-block}

/* Section labels + chart cards */
.sect{font-size:13px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--tx-2);margin:28px 0 10px;padding-left:11px;border-left:3px solid var(--ac)}
.grid{display:flex;gap:16px;flex-wrap:wrap}
.panel{flex:1;min-width:430px;background:var(--card);border:1px solid var(--bo);
  border-radius:8px;padding:8px 8px 2px;transition:border-color .15s ease}
.panel:hover{border-color:var(--bo-2)}
.panel.full{flex-basis:100%}

/* Empty / loading states */
.empty{color:var(--tx-3);padding:70px 0;text-align:center;font-size:14px}
.foot{margin-top:34px;padding-top:16px;border-top:1px solid var(--bo);
  font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--tx-3)}

/* Dash loading spinner colour */
._dash-loading-callback,.dash-spinner *{color:var(--ac)!important}


/* ---------------------------------------------------------------------------
   Accessibility foundations
   --------------------------------------------------------------------------- */

/* Focus ring. The browser default is a 1px #005FCC outline, near-invisible on
   this near-black background and a WCAG 2.2 SC 2.4.11 failure. :focus-visible
   so a mouse click doesn't leave a ring behind, but keyboard focus always
   does. #4EC3F7 clears 3:1 against both --bg and --card. */
:root{ --focus:#4EC3F7 }

*:focus{ outline:none }
*:focus-visible{
  outline:3px solid var(--focus);
  outline-offset:2px;
  border-radius:4px;
}
/* Dash renders some controls as nested divs where the ring would be clipped by
   the parent's overflow — hoist those so the ring is never cut off. */
.brave-dd:focus-within,.inv-field:focus-within{ overflow:visible }

/* Skip link — first focusable element on every page, off-screen until focused. */
.skip-link{
  position:absolute; left:-9999px; top:0; z-index:1000;
  background:var(--ac); color:#fff; font-weight:700;
  padding:12px 20px; border-radius:0 0 6px 0; text-decoration:none;
}
.skip-link:focus{ left:0 }

/* Respect a reduced-motion preference: kill transitions, the loading dots and
   Plotly's chart-entry animation rather than merely shortening them. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
    scroll-behavior:auto !important;
  }
}

/* Hidden from sight, still read by assistive tech. Used for table captions and
   the route-change announcer. */
.sr-only{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;
}

/* ============================================================
   Responsive / alignment fixes
   Selectors remapped to this app's actual classes: the tab strip is
   .brave-tabs/.brave-tab/.brave-tab--sel (not .tab-parent/.tab), the invite
   controls live in .inv-panel (not .tab-content), the recipient grid is a
   .user-table (there is no .recipient-row), and dcc.Dropdown renders
   .brave-dd/.dash-dropdown (not react-select's .Select-control).
   ============================================================ */

/* 1. Header shares the content column. .wrap is max-width 1500px + 36px
   padding; the header was full-bleed, so the logo never lined up with the
   dashboard below it. Keeps the full-width background rule intact. */
.brave-header{ padding-inline:max(36px, calc((100% - 1500px) / 2 + 36px)) }

/* 2. Header stops colliding with the logo. min-width:0 is what lets the
   right-hand block shrink instead of forcing the page to 667px. */
.brave-header{ flex-wrap:wrap; align-items:center; gap:12px 32px }
.brave-header-right{
  display:flex; flex-wrap:wrap; align-items:center; justify-content:flex-end;
  gap:12px 24px; min-width:0; flex:1 1 auto;
}
.brave-header-meta,.brave-header-meta .t1,.brave-header-meta .t2,
.brave-user{ min-width:0 }
.brave-user{ white-space:nowrap }

/* 3. Panels stop overflowing. Was a hard min-width:430px floor, which forced
   horizontal scroll below ~502px. */
.panel,.panel.full,.panel.hero-gauge{ min-width:min(430px,100%) }
.hero-gauge{ flex:1 1 330px }
.kpi{ min-width:min(170px,100%) }
.inv-field{ min-width:min(220px,100%) }

/* 4. Dead space under the KPI cards. */
.hero{ align-items:stretch }
.hero-kpis{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(170px,1fr));
  gap:16px; align-content:stretch;
}
.hero-kpis .kpi{ height:100% }

/* 5. Charts actually fluid. Plotly writes inline widths, hence !important.
   min-height stops a height:None figure collapsing to zero. */
.dash-graph,.js-plotly-plot,.js-plotly-plot .plot-container,
.js-plotly-plot .svg-container{ width:100% !important }
.js-plotly-plot .main-svg{ overflow:visible }
.dash-graph{ min-height:260px }
.hero-gauge .dash-graph{ min-height:300px }

/* 6. Invite inputs ignored their container — HTML's default size=20 pins a
   text input to ~183px, which clipped the Client placeholder even at 1920px. */
.inv-panel input[type="text"],.inv-panel input[type="email"],
.inv-panel input[type="date"],.inv-panel input:not([type]){
  width:100%; box-sizing:border-box;
}

/* 7. One baseline for every control on Send invites. Inputs were 18px content
   height against 34px dropdown buttons, so the dropdowns sat ~10px high. */
.inv-panel input[type="text"],.inv-panel input[type="email"],
.inv-panel input[type="date"],.inv-panel .brave-dd,
.inv-panel .dash-dropdown{
  min-height:40px; font-size:15px; box-sizing:border-box; vertical-align:middle;
}
.inv-panel .brave-dd,.inv-panel .dash-dropdown{ display:block }
/* recipients grid: align the email cell and its dropdown on a shared baseline */
.inv-panel .user-table td{ vertical-align:middle }

/* 8. Breakpoints — there were none at all. */
@media (max-width:1200px){ .hero{ flex-wrap:wrap } }
@media (max-width:960px){
  .brave-header{ flex-direction:column; align-items:flex-start; gap:12px }
  .brave-header-right{ justify-content:flex-start; width:100% }
  .brave-header-meta{ text-align:left }
}
@media (max-width:760px){
  .panel,.panel.full,.panel.hero-gauge,.kpi{ min-width:100% }
  .hero{ flex-direction:column }
  .hero-kpis{ grid-template-columns:1fr }
  /* stacked tabs: underline the active tab, not the whole row */
  .brave-tabs .brave-tab{ border-bottom:0 }
  .brave-tabs .brave-tab--sel{ border-bottom:3px solid var(--ac) }
  /* the two admin tables scroll inside themselves rather than the page */
  .user-table{ display:block; overflow-x:auto; -webkit-overflow-scrolling:touch }
}
@media (max-width:480px){
  .wrap{ padding-inline:16px }
  .brave-header{ padding-inline:16px }
  .controls{ flex-direction:column; align-items:stretch }
  .controls .brave-dd,.controls .dl-btn{ width:100% !important }
  .dl-btn{ min-height:44px }
}

/* ============================================================
   Send invites — three steps, side-by-side preview, sticky bar
   Uses the app's own tokens rather than hardcoded hexes, so the
   accent stays in step with the rest of the theme.
   ============================================================ */
/* Flat sections on the page, as drawn — the steps are not cards. Only the
   recipient table and the preview carry a surface of their own. */
.inv-step{ padding:0; margin:0 0 30px; }
.inv-step--form{ min-width:0 }

/* Step 3 and its preview sit side by side; steps 1 and 2 run full width. */
.inv-split{
  display:grid; grid-template-columns:minmax(0,1fr) minmax(320px,560px);
  gap:32px; align-items:start;
}
@media (max-width:1100px){ .inv-split{ grid-template-columns:1fr } }
.inv-step-head{display:flex;align-items:center;gap:12px;margin-bottom:6px}
.inv-step-num{
  display:grid;place-items:center;width:26px;height:26px;border-radius:50%;
  background:var(--ac);color:#fff;font-size:13px;font-weight:700;flex:0 0 auto;
}
.inv-step-title{
  font-size:17px;margin:0;letter-spacing:0;text-transform:none;
  font-family:"Tw Cen MT",sans-serif;font-weight:700;color:var(--tx);
}
.inv-chip{
  /* Beside the title, not margin-left:auto — that was fine while the panel
     was 780px wide, but the steps now run the full page and it flew to the
     far edge, detached from the heading it belongs to. */
  font-size:13px;padding:4px 11px;border-radius:999px;
  background:var(--card-2);color:var(--tx-2);white-space:nowrap;
}
.inv-help{color:var(--tx-3);font-size:13px;line-height:1.5;max-width:68ch}
.inv-help--privacy{border-left:2px solid var(--bo);padding-left:12px}
.inv-help code{
  background:var(--card-2);border:1px solid var(--bo);border-radius:4px;
  padding:1px 5px;font-size:12px;color:var(--tx-2);
}

/* Step 1 — fixed widths taken from the design (300 / 185 / 300), left
   grouped rather than stretched across the full width. */
.inv-row{display:flex;flex-wrap:wrap;gap:16px;align-items:flex-end;margin:16px 0 8px}
.inv-field--client{flex:0 0 300px}
.inv-field--wave{flex:0 0 185px}
.inv-field--industry{flex:0 0 300px}
.inv-field--other{flex:0 0 260px}

/* Step 3 — editor and preview side by side, so the message is never the
   last thing you see. Falls back to stacked on narrow screens. */
.inv-email-grid{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:24px;margin-top:16px;
}
.inv-email-edit{display:flex;flex-direction:column;gap:6px;min-width:0}
.inv-preview-label{
  font-size:12px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--tx-3);margin-bottom:8px;
}
/* White, because that's what an inbox looks like — the point is to show what
   lands, not to match the dashboard. */
.inv-preview{
  background:#fff;color:#1a1a1a;border-radius:8px;padding:24px;min-height:260px;
  font-family:Helvetica,Arial,sans-serif;font-size:15px;line-height:1.55;
}
.inv-preview p{margin:0 0 12px}
.pv-subject{font-weight:700;font-size:16px;margin-bottom:4px;color:#1a1a1a}
.pv-from{
  color:#666;font-size:12px;margin-bottom:18px;padding-bottom:14px;
  border-bottom:1px solid #e6e6e6;line-height:1.5;
}
.pv-cta{
  display:inline-block;margin-top:8px;padding:12px 22px;background:var(--ac);
  color:#fff;border-radius:6px;font-weight:700;
}
.pv-note{color:#888;font-size:12px;margin-top:18px}
@media (max-width:900px){ .inv-email-grid{grid-template-columns:1fr} }

/* Validation — collapses entirely when there's nothing to say. */
.inv-validation:empty{display:none}
.inv-validation{
  margin-top:12px;padding:10px 14px;border-radius:8px;font-size:13px;
  background:rgba(237,110,87,.12);border-left:3px solid var(--co);color:var(--tx-2);
}

/* Sticky action bar — states the consequence before you commit. */
/* Pinned just under the header rather than the foot of the page. The form is
   long enough that the Send button spent most of its life off-screen, so you
   scrolled to the bottom to send and back to the top to read the result. It
   now travels with you. 78px clears the sticky header above it. */
.inv-actionbar{
  position:sticky;top:78px;z-index:20;display:flex;align-items:center;
  justify-content:space-between;gap:20px;padding:14px 24px;margin:0 0 22px;
  background:var(--bar);backdrop-filter:blur(8px);
  border:1px solid var(--bo);border-radius:12px;flex-wrap:wrap;
  box-shadow:0 4px 14px var(--shadow);
}
.inv-summary{font-size:14px;color:var(--tx-2)}
.inv-summary strong{color:var(--tx)}
.inv-send-area,.inv-confirm-pair{display:flex;gap:10px;align-items:center}

.btn{
  border:0;border-radius:8px;padding:0 20px;height:44px;font-weight:700;
  font-size:14px;cursor:pointer;font-family:"Tw Cen MT",sans-serif;
}
.btn--primary{background:var(--ac);color:#fff}
.btn--primary:hover{filter:brightness(1.08)}
.btn--primary:disabled{background:var(--card-2);color:var(--tx-3);cursor:not-allowed}
.btn--ghost{background:transparent;color:var(--ac);border:1px solid var(--bo-2)}
.btn--ghost:hover{border-color:var(--ac)}
.btn--sm{height:34px;font-size:13px;padding:0 14px}

@media (max-width:600px){
  .inv-step{padding:18px 16px}
  .inv-actionbar{flex-direction:column;align-items:stretch}
  .inv-send-area,.inv-confirm-pair{width:100%}
  .inv-send-area .btn,.inv-confirm-pair .btn{flex:1}
}


/* ============================================================
   Send invites — two columns, dark fields, token buttons
   ============================================================ */

/* .inv-layout is gone — the page-height sticky column was replaced by
   .inv-split, which pairs the preview with step 3 only, as designed. */
.inv-side{min-width:0}
.inv-side .inv-preview{min-height:0}

/* Step 3 no longer splits internally — the preview lives in the side column. */
.inv-email-grid{display:block}

/* Token buttons. Typing {{client}} by hand is the sort of thing that goes
   wrong silently; these insert it for you. */
.inv-tokens{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin:6px 0 4px}
.inv-token{
  background:rgba(0,163,224,.14);border:1px solid rgba(0,163,224,.45);
  color:var(--ac);border-radius:999px;padding:5px 12px;font-size:12px;
  font-weight:700;cursor:pointer;font-family:"Tw Cen MT",sans-serif;
  letter-spacing:.02em;min-height:30px;
}
.inv-token:hover{background:rgba(0,163,224,.26)}
.inv-tokens-label{font-size:12px;color:var(--tx-3);margin-right:2px}

/* Branded email preview */
.pv-head{
  background:var(--bg);border-radius:8px 8px 0 0;padding:18px 24px;
  margin:-24px -24px 20px;display:flex;align-items:center;
}
.pv-logo{height:26px;width:auto;display:block}

/* ── Theme toggle ─────────────────────────────────────────────────────────
   Sun · pill · moon, as drawn in the header. 44px tall so it clears the
   24x24 minimum target size (WCAG 2.2 SC 2.5.8) even though the pill
   itself is smaller. */
.theme-toggle{
  display:flex;align-items:center;gap:7px;
  background:none;border:0;cursor:pointer;
  padding:0 10px;height:44px;margin-left:18px;
  color:var(--tx-3);font-size:12px;line-height:1;
  border-radius:999px;
}
.theme-toggle:hover{ color:var(--tx-2) }
.theme-toggle__track{
  position:relative;width:34px;height:18px;border-radius:999px;
  background:var(--ac);transition:background .16s ease;
}
.theme-toggle__track::after{
  content:"";position:absolute;top:2px;left:2px;
  width:14px;height:14px;border-radius:50%;
  background:var(--bg);transition:transform .16s ease;
}
/* Light = knob to the right. */
:root[data-theme="light"] .theme-toggle__track::after{ transform:translateX(16px) }
:root[data-theme="light"] .theme-toggle__track{ background:var(--bo-2) }

@media (prefers-reduced-motion: reduce){
  .theme-toggle__track,.theme-toggle__track::after{ transition:none }
}

/* Chrome paints its own background on autofilled fields, which showed as a
   pale block inside the dark field on the sign-in form. There is no property
   to turn it off — the standard trick is an inset shadow large enough to
   cover the field, plus text-fill-color for the text itself. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active{
  -webkit-box-shadow:0 0 0 1000px var(--card-2) inset !important;
  -webkit-text-fill-color:var(--tx) !important;
  caret-color:var(--tx);
  border:1px solid var(--bo) !important;
  transition:background-color 9999s ease-in-out 0s;
}

/* ── Token chips inside the message editor ────────────────────────────────
   The backdrop and the textarea must share EVERY metric that affects where
   a glyph lands — font, size, line-height, padding, border width, wrapping.
   Any mismatch shows up as drifting text. */
.inv-editor{ position:relative; margin:6px 0 12px }
.inv-editor .inv-textarea{ margin:0 }
.inv-editor__backdrop,
.inv-textarea--chips{
  font-family:inherit; font-size:14px; line-height:1.55;
  padding:11px 13px; border:1px solid transparent; border-radius:6px;
  white-space:pre-wrap; overflow-wrap:break-word; word-break:normal;
  letter-spacing:normal;
}
.inv-editor__backdrop{
  position:absolute; inset:0; z-index:0; overflow:hidden;
  color:var(--tx); pointer-events:none;
  background:var(--card-2); border-color:var(--bo);
}
/* FAIL SAFE. By default this is an ordinary, fully visible textarea and the
   backdrop is hidden. Only once the script has actually painted the backdrop
   does it add .chips-on, which hands the glyphs over to that layer. If the
   callback never runs, you get a plain textarea -- never invisible text. */
.inv-editor__backdrop{ display:none }
.inv-editor.chips-on .inv-editor__backdrop{ display:block }
.inv-textarea--chips{ position:relative; z-index:1 }
.inv-editor.chips-on .inv-textarea--chips{
  background:transparent !important;
  color:transparent !important;
  -webkit-text-fill-color:transparent;
  caret-color:var(--tx);
}
.inv-textarea--chips::selection{ background:rgba(0,163,224,.35) }
.inv-editor:hover .inv-editor__backdrop{ border-color:var(--bo-2) }
.inv-editor:focus-within .inv-editor__backdrop{ border-color:var(--ac) }

/* The chip must occupy EXACTLY the width of the raw token text, or every
   character after it shifts and the caret stops matching what is drawn.
   So: padding cancelled by equal negative margin, and an inset shadow
   instead of a border (a border would add 2px of advance). font-weight
   stays inherited for the same reason — bold is wider. */
.inv-editor__backdrop .tok{
  background:rgba(0,163,224,.16);
  box-shadow:inset 0 0 0 1px rgba(0,163,224,.45);
  border-radius:999px;
  padding:2px 6px; margin:0 -6px;
  color:var(--ac);
  white-space:nowrap;
}

/* ── Disclosure sections (Backup, Audit log) ──────────────────────────────
   Native <details>, so it opens with no callback and is keyboard-operable
   without any custom handling. */
.disclosure{
  border:1px solid var(--bo); border-radius:10px;
  margin-top:20px; background:var(--card);
}
.disclosure__head{
  list-style:none; cursor:pointer;
  display:flex; align-items:center; gap:10px;
  padding:16px 20px; min-height:44px;
  font-family:"Stardos Stencil",Georgia,serif;
  font-size:17px; font-weight:700; color:var(--tx);
}
.disclosure__head::-webkit-details-marker{ display:none }
.disclosure__head::before{
  content:"›"; display:inline-block;
  font-family:"Tw Cen MT",sans-serif; font-size:20px; line-height:1;
  color:var(--ac); transition:transform .15s ease;
}
.disclosure[open] .disclosure__head::before{ transform:rotate(90deg) }
.disclosure__head:hover{ color:var(--tx) }
.disclosure__head:focus-visible{
  outline:3px solid var(--focus); outline-offset:-3px; border-radius:10px;
}
.disclosure__body{ padding:0 20px 20px }
.disclosure__body .inv-help{ margin-top:0 }

@media (prefers-reduced-motion: reduce){
  .disclosure__head::before{ transition:none }
}

/* ── Recipient grid ───────────────────────────────────────────────────────
   A spreadsheet, not a form. The cell IS the field: no border or fill of its
   own, so ten rows read as one surface instead of ten stacked boxes. The
   row separator does the structural work; focus is what draws a box. */
.inv-grid{
  width:100%; max-width:900px; border-collapse:separate; border-spacing:0;
  margin-top:12px; border:1px solid var(--bo); border-radius:8px;
  overflow:hidden; background:var(--card);
}
.inv-grid th{
  text-align:left; font-size:12px; font-weight:700; letter-spacing:.08em;
  text-transform:uppercase; color:var(--tx-3);
  padding:11px 14px; background:var(--card-2);
  border-bottom:1px solid var(--bo);
}
.inv-grid td{ padding:0; border-bottom:1px solid var(--bo) }
.inv-grid tbody tr:last-child td{ border-bottom:none }
.inv-grid tbody tr:hover td{ background:var(--card-2) }

/* Fields fill their cell edge to edge and stay invisible until used. */
.inv-cell-input,
.inv-grid .brave-dd.dash-dropdown{
  width:100%!important; height:42px!important; min-height:42px!important;
  background:transparent!important; border:0!important; border-radius:0!important;
  color:var(--tx)!important; font-size:14px;
  padding:0 14px!important; box-shadow:none!important;
}
.inv-cell-input{
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  -webkit-text-fill-color:var(--tx); caret-color:var(--ac);
  display:block; box-sizing:border-box;
}
.inv-cell-input::placeholder{ color:var(--tx-3); -webkit-text-fill-color:var(--tx-3) }
.inv-cell-input:focus,
.inv-grid .brave-dd.dash-dropdown:focus-visible{
  outline:none;
  background:var(--card-2)!important;
  box-shadow:inset 0 0 0 2px var(--ac)!important;
}
/* Vertical rule between the two columns, so the pair still reads as a grid. */
.inv-grid__cell--sen{ border-left:1px solid var(--bo) }

/* ── Sticky header ────────────────────────────────────────────────────────
   Stays put while the page scrolls. Sits above the sticky preview column. */
.brave-header{ position:sticky; top:0; z-index:50 }

/* ── Scroll affordance ────────────────────────────────────────────────────
   A badge in the bottom-right corner rather than a full-width fade, which
   was too quiet to notice. Hidden once the page is within 24px of the
   bottom, and never shown at all when the page does not scroll. */
.scroll-hint{
  position:fixed; right:28px; bottom:28px; z-index:45;
  display:flex; flex-direction:column; align-items:center; gap:6px;
  pointer-events:none; opacity:1; transition:opacity .22s ease, transform .22s ease;
}
.scroll-hint[data-at-end="1"]{ opacity:0; transform:translateY(8px) }
.scroll-hint__pill{
  display:grid; place-items:center;
  width:58px; height:58px; border-radius:50%;
  background:var(--card-2); border:2px solid var(--ac);
  box-shadow:0 6px 20px var(--shadow);
  color:var(--ac); font-size:0;
}
.scroll-hint__pill::after{
  content:"⌄"; font-size:34px; line-height:1;
  position:relative; top:-7px;
  animation:scroll-nudge 1.6s ease-in-out infinite;
}
.scroll-hint__label{
  font-size:10px; font-weight:700; letter-spacing:.14em; text-transform:uppercase;
  color:var(--tx-2);
  background:var(--bar); border-radius:999px; padding:3px 10px;
}
@keyframes scroll-nudge{
  0%,100%{ transform:translateY(-2px); opacity:.6 }
  50%    { transform:translateY(4px);  opacity:1 }
}
@media (prefers-reduced-motion: reduce){
  .scroll-hint__pill::after{ animation:none }
  .scroll-hint{ transition:none }
}

/* Reminders — the pick column stays narrow so the addresses lead. */
.inv-grid .rem-selectall label,
.inv-grid .rem-pick label{ display:flex; align-items:center; gap:6px; margin:0 }
.inv-grid .rem-selectall{ font-size:12px; font-weight:700; letter-spacing:.06em;
  text-transform:uppercase; color:var(--tx-3) }
.inv-grid th:first-child,.inv-grid td:first-child{ width:120px; padding-left:14px }
.inv-grid td:nth-child(2){ padding:11px 14px; font-size:13px }
.inv-grid td:nth-child(3){ padding:11px 14px; font-size:12px; white-space:nowrap }
.inv-grid input[type="checkbox"]{ width:17px; height:17px; accent-color:var(--ac);
  cursor:pointer }
.inv-grid input[type="checkbox"]:disabled{ cursor:not-allowed; opacity:.4 }

/* Client field with a clear button. The datalist filters itself to whatever
   is typed, so emptying the box is how you get the full list back. */
.field-with-clear{ position:relative; display:block }
.field-with-clear .inv-input{ padding-right:40px }
.field-clear{
  position:absolute; right:6px; top:50%; transform:translateY(-50%);
  width:32px; height:32px; border:0; border-radius:6px;
  background:transparent; color:var(--tx-3); cursor:pointer;
  font-size:19px; line-height:1;
}
.field-clear:hover{ color:var(--tx); background:var(--bo) }
.field-clear:focus-visible{ outline:3px solid var(--focus); outline-offset:1px }

/* The count that sits immediately above a list. Reads as a statement, not a
   decorative pill — it is the number you check before acting on the list
   below it, so it gets real weight and the primary text colour. */
.count-line{
  font-size:15px; font-weight:700; color:var(--tx);
  margin:0 0 10px; display:flex; align-items:center; gap:9px;
}
.count-line::before{
  content:""; width:4px; height:17px; border-radius:2px;
  background:var(--ac); flex:0 0 auto;
}
.count-line:empty{ display:none }


/* Dash's Tabs wrapper sets overflow:hidden, and a sticky descendant cannot
   stick inside a clipped ancestor — which is why the send bar stayed put. */
.tab-parent, .tab-content{ overflow:visible !important }

/* dcc.Input renders <div class="dash-input-container …"><input
   class="dash-input-element">. Whatever className you pass lands on the
   WRAPPER, and the inner input keeps a border and background of its own —
   which is the box-inside-a-box on the sign-in fields. The sign-in inputs
   carry no className at all, so scoping this to .inv-input missed them
   entirely. Target the Dash classes directly and it covers every input in
   the app. */
.dash-input-container .dash-input-element,
.dash-input .dash-input-element{
  width:100% !important; border:0 !important; outline:none !important;
  background:transparent !important; box-shadow:none !important;
  color:inherit; font:inherit; padding:0; margin:0;
  -webkit-text-fill-color:currentColor;
}
.dash-input-container .dash-input-element:focus{ outline:none !important }
/* The wrapper is the field: it draws the edge, on focus only. */
.login-card .dash-input-container:focus-within{ border-color:var(--ac) !important }
.login-card .dash-input-container:hover{ border-color:var(--bo) !important }

/* Send bar: status and the reasons you cannot send yet, beside the button. */
.inv-actionbar__text{ display:flex; flex-direction:column; gap:3px; min-width:0 }
/* Amber, not red. These appear before you have done anything wrong — they
   are telling you what is still needed, not reporting a failure. */
.inv-validation{ font-size:13px; color:var(--notice); line-height:1.45 }
.inv-validation > div{ display:block }
.inv-validation:empty{ display:none }

/* The sender banner sits inside the send bar, so it needs to be compact. */
.inv-actionbar__text .inv-status{ margin:0 0 2px; font-size:12px; padding:2px 8px }
