/* ══════════════════════════════════════════════════════════════════════
   zmove.ai portal — token pass (drop-in replacement for
   zmove-portal/public/css/app.css)

   SCOPE: values only. Every class name, selector, and structural rule
   from the original file is preserved, so no .ejs view needs editing.
   Nothing here changes nav links, routes, tables, forms, or copy.

   WHAT CHANGED
   1. Space Grotesk -> IBM Plex Sans (+ Plex Mono for labels/figures).
   2. Nav: dark navy gradient + SVG noise -> light neutral, navy ink,
      brand-gradient hairline. (Set $nav-dark below to keep it dark.)
   3. Metric cards: four rainbow nth-child gradients -> one neutral
      white card. Attention is carried by Z Gold only.
   4. Blue is reserved for actions. Gold is reserved for attention.
      Teal/purple/coral decorative uses are retired.
   5. Warm sandstone surfaces + warm hairlines, matching the workspace.
   ══════════════════════════════════════════════════════════════════════ */

@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap');

:root {
  /* ── Brand (zmove.ai style guide) ──
     Canonical source is now src/lib/brand.js (see BRAND.md) — these
     four literals (--navy/--sky/--gold, plus Light Gray which has no
     root-level token here yet) are a static fallback for any page that
     doesn't include partials/nav.ejs or partials/ps_head.ejs, not a
     second source of truth. Every nav-bearing page overrides these at
     render time via partials/brand_vars.ejs with the same values, read
     from that one module. If this file's literal and brand.js's value
     ever disagree, brand.js is correct — this drifted, not the other
     way around. */
  --navy:    #0B1D3A;  /* Deep Navy — text, headings */
  --navy-lt: #1E325A;
  --sky:     #1473E6;  /* Enterprise Blue — ACTIONS ONLY */
  --sky-dk:  #0F5BB8;
  --gold:    #FFB32E;  /* Z Gold — ATTENTION ONLY */
  --gold-lt: #FFF3DC;
  --gold-ink:#8A5A0B;

  /* Legacy aliases kept so existing views don't break.
     Deliberately converged onto the brand palette. */
  --teal:    #1473E6;
  --teal-lt: #E7F1FD;
  --emerald: #1F9A6D;
  --emerald-lt: #E3F5EE;
  --green:   #1F9A6D;
  --amber:   #FFB32E;
  --amber-lt:#FFF3DC;
  --coral:   #D14343;
  --coral-lt:#FCE9E9;
  --purple:  #4A586B;   /* retired -> neutral ink */
  --purple-lt:#F1EDE5;  /* retired -> neutral surface */
  --red:     #D14343;
  --red-lt:  #FCE9E9;

  /* ── Warm neutral ramp (matches the agent workspace) ── */
  --paper:    #F9F5EE;
  --paper-2:  #FBF8F3;
  --gray-50:  #F9F5EE;
  --gray-100: #F1EDE5;
  --gray-200: #DDD5C8;
  --gray-400: #5A6675;   /* 6.1:1 on white — .metric-label, .card-subtitle,
                            .form-hint, .empty-state */
  --gray-700: #4A586B;   /* 7.4:1 on white */
  --gray-900: #0B1D3A;
  --white:    #ffffff;
  --line:     #E9E3DA;
  --line-2:   #F4F0EA;

  /* Gradients: retired as decoration, kept as tokens for the two
     places they still earn their keep (brand hairline, login). */
  --grad-brand:    linear-gradient(90deg, #0B1D3A, #1473E6 52%, #FFB32E);
  --grad-progress: #1473E6;
  --grad-complete: #1F9A6D;
  --grad-nav:      #FFFFFF;

  --radius:    8px;
  --radius-lg: 12px;
  --radius-xl: 16px;
  --shadow-sm: 0 1px 2px rgba(11,29,58,.05);
  --shadow:    0 3px 12px rgba(11,29,58,.09);
  --shadow-md: 0 8px 28px rgba(11,29,58,.12);

  --surface:   #ffffff;
  --surface-2: #FBF8F3;
  --border:    #E9E3DA;
  --text-primary:   #0B1D3A;
  --text-secondary: #4A586B;
  --text-muted:     #5A6675;

  --mono: 'IBM Plex Mono', ui-monospace, monospace;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
body {
  font-family: 'IBM Plex Sans', -apple-system, 'Segoe UI', Arial, sans-serif;
  font-size: 14px; line-height: 1.6;
  color: var(--navy); background: var(--paper);
  -webkit-font-smoothing: antialiased;
}
a { color: var(--sky); text-decoration: none; }
a:hover { color: var(--sky-dk); text-decoration: none; }

/* ── NAV ───────────────────────────────────────────────────────────────
   Light treatment. The 3px brand hairline is the one piece of colour,
   and it's the same hairline the agent workspace rail uses — that's
   what ties the two shells together without a dark bar fighting the
   light rail. To revert to dark, swap the four marked values.        */
.nav {
  background: #FFFFFF;                       /* dark: #0B1D3A            */
  border-bottom: 1px solid var(--line);      /* dark: rgba(255,255,255,.14) */
  padding: 0 28px; display: flex; align-items: center;
  height: 54px; gap: 4px;
  position: sticky; top: 0; z-index: 100;
  box-shadow: 0 1px 2px rgba(11,29,58,.04);
}
/* The brand hairline replaces the old radial-gradient wash + SVG squiggles. */
.nav::before {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 3px;
  background: var(--grad-brand); pointer-events: none;
}
.nav::after { content: none; }

.nav-brand { color: var(--navy); font-weight: 600; font-size: 16px; letter-spacing: -.3px; display: inline-flex; align-items: center; }
.nav-brand img { height: 40px; width: auto; display: block; }   /* dark: + filter: brightness(0) invert(1) */

.nav-links { display: flex; gap: 2px; margin-left: auto; align-items: center; }
.nav-links a {
  color: var(--gray-700);                    /* dark: rgba(255,255,255,.72) */
  font-size: 13px; font-weight: 500;
  padding: 6px 11px; border-radius: 6px;
  transition: background .15s, color .15s;
}
.nav-links a:hover { color: var(--navy); background: var(--paper-2); text-decoration: none; }
/* Active state: the views set inline font-weight:700, so we style on that. */
.nav-links a[style*="700"] { color: var(--navy); background: var(--gray-100); }

.nav-badge {
  background: var(--sky); color: #fff;
  font-size: 11px; font-weight: 600; padding: 3px 10px; border-radius: 20px;
}

/* Settings/Help icons -- persistent-nav home for these, next to the account
   badge. Previously lived in super-agent-dashboard.ejs's own scrolling
   page body (.sa-icons/.sa-icon-link, scoped to that one page's <style>
   block) instead of the sticky nav, so they scrolled away with the rest
   of the dashboard content. Moved here, into partials/nav.ejs and
   partials/ps_nav.ejs, so they're actually persistent on every page and
   every nav variant, not just present on one page's initial scroll
   position.
   The move itself left the icons undersized relative to their new home --
   the inline <svg> tags in both nav.ejs and ps_nav.ejs were 15x15, which
   read as decorative rather than clickable against this 26px circular
   target. Bumped to 18x18 in the two view files -- which never actually
   landed visually. Confirmed live by measuring the SVG glyph itself (not
   just its 26x26 container) with getBoundingClientRect(): it rendered at
   4px x 18px, not 18x18. Cause: .nav-links a's generic `padding: 6px 11px`
   two rules up also matches these anchors (plain <a> tags inside
   .nav-links), and at (0,1,1) it's higher specificity than .nav-icon-link's
   own (0,1,0) -- always wins regardless of source order. Combined with the
   global `* { box-sizing: border-box }` reset above, that padding eats 22px
   of this element's declared 26px width, leaving only 4px of content box
   for the flex-centered SVG child to size into. Height is unaffected --
   align-items:center doesn't force the same squeeze on the cross axis,
   which is why only the width collapsed. Zeroed out below for icon links
   specifically (a.nav-icon-link, (0,2,1), beats (0,1,1)) without touching
   the padding ordinary .nav-links text links still need. The glyph itself
   is also now sized here via CSS (not the inline SVG width/height
   attributes in the view files, which this fix deliberately leaves alone)
   -- 18px read as decorative next to ~16px nav text; 22px reads as an
   actual affordance while still leaving real margin inside the 26px
   circular hit target. */
.nav-icon-link {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; flex-shrink: 0; border-radius: 50%;
  color: var(--gray-700); transition: background .15s, color .15s;
}
/* flex-shrink:0 -- found live while verifying the padding/glyph-size fix
   above on both nav variants: ps_nav.ejs's longer link list (Projects
   through Team, ten items before Sign out) leaves .nav-links tighter on
   available width than nav.ejs's shorter one, and .nav-icon-link's default
   flex-shrink:1 (it's a flex item inside .nav-links) let the row shrink
   this container from its declared 26px down to 22px to make everything
   fit with no overflow. The glyph itself stayed correctly sized regardless
   (its own flex-shrink:0 below already protected it), just with zero
   margin left inside the shrunk circle instead of the intended ~2px each
   side. Confirmed live: adding this keeps the container's own 26px
   consistent on both nav variants with no overflow introduced (.nav-links'
   scrollWidth still equals its clientWidth). */
/* Specificity (0,2,1) -- beats .nav-links a's (0,1,1) outright, regardless
   of source order. A bare `.nav-icon-link { padding: 0 }` at (0,1,0) would
   NOT be enough -- it still loses to .nav-links a's (0,1,1) even placed
   after it, which is exactly how this got squeezed in the first place. */
.nav-links a.nav-icon-link { padding: 0; }
.nav-icon-link:hover { color: var(--navy); background: var(--paper-2); }
.nav-icon-link svg { width: 22px; height: 22px; flex-shrink: 0; }

/* ── INTEGRATION DOTS ── */
/* Three real connection states, not two -- own (personally connected
   everywhere, green), shared (working via a client-level/service
   credential, blue -- a legitimate state, not a warning), none (something
   genuinely not configured, grey). amber/red are health overlays
   (approaching expiry / broken) that take priority over own/shared when
   present -- see src/lib/integrations/connection-state.js. */
.cxn-dot    { display: inline-block; width: 8px; height: 8px; border-radius: 50%; }
.cxn-own    { background: var(--emerald); }
.cxn-shared { background: #3b82f6; }
.cxn-amber  { background: var(--gold); }
.cxn-red    { background: var(--red); }
.cxn-none   { background: var(--gray-200); }

/* ── LAYOUT ── */
.page        { max-width: 1080px; margin: 0 auto; padding: 30px 28px 56px; }
.page-wide   { max-width: 1320px; margin: 0 auto; padding: 30px 28px 56px; }
.page-narrow { max-width: 640px;  margin: 0 auto; padding: 30px 28px 56px; }

/* ── CARDS ── */
.card {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: 20px 24px;
  margin-bottom: 14px; box-shadow: var(--shadow-sm);
}
.card-title { font-size: 15px; font-weight: 600; color: var(--navy); margin-bottom: 12px; letter-spacing: -.2px; }
.card-subtitle { font-size: 12px; color: var(--gray-400); margin-top: 2px; }

/* ── METRICS ──────────────────────────────────────────────────────────
   The rainbow nth-child variants are gone. One card treatment; figures
   carry the weight. Add .metric.attention for a gold top rule.       */
.metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px,1fr)); gap: 12px; margin-bottom: 24px; }
.metric {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: 15px 17px;
  box-shadow: var(--shadow-sm); position: relative; overflow: hidden;
}
.metric::after { content: none; }
.metric.attention::after {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 2px;
  background: var(--gold);
}
.metric-label {
  font-family: var(--mono); font-size: 9.5px; font-weight: 500;
  color: var(--gray-400); letter-spacing: .1em; text-transform: uppercase;
  margin-bottom: 8px;
}
.metric-value {
  font-size: 27px; font-weight: 600; color: var(--navy);
  line-height: 1; letter-spacing: -.7px; font-variant-numeric: tabular-nums;
}
.metric-sub { font-size: 11.5px; color: var(--gray-400); margin-top: 5px; }

/* Neutralise the old per-position colour overrides. */
.metrics .metric:nth-child(1),
.metrics .metric:nth-child(2),
.metrics .metric:nth-child(3),
.metrics .metric:nth-child(4) { background: var(--white); border-color: var(--line); }
.metrics .metric:nth-child(1) .metric-value, .metrics .metric:nth-child(1) .metric-label,
.metrics .metric:nth-child(2) .metric-value, .metrics .metric:nth-child(2) .metric-label,
.metrics .metric:nth-child(3) .metric-value, .metrics .metric:nth-child(3) .metric-label,
.metrics .metric:nth-child(4) .metric-value, .metrics .metric:nth-child(4) .metric-label { color: inherit; }
.metrics .metric .metric-value { color: var(--navy); }
.metrics .metric .metric-label { color: var(--gray-400); }
.metrics .metric:nth-child(4) .metric-sub { color: var(--gray-400); }

/* ── PROGRESS BARS ── */
.progress-wrap { background: var(--gray-100); border-radius: 6px; height: 6px; overflow: hidden; margin: 6px 0; }
.progress-fill { height: 100%; background: var(--sky); border-radius: 6px; transition: width .5s cubic-bezier(.4,0,.2,1); }
.progress-fill.complete { background: var(--emerald); }
.progress-fill.warn     { background: var(--gold); }
.progress-fill.over     { background: var(--red); }

/* ── STAGE BADGES ─────────────────────────────────────────────────────
   Collapsed from nine colours to four semantic ones: neutral for
   in-flight stages, gold for waiting, green for settled, red for lost. */
.stage {
  display: inline-flex; align-items: center; padding: 3px 10px;
  border-radius: 20px; font-size: 11px; font-weight: 600; letter-spacing: .01em;
  border: 1px solid transparent;
}
.stage-questionnaire { background: var(--gold-lt); color: var(--gold-ink); border-color: #F5DCAE; }
.stage-day1_prep     { background: var(--gray-100); color: var(--gray-700); border-color: var(--line); }
.stage-week1_install { background: var(--gray-100); color: var(--gray-700); border-color: var(--line); }
.stage-week2_run     { background: var(--gray-100); color: var(--gray-700); border-color: var(--line); }
.stage-day14_tune    { background: var(--gray-100); color: var(--gray-700); border-color: var(--line); }
.stage-subscribed    { background: var(--emerald-lt); color: #0F6B4A; border-color: #BFE7D7; }
.stage-churned       { background: var(--red-lt); color: #9B2C2C; border-color: #F3C9C9; }
.stage-admin         { background: var(--teal-lt); color: var(--sky-dk); border-color: #C3DBF8; }
.stage-consultant    { background: var(--gray-100); color: var(--gray-700); border-color: var(--line); }

/* ── CHECKLIST ── */
.checklist { list-style: none; display: flex; flex-direction: column; gap: 7px; }
.checklist li { display: flex; align-items: center; gap: 10px; font-size: 13px; }
.check-box {
  width: 17px; height: 17px; border-radius: 5px;
  border: 1.5px solid var(--gray-200); flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; transition: all .2s;
}
.check-box.done { background: var(--emerald); border-color: var(--emerald); box-shadow: none; }
.check-box.done::after { content: '✓'; color: #fff; font-size: 11px; font-weight: 700; }
.check-label.done { text-decoration: line-through; color: var(--gray-400); }

/* ── TABLES ── */
table { width: 100%; border-collapse: collapse; font-size: 13px; }
th {
  background: var(--paper-2); color: var(--gray-700);
  font-family: var(--mono); font-weight: 500; font-size: 9.5px;
  text-transform: uppercase; letter-spacing: .1em;
  padding: 10px 16px; text-align: left; border-bottom: 1px solid var(--line);
}
td { padding: 11px 16px; border-bottom: 1px solid var(--line-2); vertical-align: top; }
tr:last-child td { border-bottom: none; }
tr:hover td { background: var(--paper-2); }

/* ── FORMS ── */
.form-group { margin-bottom: 16px; }
.form-label { display: block; font-size: 12px; font-weight: 600; color: var(--gray-700); margin-bottom: 5px; }
.form-hint  { font-size: 11px; color: var(--gray-400); margin-bottom: 4px; display: block; }
input[type=text], input[type=email], input[type=password], input[type=number], select, textarea {
  width: 100%; padding: 9px 13px;
  border: 1px solid var(--gray-200); border-radius: var(--radius);
  font-size: 13px; color: var(--navy); background: #fff; outline: none;
  transition: border-color .15s, box-shadow .15s; font-family: inherit;
}
input:focus, select:focus, textarea:focus { border-color: var(--sky); box-shadow: 0 0 0 3px var(--teal-lt); }
textarea { min-height: 80px; resize: vertical; }
.form-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.form-check { display: flex; align-items: center; gap: 8px; font-size: 13px; margin-bottom: 6px; cursor: pointer; }
.form-check input { width: 15px; height: 15px; cursor: pointer; accent-color: var(--sky); }

/* ── BUTTONS ──────────────────────────────────────────────────────────
   Enterprise Blue is now the primary action (it was navy, which read
   as another neutral). Gradients removed.                            */
.btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 9px 17px; border-radius: var(--radius);
  font-size: 13px; font-weight: 600; cursor: pointer;
  border: 1px solid transparent; transition: all .15s; font-family: inherit;
}
.btn-primary { background: var(--sky); color: #fff; border-color: var(--sky); box-shadow: var(--shadow-sm); }
/* .btn-primary is used on <a> as often as <button> (e.g. "Connect your
   own account →" on /portal/integrations) -- the generic `a:hover {
   color: var(--sky-dk) }` rule below has higher specificity (element +
   pseudo-class) than plain `.btn-primary` alone (one class), so without
   restating color here explicitly, a hovered/focused link version of
   this button loses its white text to that rule while the background
   also becomes var(--sky-dk) -- text rendering the same color as its
   own fill, effectively invisible. Also covers :focus, which had no
   rule of its own at all before this. */
.btn-primary:hover, .btn-primary:focus { background: var(--sky-dk); border-color: var(--sky-dk); color: #fff; }
.btn-sky { background: var(--sky); color: #fff; border-color: var(--sky); }
.btn-sky:hover { background: var(--sky-dk); border-color: var(--sky-dk); }
.btn-teal { background: var(--sky); color: #fff; border-color: var(--sky); }
.btn-teal:hover { background: var(--sky-dk); }
.btn-outline { background: #fff; color: var(--navy); border-color: var(--gray-200); }
.btn-outline:hover { background: var(--paper-2); border-color: #C9BFAE; }
.btn-success { background: var(--emerald); color: #fff; border-color: var(--emerald); }
.btn-success:hover { background: #178257; }
.btn-danger { background: var(--red); color: #fff; border-color: var(--red); }
.btn-danger:hover { background: #B93636; }
.btn-sm { padding: 6px 13px; font-size: 12px; }

/* ── ALERTS ── */
.alert { padding: 11px 15px; border-radius: var(--radius); font-size: 13px; margin-bottom: 14px; font-weight: 500; }
.alert-success { background: var(--emerald-lt); color: #0F6B4A; border: 1px solid #BFE7D7; }
.alert-error   { background: var(--red-lt); color: #9B2C2C; border: 1px solid #F3C9C9; }
.alert-info    { background: var(--teal-lt); color: var(--sky-dk); border: 1px solid #C3DBF8; }
.alert-warn    { background: var(--gold-lt); color: var(--gold-ink); border: 1px solid #F5DCAE; }

/* ── TIMELINE ── */
.timeline { position: relative; padding-left: 20px; }
.timeline::before { content: ''; position: absolute; left: 6px; top: 0; bottom: 0; width: 1px; background: var(--line); }
.tl-item { position: relative; padding-bottom: 16px; }
.tl-dot  { position: absolute; left: -16px; top: 4px; width: 9px; height: 9px; border-radius: 50%; background: var(--gray-200); border: 2px solid #fff; }
.tl-dot.done   { background: var(--emerald); box-shadow: none; }
.tl-dot.active { background: var(--sky); box-shadow: 0 0 0 3px var(--teal-lt); }
.tl-label { font-size: 12.5px; font-weight: 600; color: var(--navy); }
.tl-sub   { font-size: 11.5px; color: var(--gray-400); }

/* ── SECTION HEADER ── */
.section-hdr {
  font-family: var(--mono); font-size: 10px; font-weight: 500;
  letter-spacing: .1em; text-transform: uppercase; color: var(--gray-400);
  padding-bottom: 8px; border-bottom: 1px solid var(--line); margin-bottom: 14px;
}

/* ── EMPTY STATE ── */
.empty-state {
  background: var(--white); border: 1px dashed var(--gray-200);
  border-radius: var(--radius-lg); padding: 40px 28px;
  text-align: center; color: var(--gray-400); font-size: 13px;
}

/* ── LOGIN ──
   The one place a rich background still earns its keep. Flattened from
   a three-stop rainbow to a deep navy field. */
.login-wrap {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  background: radial-gradient(ellipse 90% 70% at 50% 0%, #16305C 0%, #0B1D3A 62%, #061224 100%);
}
.login-card {
  background: #fff; border-radius: var(--radius-xl);
  padding: 40px 44px; width: 380px; box-shadow: 0 24px 56px rgba(6,18,36,.42);
}
.login-logo-img { width: 220px; height: auto; display: block; margin: 0 auto 14px; }
.login-sub { font-size: 13px; color: var(--gray-400); margin-bottom: 26px; }

/* ── MODAL ── */
.modal-overlay {
  position: fixed; inset: 0; background: rgba(11,29,58,.42);
  backdrop-filter: blur(3px); z-index: 1000;
  display: flex; align-items: center; justify-content: center;
  opacity: 0; pointer-events: none; transition: opacity .2s;
}
.modal-overlay.open { opacity: 1; pointer-events: all; }
.modal {
  background: #fff; border-radius: var(--radius-xl); padding: 28px 32px;
  width: 100%; max-width: 500px; box-shadow: var(--shadow-md);
  position: relative; transform: translateY(14px); transition: transform .2s;
}
.modal-overlay.open .modal { transform: translateY(0); }
.modal-title { font-size: 17px; font-weight: 600; color: var(--navy); margin-bottom: 20px; letter-spacing: -.3px; }
.modal-close {
  position: absolute; top: 18px; right: 20px;
  background: var(--gray-100); border: none; width: 27px; height: 27px;
  border-radius: 50%; font-size: 13px; cursor: pointer; color: var(--gray-700);
  display: flex; align-items: center; justify-content: center; transition: background .15s;
}
.modal-close:hover { background: var(--gray-200); }
.modal-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.pass-hint { font-size: 11px; color: var(--gray-400); margin-top: 4px; }

/* ── JOURNEY / RINGS ── */
.journey-node.done   { background: var(--emerald) !important; }
.journey-node.active { background: var(--sky) !important; box-shadow: 0 0 0 4px var(--teal-lt) !important; }
.journey-node.todo   { background: #fff !important; border: 1.5px solid var(--gray-200) !important; color: var(--gray-400) !important; }
.journey-progress-fill { background: var(--sky) !important; }

/* ── FADE-IN ── */
.fade-in { animation: fadeIn .4s ease forwards; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }

/* ── RESPONSIVE ── */
@media (max-width: 768px) {
  .page, .page-wide, .page-narrow { padding: 20px 16px; }
  .nav { padding: 0 16px; gap: 0; }
  .nav-links { gap: 0; }
  .nav-links a { padding: 6px 8px; font-size: 12px; }
  .metrics { grid-template-columns: 1fr 1fr; }
}

/* Questionnaire progress bar — was a gold/blue gradient. */
td .progress-fill { background: var(--sky); }

/* ── STAGING BANNER ── */
.env-banner {
  position: sticky; top: 0; z-index: 200;
  background: var(--gold); color: #1A1200;
  text-align: center; font-family: var(--mono);
  font-size: 10px; font-weight: 500; letter-spacing: .16em;
  padding: 5px 0;
}

/* ── PASSWORD SHOW/HIDE TOGGLE ──────────────────────────────────────────
   Wraps a password <input> so an icon button can sit inside it without
   splitting into two swapped fields (that breaks password managers and
   autofill -- the JS toggles type="password"/"text" on this same input).
   Toggle state is visual only, driven off the button's own aria-pressed
   attribute -- never persisted, always starts hidden on load. */
.pw-field { position: relative; }
.pw-field input[type=password],
.pw-field input[type=text] { padding-right: 40px; }
.pw-toggle {
  position: absolute; top: 50%; right: 4px; transform: translateY(-50%);
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0; border: none; background: transparent;
  color: var(--gray-400); cursor: pointer; border-radius: var(--radius);
}
.pw-toggle:hover { color: var(--sky); }
.pw-toggle:focus-visible { outline: 2px solid var(--sky); outline-offset: 1px; }
.pw-toggle .pw-icon-eye { display: none; }
.pw-toggle[aria-pressed="true"] .pw-icon-eye { display: block; }
.pw-toggle[aria-pressed="true"] .pw-icon-eye-off { display: none; }
