/* inter-cyrillic-ext-wght-normal */
@font-face {
  font-family: 'Inter Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url(/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2) format('woff2-variations');
  unicode-range: U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F;
}

/* inter-cyrillic-wght-normal */
@font-face {
  font-family: 'Inter Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url(/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2) format('woff2-variations');
  unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;
}

/* inter-greek-ext-wght-normal */
@font-face {
  font-family: 'Inter Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url(/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2) format('woff2-variations');
  unicode-range: U+1F00-1FFF;
}

/* inter-greek-wght-normal */
@font-face {
  font-family: 'Inter Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url(/assets/inter-greek-wght-normal-CkhJZR-_.woff2) format('woff2-variations');
  unicode-range: U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;
}

/* inter-vietnamese-wght-normal */
@font-face {
  font-family: 'Inter Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url(/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2) format('woff2-variations');
  unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;
}

/* inter-latin-ext-wght-normal */
@font-face {
  font-family: 'Inter Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url(/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2) format('woff2-variations');
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}

/* inter-latin-wght-normal */
@font-face {
  font-family: 'Inter Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url(/assets/inter-latin-wght-normal-Dx4kXJAl.woff2) format('woff2-variations');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}/* jetbrains-mono-cyrillic-ext-wght-normal */
@font-face {
  font-family: 'JetBrains Mono Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 800;
  src: url(data:font/woff2;base64,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) format('woff2-variations');
  unicode-range: U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F;
}

/* jetbrains-mono-cyrillic-wght-normal */
@font-face {
  font-family: 'JetBrains Mono Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 800;
  src: url(/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2) format('woff2-variations');
  unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;
}

/* jetbrains-mono-greek-wght-normal */
@font-face {
  font-family: 'JetBrains Mono Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 800;
  src: url(/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2) format('woff2-variations');
  unicode-range: U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF;
}

/* jetbrains-mono-vietnamese-wght-normal */
@font-face {
  font-family: 'JetBrains Mono Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 800;
  src: url(/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2) format('woff2-variations');
  unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;
}

/* jetbrains-mono-latin-ext-wght-normal */
@font-face {
  font-family: 'JetBrains Mono Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 800;
  src: url(/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2) format('woff2-variations');
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}

/* jetbrains-mono-latin-wght-normal */
@font-face {
  font-family: 'JetBrains Mono Variable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 800;
  src: url(/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2) format('woff2-variations');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}/* ════════════════════════════════════════════════════════════════════════
 * CANONICAL TOKEN ALLOWLIST
 * ════════════════════════════════════════════════════════════════════════
 * The tokens below are the ONLY tokens that may appear in any CSS module.
 * The list is enforced by `npm run check:tokens` — any `var(--…)` outside
 * this set fails the build. Tighten by design: a token earns a slot only
 * if it represents an irreducible design concept, not because there
 * happen to be call sites that use it.
 *
 * ─── COLORS (23) ──────────────────────────────────────────────────────
 *
 * Text tiers (--text-h is the base; tiers derive via alpha)
 *   --text-h                      (raw base; prefer tiers in modules)
 *   --text-primary, --text-secondary, --text-tertiary, --text-disabled
 *   --text-light                  (semantic-flip "on-dark" foreground)
 *
 * Operational accent (indigo — CTAs, controls, focus, selection)
 *   --text-accent, --text-accent-soft
 *   --surface-accent-tint
 *
 * Secondary accent (match green — affirmative actions, matched-flight)
 *   --text-accent-secondary
 *   --surface-accent-secondary-tint, --surface-accent-secondary-tint-strong
 *
 * Surfaces
 *   --section-bg                  (card surface — sits on top of page)
 *   --section-bg-alt              (page canvas — one step back from cards)
 *   --surface-elevated            (lifted panel: sidebars, table headers)
 *   --surface-overlay             (hover / selected fills)
 *
 * Borders
 *   --section-border-faint        (card / section edge)
 *   --section-line-faint          (internal divider, table rules)
 *
 * Status (semantic signals — banner bg/text derive via rgb(from …))
 *   --status-urgent, --status-info, --status-success, --status-warning
 *
 * Modal
 *   --modal-backdrop              (translucent veil; theme-aware)
 *
 * ─── TYPOGRAPHY ───────────────────────────────────────────────────────
 *   --font, --mono
 *   --font-size-2xs, --font-size-xs, --font-size-sm, --font-size-base
 *   --weight-regular, --weight-medium, --weight-semibold, --weight-bold
 *   --leading-none, --leading-tight, --leading-snug, --leading-normal
 *   --tracking-tight, --tracking-normal, --tracking-snug,
 *     --tracking-wide, --tracking-caps
 *
 * ─── CHROME ───────────────────────────────────────────────────────────
 *   --radius-default
 *   --border-hairline   (1px — universal hairline: card edges, dividers,
 *                        column rules, focus-ring overlap)
 *   --border-emphasis   (2px — focus outlines, emphasis underlines)
 *   --rail              (3px — inset selection rail on active list rows,
 *                        focus-ring spread)
 *
 * ─── SPACING ──────────────────────────────────────────────────────────
 * Apply to padding / margin / gap. Snap to the nearest tier rather than
 * inventing 0.35rem / 0.55rem / etc. — the tiers below collapse 71
 * historical values into 8.
 *   --space-2xs   4px   (0.25rem)  — tight icon/chip gaps
 *   --space-xs    8px   (0.5rem)   — standard small gap (workhorse)
 *   --space-sm   12px   (0.75rem)  — comfortable gap
 *   --space-md   16px   (1rem)     — default card / section gap
 *   --space-lg   24px   (1.5rem)   — card padding, group separation
 *   --space-xl   32px   (2rem)     — section break
 *   --space-2xl  48px   (3rem)     — page-level break
 *   --space-3xl  64px   (4rem)     — landing hero / block separation
 *
 * ─── LAYOUT / MOTION ──────────────────────────────────────────────────
 *   --left-sidebar-width, --header-height-app
 *   --z-header, --z-drawer-backdrop, --z-drawer, --z-popover
 *   --page-enter-duration, --page-enter-ease, --page-enter-stagger
 *
 * Anything not listed above is on the chopping block. Inline literals or
 * derive from a tier (e.g. `rgb(from var(--text-h) r g b / 0.08)`) rather
 * than adding a new token. If a genuine concept gap exists, update this
 * comment AND `scripts/check-tokens.mjs` in the same PR.
 * ════════════════════════════════════════════════════════════════════════ */

/* ════════════════════════════════════════════════════════════════════════
 * CANONICAL LAYOUT BREAKPOINTS
 * ════════════════════════════════════════════════════════════════════════
 * CSS cannot import the TypeScript constants in `src/layouts/breakpoints.ts`,
 * so the values are mirrored here. Any media query in this codebase MUST
 * use one of these three thresholds — no ad-hoc widths. If a band changes,
 * update BOTH this docblock AND `src/layouts/breakpoints.ts`.
 *
 *   @media (max-width: 599.98px)  — BP_MOBILE
 *     Phone surface. Mobile card list, mobile header layout, `.pageMobile`
 *     clamp (single-scrollbar invariant), drawer sidebar.
 *
 *   @media (max-width: 900px)     — BP_COMPACT
 *     Compact surface. Missions table swaps to the desktop card list.
 *     Drawer sidebar still in effect.
 *
 *   @media (max-width: 1279.98px) — BP_TABLET
 *     Tablet / small-laptop surface. Sidebar is a drawer (the docked rail
 *     would crowd the content). Above 900px the missions table renders
 *     and uses internal horizontal scroll when its container is narrower
 *     than the table's locked natural width.
 *
 *   @media (min-width: 1280px)    — desktop (no `max-width` below)
 *     Sidebar docks. Table fits cleanly once viewport ≥ ~1610px; below
 *     that, `MissionsTable` provides horizontal scroll.
 * ════════════════════════════════════════════════════════════════════════ */

:root {
  --text-h: #08060d;

  /* Single UI typeface. Inter is the de-facto polished-product sans
   * (Linear, Stripe, Vercel, Notion, Figma). Loaded via Fontsource so
   * it renders identically on every OS — no system-font drift. Use
   * `--font` for everything UI; reach for `--mono` only for tabular
   * data (dates, IDs, airport codes). Hierarchy via weight + size,
   * never via additional font families. */
  --font: "Inter Variable", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "JetBrains Mono Variable", ui-monospace, Consolas, monospace;

  /* ====================================================================
     SEMANTIC TIER TOKENS — operational UI legibility scale
     ====================================================================
     Use these in place of ad-hoc `rgb(from var(--text-h) r g b / X)`
     opacity expressions. The four text tiers map to the visual
     hierarchy a coordinator reads through:

       primary   — body text, headings, anything that must be unmissable
       secondary — labels, supporting copy, button chrome
       tertiary  — captions, metadata, separators
       disabled  — disabled controls, ghosted hints

     Both themes overlay text on theme-aware glass surfaces, so the
     tier values are alpha-of-`--text-h` rather than baked literals —
     they automatically blend correctly against whatever surface
     they're on. The surface and border tiers follow the same idea. */

  --text-primary: var(--text-h);
  --text-secondary: rgb(from var(--text-h) r g b / 0.85);
  --text-tertiary: rgb(from var(--text-h) r g b / 0.7);
  --text-disabled: rgb(from var(--text-h) r g b / 0.45);

  /* Operational accent — deep blue (~220° hue). Reads as the "premium
     operator tool" accent the audience (HNW jet owners, private-banking
     patrons) sees in their fintech dashboards. Same hue family in both
     themes so the brand feel doesn't swing between light and dark; only
     the lightness shifts to maintain ≥4.5:1 contrast on each surface. */
  --text-accent: #1e40af;
  --text-accent-soft: #1d4ed8;

  /* Secondary accent — affirmative green. Same hex as the mission-map
     leg-polyline so the "matched flight" UI semantic and the bright
     line on the map read as one color. Used for Reach Out / Apply /
     Send buttons, selected-match tints, and the metric tile when
     matches > 0. */
  --text-accent-secondary: #147a3a;
  --surface-accent-secondary-tint: rgb(
    from var(--text-accent-secondary) r g b / 0.12
  );
  --surface-accent-secondary-tint-strong: rgb(
    from var(--text-accent-secondary) r g b / 0.45
  );

  /* Surface overlays — fills inside the glass dock (suggestion cards,
     budget banner background, row hover, selected-row tint). */
  --surface-overlay: rgb(from var(--text-h) r g b / 0.05);
  --surface-accent-tint: rgb(from var(--text-accent) r g b / 0.1);

  --text-light: #ffffff;

  /* ====================================================================
     TYPOGRAPHY SCALE — single source of truth for font sizes.
     ====================================================================
     Reach for these instead of ad-hoc `font-size: 0.78rem` literals so
     the app reads as one consistent system. Sizes are rem-based against
     the 16px html root, so each step matches a familiar px value:

       --font-size-2xs:  11px  (0.6875rem)  — micro-labels, dense pills
       --font-size-xs:   12px  (0.75rem)    — captions, table chrome
       --font-size-sm:   14px  (0.875rem)   — field labels, secondary copy
       --font-size-base: 15px  (0.9375rem)  — body values, default

     For dense operational UI (mission detail, tables): field labels at
     `--font-size-sm`, values at `--font-size-base`, section labels at
     `--font-size-xs`. Display sizes above --font-size-base are inline
     literals at the call site with a justifying comment. */
  --font-size-2xs: 0.6875rem;
  --font-size-xs: 0.75rem;
  --font-size-sm: 0.875rem;
  --font-size-base: 0.9375rem;

  /* ====================================================================
     TYPE WEIGHT / LINE-HEIGHT / TRACKING — the rest of the type system.
     ====================================================================
     `font-size` lives above; these three scales govern the remaining
     typographic dimensions so weight, leading, and tracking stay on a
     fixed ramp instead of drifting into dozens of near-duplicate raw
     values (the system replaced 7 weight / 16 line-height / 27 tracking
     literals with these). Theme-independent — no dark override. Enforced
     by check:tokens via the font-weight / line-height / letter-spacing
     property rules; the deliberate-display-literal marker still bypasses
     them for genuine display surfaces.

       Weight    regular 400 · medium 500 · semibold 600 · bold 700
       Leading   none 1 · tight 1.2 · snug 1.4 · normal 1.5
       Tracking  tight -0.02 · normal 0 · snug 0.02 · wide 0.05 · caps 0.1 */
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  --leading-none: 1;
  --leading-tight: 1.2;
  --leading-snug: 1.4;
  --leading-normal: 1.5;

  --tracking-tight: -0.02em;
  --tracking-normal: 0;
  --tracking-snug: 0.02em;
  --tracking-wide: 0.05em;
  --tracking-caps: 0.1em;

  /* Section surfaces. --section-bg is the white card surface;
     --section-bg-alt is the page canvas one step back so cards lift. */
  --section-bg: #ffffff;
  --section-bg-alt: #fcfcfc;
  --section-border-faint: #f0f0f0;
  --section-line-faint: #e0e0e0;

  /* Semantic status accents — meaning-bearing colors. Banner bg derives
     via `rgb(from var(--status-X) r g b / 0.12)` at the call site;
     banner text is the same `--status-X`. All ≥4.5:1 on --section-bg. */
  --status-urgent: #c0392b;
  --status-info: #2c6fbb;
  --status-success: #287a51;
  --status-warning: #b14a3a;

  /* Elevated content surface — cool blue-grey panel that sits visibly
     above the page bg. Page-level sidebars, data-table headers, lifted
     panels. Body text reads ≥4.5:1 against it. */
  --surface-elevated: #eef2f6;

  /* Modal backdrop — light: brand-navy tint; dark: near-black veil. */
  --modal-backdrop: rgba(18, 34, 48, 0.55);

  /* Default border radius for app chrome (rows, chips, inputs, small
     surfaces). 4px is already the dominant value across the app; this
     token lets call sites converge on a single source of truth. */
  --radius-default: 4px;

  /* Border-width scale. The three tokens cover ~87% of px-width sites
     across the app. Drop-shadow elevation is forbidden (§5b of
     SKILL_STYLING_CHECKLIST) — these are line widths only, not shadow
     blur radii. */
  --border-hairline: 1px;
  --border-emphasis: 2px;
  --rail: 3px;

  /* Spacing scale — applies to padding / margin / gap. 4px base unit,
     ~1.5× ramp. Snap to the nearest tier; don't invent intermediate
     values. Layout dimensions (sidebar widths, hero paddings, etc.) are
     NOT spacing — they get their own layout tokens or, for marketing
     surfaces, inline literals with the `deliberate display literal`
     comment marker. */
  --space-2xs: 0.25rem;
  --space-xs: 0.5rem;
  --space-sm: 0.75rem;
  --space-md: 1rem;
  --space-lg: 1.5rem;
  --space-xl: 2rem;
  --space-2xl: 3rem;
  --space-3xl: 4rem;

  /* Page-arrival motion tokens — duration / easing / stagger shared
     across every page that opts into the layered fade-up. Tuned for a
     deliberate, exquisite entrance: long duration with an out-expo
     decelerating curve (the "settles into place from a tall arc" feel
     used in high-end product hero sections — Apple, Linear, Vercel),
     and a generous stagger so each block arrives as its own moment
     rather than the page slamming open. Reduced-motion users get
     instant arrival via the global gate at the top of this file.
     Keyframes themselves are declared per-module (vite's CSS-module
     parser won't accept :global() in property values). Reference
     recipe lives in `src/matches/MatchesPage.module.css`. */
  --page-enter-duration: 1100ms;
  --page-enter-ease: cubic-bezier(0.16, 1, 0.3, 1);
  --page-enter-stagger: 200ms;

  /* Authenticated app shell — landing chrome uses its own inline heights. */
  --header-height-app: 56px;
  --left-sidebar-width: 260px;
  --z-header: 20;
  /* Drawer (left + right) and its backdrop must sit above any page-level
   * overlays — e.g., /mission-map's floating panels and rail use z-index
   * 400/500. The drawer is layout chrome and always wins over page content. */
  --z-drawer-backdrop: 900;
  --z-drawer: 910;
  /* Popovers / portaled dropdowns (AirportSearch results, etc.) must sit
   * above the drawer so a picker inside a slideout panel doesn't render
   * behind its own host surface. */
  --z-popover: 1000;

  font: 20px/145% var(--font);
  letter-spacing: 0.18px;
  /* Locked to light at the root — landing/sign-in must not pick up dark
     native UI when the OS is dark. The authenticated shell explicitly
     overrides `color-scheme: dark` on <html> while mounted (see Iter 3). */
  color-scheme: light;
  color: var(--text-h);
  background: var(--section-bg);
  font-synthesis: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  /* Landing-only header height (80px); app shell scroll behavior is
   * unaffected because the app uses sticky layouts, not anchor jumps. */
  scroll-padding-top: 80px;
  /* Always reserve a scrollbar track so content height crossing the
   * viewport threshold doesn't reflow horizontally (the "jump" when a
   * scrollbar appears/disappears between renders). `overflow-y: scroll`
   * is more universally supported than `scrollbar-gutter: stable` —
   * the latter requires the element to already be a scroll container,
   * which <html> isn't by default. */
  overflow-y: scroll;
}

/* Authoritative reduced-motion gate. The `!important` overrides every
 * animation/transition declaration in every module, including infinite
 * keyframe loops (capped to one iteration). Per-module @media blocks
 * exist for explicit-intent locality (a maintainer scanning a single
 * CSS module sees the gate without having to remember this global
 * rule), but this is the safety net of last resort — no animation
 * survives reduced motion regardless of what a future module declares. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Dark palette — applied via [data-theme="dark"] on <html> (and on the
   #root-popover portal subtree) by the ThemeProvider's DOM effect (Iter 3).
   The selector is unscoped on purpose so portals rendered outside the shell
   subtree pick it up too.

   WCAG verification: run `npm run check:contrast`. Targets — body text AAA
   ≥7:1 on bg/section-bg; headings, accents, status text AA ≥4.5:1 on
   section-bg. */
[data-theme="dark"] {
  /* Surfaces */
  --section-bg: #171b22;
  --section-bg-alt: #1d2129;
  --section-border-faint: #262b34;
  --section-line-faint: #2f3540;

  /* Text base — tiers derive automatically via alpha-of-text-h. */
  --text-h: #f3f4f7;
  --text-light: #0e1116;

  /* Operational accent — a clean, trust-leaning azure that reads decisively
     blue on the dark surface without the purple lean of the previous indigo.
     Lifted slightly off the stock blue-500 it started from, which cleared AA
     on the page canvas but not on `--surface-elevated` (4.23:1) — where every
     page-owned sidebar and the mission map's control panel put text. Both this
     and the soft hover shade clear ≥4.5:1 on BOTH surfaces; `check:contrast`
     enforces it. */
  --text-accent: #4C8DF7;
  --text-accent-soft: #60A5FA;

  /* Secondary accent — same hex as the dark-theme leg polyline. */
  --text-accent-secondary: #34d399;

  /* Status */
  --status-urgent: #e0685a;
  --status-info: #5b9bd9;
  --status-success: #5cb583;
  --status-warning: #d9755e;

  /* Elevated content surface */
  --surface-elevated: #1f242d;

  /* Modal backdrop — true near-black veil (a navy tint reads too light). */
  --modal-backdrop: rgba(0, 0, 0, 0.7);
}

/* Cross-fade window during a deliberate theme switch. The flag is set on
   <html> by ThemeProvider's setMode and cleared ~260ms later, so this rule
   is only active while a user-initiated swap settles. !important is fine
   here precisely because the attribute is short-lived; permanent transitions
   on every element would make hover/focus animations feel sluggish forever.
   Reduced-motion users never get the flag set (see ThemeProvider). */
html[data-theme-transitioning] body,
html[data-theme-transitioning] body *,
html[data-theme-transitioning] body *::before,
html[data-theme-transitioning] body *::after {
  /* `transition` is shorthand — without `transform` here, !important
     would clobber per-element transform transitions (e.g. the toggle
     indicator's slide) and the new value would snap. Other transforms
     in the shell get retimed to 220ms ease for this one window;
     acceptable trade vs. a visible snap on the control the user just
     interacted with. */
  transition:
    background-color 220ms ease,
    color 220ms ease,
    border-color 220ms ease,
    box-shadow 220ms ease,
    transform 220ms ease !important;
}

#root {
  width: 100%;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  margin: 0 auto;
}

body {
  margin: 0;
}

h1,
h2 {
  font-family: var(--font);
  font-weight: 500;
  color: var(--text-h);
}

h1 {
  font-size: 56px;
  letter-spacing: -1.68px;
  margin: 32px 0;
  @media (max-width: 1024px) {
    font-size: 36px;
    margin: 20px 0;
  }
}
h2 {
  font-size: 24px;
  line-height: 118%;
  letter-spacing: -0.24px;
  margin: 0 0 8px;
  @media (max-width: 1024px) {
    font-size: 20px;
  }
}
p {
  margin: 0;
}

code,
.counter {
  font-family: var(--mono);
  display: inline-flex;
  border-radius: var(--radius-default);
  color: var(--text-h);
}

code {
  font-size: 15px;
  line-height: 135%;
  padding: 4px 8px;
  background: var(--surface-overlay);
}
._root_dviix_1 {
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--section-bg);
  color: var(--text-h);
  font-family: var(--font);
}
/* Shared form chrome for SignIn + PasswordReset. Whitelist tokens only;
 * canonical recipes: §4 primary CTA (solid indigo), §4 secondary ghost,
 * §4 icon-button for the eye-toggle. Reduced motion handled globally. */

._form_1hmgl_5 {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  margin: 0;
}

._subtitle_1hmgl_12 {
  margin: 0 0 var(--space-2xs);
  font-family: var(--font);
  font-size: var(--font-size-sm);
  color: var(--text-tertiary);
  line-height: var(--leading-normal);
}

._field_1hmgl_20 {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

/* Right-aligned inline action paired with a field — currently used
 * for the "Forgot password?" link sitting beneath the password input. */
._labelRow_1hmgl_28 {
  display: flex;
  align-items: baseline;
  justify-content: flex-end;
}

._label_1hmgl_28 {
  font-family: var(--font);
  font-size: var(--font-size-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-secondary);
}

._input_1hmgl_43 {
  width: 100%;
  appearance: none;
  font-family: var(--font);
  font-size: var(--font-size-sm);
  padding: var(--space-sm) var(--space-md);
  border: var(--border-hairline) solid var(--section-border-faint);
  border-radius: var(--radius-default);
  background: var(--section-bg);
  color: var(--text-primary);
  outline: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
  box-sizing: border-box;
}

._input_1hmgl_43::placeholder {
  color: var(--text-tertiary);
}

._input_1hmgl_43:hover {
  border-color: var(--text-accent-soft);
}

._input_1hmgl_43:focus,
._input_1hmgl_43:focus-visible {
  border-color: var(--text-accent);
  box-shadow: 0 0 0 var(--rail) var(--surface-accent-tint);
}

/* Wraps an input that needs a trailing affordance (e.g. the eye toggle
 * on the password field). */
._inputWrap_1hmgl_74 {
  position: relative;
  display: flex;
  align-items: center;
}

._inputWrap_1hmgl_74 ._input_1hmgl_43 {
  padding-right: var(--space-2xl);
}

/* Canonical .helpButton icon-button recipe (§4): transparent ghost,
 * indigo glyph, indigo tint on hover. */
._eyeButton_1hmgl_86 {
  position: absolute;
  right: 0.4rem;
  top: 50%;
  transform: translateY(-50%);
  width: 2rem;
  height: 2rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  appearance: none;
  background: transparent;
  border: none;
  border-radius: var(--radius-default);
  color: var(--text-accent);
  font-family: var(--font);
  font-size: var(--font-size-sm);
  cursor: pointer;
  transition: background-color 0.15s ease;
}

._eyeButton_1hmgl_86:hover:not(:disabled) {
  background: var(--surface-accent-tint);
}

._eyeButton_1hmgl_86:focus-visible {
  outline: var(--border-emphasis) solid var(--text-accent);
  outline-offset: var(--border-emphasis);
}

._eyeButton_1hmgl_86:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

._hint_1hmgl_121 {
  margin: var(--space-2xs) 0 0;
  font-family: var(--font);
  font-size: var(--font-size-xs);
  color: var(--text-tertiary);
}

/* Primary CTA — §4 recipe: solid indigo, light text, indigo-soft on
 * hover. Full-width inside the card. */
._submit_1hmgl_130 {
  margin-top: var(--space-xs);
  width: 100%;
  padding: var(--space-sm) var(--space-lg);
  appearance: none;
  font-family: var(--font);
  font-size: var(--font-size-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-snug);
  background: var(--text-accent);
  color: var(--text-light);
  border: var(--border-hairline) solid var(--text-accent);
  border-radius: var(--radius-default);
  cursor: pointer;
  transition: background-color 0.18s ease, border-color 0.18s ease;
}

._submit_1hmgl_130:hover:not(:disabled) {
  background: var(--text-accent-soft);
  border-color: var(--text-accent-soft);
}

._submit_1hmgl_130:focus-visible {
  outline: var(--border-emphasis) solid var(--text-accent);
  outline-offset: var(--border-emphasis);
}

._submit_1hmgl_130:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* Inline link beside a label (e.g. "Forgot password?"). */
._inlineLink_1hmgl_163 {
  appearance: none;
  background: transparent;
  border: none;
  padding: 0;
  font-family: var(--font);
  font-size: var(--font-size-xs);
  font-weight: var(--weight-medium);
  color: var(--text-accent);
  cursor: pointer;
  transition: color 0.15s ease;
}

._inlineLink_1hmgl_163:hover {
  text-decoration: underline;
  text-underline-offset: 2px;
}

._inlineLink_1hmgl_163:focus-visible {
  outline: var(--border-emphasis) solid var(--text-accent);
  outline-offset: var(--border-emphasis);
  border-radius: var(--radius-default);
}

/* Secondary CTA — §4 ghost recipe: transparent, indigo text, faint
 * border, indigo tint + indigo border on hover. Full-width below the
 * primary submit (e.g. "Back to sign in" on the reset surface). */
._secondary_1hmgl_190 {
  margin-top: var(--space-xs);
  width: 100%;
  padding: var(--space-sm) var(--space-lg);
  appearance: none;
  background: transparent;
  border: var(--border-hairline) solid var(--section-border-faint);
  border-radius: var(--radius-default);
  font-family: var(--font);
  font-size: var(--font-size-sm);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-snug);
  color: var(--text-accent);
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

._secondary_1hmgl_190:hover {
  background: var(--surface-accent-tint);
  border-color: var(--text-accent);
}

._secondary_1hmgl_190:focus-visible {
  outline: var(--border-emphasis) solid var(--text-accent);
  outline-offset: var(--border-emphasis);
}

/* Slim inline error — always rendered with reserved height so the
 * form's vertical rhythm is identical whether or not an error is
 * surfaced (no layout shift). When the slot becomes non-empty, the
 * message fades + rises into place with a subtle letter-spacing
 * settle — small premium polish that reads as deliberate rather
 * than alarming. Reduced motion is handled by the global gate in
 * index.css. */
._error_1hmgl_224 {
  margin: 0;
  min-height: 1.25rem;
  font-family: var(--font);
  font-size: var(--font-size-sm);
  line-height: var(--leading-snug);
  color: var(--status-urgent);
}

/* Luxurious arrival — long, monotonic out-expo interpolation that
 * mirrors the sign-in page's wordmark cadence: a soft de-focus from
 * blur and wider tracking, with an urgent-tinted halo that recedes
 * to nothing. No mid-animation jumps; one continuous breath so the
 * message reads as considered, not alarmed. */
._error_1hmgl_224:not(:empty) {
  animation: _errorEnter_1hmgl_1 1600ms cubic-bezier(0.16, 1, 0.3, 1) both;
}

@keyframes _errorEnter_1hmgl_1 {
  from {
    opacity: 0;
    transform: translateY(-4px);
    filter: blur(6px);
    letter-spacing: var(--tracking-wide);
    text-shadow: 0 0 18px var(--status-urgent);
  }
  to {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
    letter-spacing: 0;
    text-shadow: 0 0 0 transparent;
  }
}

/* Dual-state status line — used by the sign-in form. Hosts two
 * stacked spans (pending, error) that cross-fade between each other
 * via transition. Keeping both rendered (rather than swapping a
 * single element) lets the outgoing message recede as the incoming
 * one settles in — a continuous, luxurious handoff instead of a
 * snap. Container reserves height so the form's vertical rhythm is
 * stable whether the slot is empty, pending, or showing an error.
 * Reduced-motion is handled by the global gate in index.css. */
._statusLine_1hmgl_267 {
  position: relative;
  min-height: 1.25rem;
  line-height: var(--leading-snug);
}

._statusPending_1hmgl_273,
._statusError_1hmgl_274 {
  position: absolute;
  inset: 0;
  display: block;
  font-family: var(--font);
  font-size: var(--font-size-sm);
  line-height: var(--leading-snug);
  opacity: 0;
  transform: translateY(-4px);
  filter: blur(6px);
  letter-spacing: var(--tracking-wide);
  pointer-events: none;
  /* 1100ms out-expo — long enough for the de-focus to feel deliberate,
   * short enough that the user isn't left waiting for either message
   * to commit. Letter-spacing transitions alongside opacity/blur so
   * the settle reads as a single coherent motion. */
  transition:
    opacity 1100ms cubic-bezier(0.16, 1, 0.3, 1),
    transform 1100ms cubic-bezier(0.16, 1, 0.3, 1),
    filter 1100ms cubic-bezier(0.16, 1, 0.3, 1),
    letter-spacing 1100ms cubic-bezier(0.16, 1, 0.3, 1),
    text-shadow 1100ms cubic-bezier(0.16, 1, 0.3, 1);
}

._statusPending_1hmgl_273 {
  color: var(--text-tertiary);
}

._statusError_1hmgl_274 {
  color: var(--status-urgent);
  text-shadow: 0 0 18px var(--status-urgent);
}

._statusVisible_1hmgl_307 {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
  letter-spacing: 0;
  text-shadow: 0 0 0 transparent;
}

._success_1hmgl_315 {
  text-align: center;
  padding: var(--space-xs) 0 var(--space-2xs);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

._successTitle_1hmgl_323 {
  margin: 0;
  font-family: var(--font);
  font-size: var(--font-size-base);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  color: var(--text-primary);
}

._successBody_1hmgl_332 {
  margin: 0;
  font-family: var(--font);
  font-size: var(--font-size-sm);
  line-height: var(--leading-normal);
  color: var(--text-secondary);
}
/* Sign-in page — centered single-card composition on the canonical
 * --section-bg-alt surface. Whitelist tokens only; reduced-motion
 * handled by the global gate in index.css.
 *
 * Composition: a generous vertical column with brand wordmark above,
 * sign-in card below, fine-print footer at the bottom. A subtle
 * indigo radial gradient on the page background gives the surface
 * ambient depth without competing with the card. */

._page_hd6q2_10 {
  position: relative;
  min-height: 100svh;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3rem clamp(1.25rem, 4vw, 3rem);/* deliberate display literal */
  box-sizing: border-box;
  background: var(--surface-elevated);
  /* Soft indigo aura — places a quiet glow behind the card so the
   * white card has something to lift above. Uses the whitelisted
   * --surface-accent-tint (indigo @ 0.10), not a custom recipe. */
  background-image: radial-gradient(
    ellipse 60rem 40rem at 50% 35%,
    var(--surface-accent-tint) 0%,
    transparent 70%
  );
  overflow: hidden;
}

/* Full-page glass veil — a single full-bleed frosted plane laid over
 * the entire flight-path backdrop, edge to edge, so there's no panel
 * rim slicing across arcs or label pills. Sits above the z-0 backdrop
 * and below the z-1 shell, so its blur calms the whole animation while
 * the sign-in column stays perfectly crisp on top. Lighter tint than a
 * contained panel (it covers everything) but a heavy blur keeps it
 * glassy. Theme-flips via --surface-elevated. */
._page_hd6q2_10::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: rgb(from var(--surface-elevated) r g b / 0.08);
  /* `-webkit-` prefix for Safari < 18, standard property for Chrome/modern.
   * These survive minification intact only because vite.config pins
   * `build.cssMinify: 'esbuild'` — Vite 8's default Lightning CSS minifier
   * drops the standard `backdrop-filter` here and Chrome ignores the
   * `-webkit-` form (vitejs/vite#22649). */
  -webkit-backdrop-filter: blur(3px) saturate(108%);
  backdrop-filter: blur(3px) saturate(108%);
  pointer-events: none;
}

/* Flight-path backdrop — a full-bleed SVG of thin dashed great-circle
 * arcs that slowly draw themselves across the page, evoking an ATC
 * route map. Sits below content (z-index 0; .shell is lifted to 1).
 * Animated stroke-dashoffset is the only motion; the global
 * reduced-motion gate in index.css collapses it. */
._backdrop_hd6q2_59 {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}

._backdrop_hd6q2_59 svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* Background flight legs — every arc is a self-contained group
 * (path + start/end dots + center label pill) that fades in, holds,
 * and fades out as one continuous beat. The React tick loop unmounts
 * legs at end-of-life and spawns fresh ones between airports drawn
 * from the inline catalog projected onto the viewport — so the
 * network keeps reshaping without ever repeating the exact same
 * composition. Mirrors the mission map's "other flights" rendering:
 * thin, dashed, low-contrast gray. */
._arc_hd6q2_85 {
  opacity: 0;
  animation: _arcLife_hd6q2_1 linear;
}

._arcPath_hd6q2_90 {
  fill: none;
  stroke: var(--text-tertiary);
  stroke-width: 1.25;
  stroke-linecap: round;
  stroke-dasharray: 5 8;
}

._arcDot_hd6q2_98 {
  fill: var(--text-tertiary);
}

/* Active mission — the focal flight. Solid green line over a soft
 * green glow halo, with dashed search-radius rings at the origin
 * (patient, green) and destination (indigo) endpoints. The line
 * traces itself in via stroke-dashoffset on a slow loop. */
._activeMission_hd6q2_106 {
  opacity: 0;
  animation: _missionEnter_hd6q2_1 2400ms cubic-bezier(0.16, 1, 0.3, 1) 1200ms both;
}

._missionGlow_hd6q2_111 {
  fill: none;
  stroke: var(--text-accent-secondary);
  stroke-width: 8;
  stroke-linecap: round;
  opacity: 0.18;
}

._missionLine_hd6q2_119 {
  fill: none;
  stroke: var(--text-accent-secondary);
  stroke-width: 2.5;
  stroke-linecap: round;
  opacity: 0.85;
  stroke-dasharray: 1400;
  stroke-dashoffset: 1400;
  animation: _missionTrace_hd6q2_1 18s cubic-bezier(0.65, 0, 0.35, 1) 1500ms;
}

._searchRingOrigin_hd6q2_130 {
  fill: var(--text-accent-secondary);
  fill-opacity: 0.08;
  stroke: var(--text-accent-secondary);
  stroke-width: 1;
  stroke-dasharray: 5 5;
  opacity: 0.55;
}

._searchRingDest_hd6q2_139 {
  fill: var(--text-accent);
  fill-opacity: 0.06;
  stroke: var(--text-accent);
  stroke-width: 1;
  stroke-dasharray: 5 5;
  opacity: 0.55;
}

/* Active mission endpoint dots — slightly larger than the muted
 * background dots, tinted to match their respective rings. */
._missionDotOrigin_hd6q2_150 {
  fill: var(--text-accent-secondary);
}

._missionDotDest_hd6q2_154 {
  fill: var(--text-accent);
}

/* Active mission's PATIENT / DEST endpoint pills — same shape as
 * route labels but tinted to match their respective rings. */
._activeLabels_hd6q2_160 {
  opacity: 0;
  animation: _missionEnter_hd6q2_1 2200ms cubic-bezier(0.16, 1, 0.3, 1) 2200ms both;
}

._originPill_hd6q2_165 {
  fill: var(--section-bg);
  stroke: var(--text-accent-secondary);
  stroke-width: 1;
  stroke-dasharray: 3 3;
}

._originText_hd6q2_172 {
  fill: var(--text-accent-secondary);
  font-family: var(--mono);
  font-size: var(--font-size-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wide);
  text-anchor: middle;
  text-transform: uppercase;
}

._destPill_hd6q2_182 {
  fill: var(--section-bg);
  stroke: var(--text-accent);
  stroke-width: 1;
  stroke-dasharray: 3 3;
}

._destText_hd6q2_189 {
  fill: var(--text-accent);
  font-family: var(--mono);
  font-size: var(--font-size-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wide);
  text-anchor: middle;
  text-transform: uppercase;
}

._shell_hd6q2_56 {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 24rem;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-lg);
  animation: _pageEnterFade_hd6q2_1 var(--page-enter-duration) var(--page-enter-ease)
    both;
}

._brand_hd6q2_212 {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
  text-align: center;
}

/* Entrance choreography — the form arrives first so the user can
 * begin scanning credentials immediately, the tagline whispers in
 * underneath, and the wordmark lands last as the deliberate
 * headline beat. Long durations + a soft out-expo curve keep the
 * cadence unhurried and continuous — no abrupt mid-animation jumps. */
._formBlock_hd6q2_225 {
  animation: _formBlockEnter_hd6q2_1 1800ms cubic-bezier(0.16, 1, 0.3, 1) 200ms both;
}

/* View-transition target — the Sign-in ↔ Reset swap is driven by
 * the View Transition API (see SignInPage.tsx). The browser captures
 * before/after snapshots of this element and cross-fades them via
 * the ::view-transition-old/new(auth-form) rules below. The initial
 * page-load arrival is handled by .formBlock's formBlockEnter; this
 * wrapper carries no entrance animation of its own. */
._formSwap_hd6q2_235 {
  view-transition-name: auth-form;
}

::view-transition-old(auth-form),
::view-transition-new(auth-form) {
  animation-duration: 900ms;
  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
  animation-fill-mode: both;
}

::view-transition-old(auth-form) {
  animation-name: _authFormOldOut_hd6q2_1;
}

::view-transition-new(auth-form) {
  animation-name: _authFormNewIn_hd6q2_1;
}

@keyframes _authFormOldOut_hd6q2_1 {
  from {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
  }
  to {
    opacity: 0;
    transform: translateY(-6px);
    filter: blur(6px);
  }
}

@keyframes _authFormNewIn_hd6q2_1 {
  from {
    opacity: 0;
    transform: translateY(8px);
    filter: blur(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
  }
}

._tagline_hd6q2_280 {
  animation: _taglineEnter_hd6q2_1 1600ms cubic-bezier(0.16, 1, 0.3, 1) 1100ms both;
}

/* Wordmark — the showpiece. A single, slow, monotonic interpolation
 * from a wide-tracked, softly blurred whisper to its final settled
 * state. No mid-animation glow bursts, no scale snaps — just a
 * patient 3-second arrival on out-expo easing. */
._wordmark_hd6q2_288 {
  animation: _wordmarkEnter_hd6q2_1 3200ms cubic-bezier(0.16, 1, 0.3, 1) 2200ms both;
}

/* TOKEN GAP: display-scale wordmark — no whitelisted --font-size-*
 * token expresses brand wordmark sizes (precedent: MatchesPage
 * `.heroValue` 3.5rem). Letter-spacing tuned for the wordmark's
 * proportions, weight 600 for confident presence. */
._wordmark_hd6q2_288 {
  margin: 0;
  font-family: var(--font);
  font-size: 1.75rem; /* deliberate display literal */
  font-weight: var(--weight-semibold);
  line-height: var(--leading-none);
  letter-spacing: var(--tracking-tight);
  color: var(--text-accent);
}

._tagline_hd6q2_280 {
  margin: 0;
  font-family: var(--font);
  font-size: var(--font-size-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-tertiary);
}

/* Form block baked into the page — no card chrome. Vertical rhythm
 * alone composes the heading + form on the page surface; the inputs
 * (white --section-bg) provide enough visual lift against the cool
 * --surface-elevated page background.
 *
 * `min-height` locks the block to a stable height across the
 * Sign-in / Reset / success states so the wordmark above never
 * shifts when the inner form swaps. Sized to the tallest form
 * (Sign-in, with the status line) plus breathing room; shorter
 * states leave quiet air beneath, which reads as composed rather
 * than empty. */
._formBlock_hd6q2_225 {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  min-height: 22rem;
}

@keyframes _pageEnterFade_hd6q2_1 {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes _pageEnterRise_hd6q2_1 {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes _wordmarkEnter_hd6q2_1 {
  from {
    opacity: 0;
    transform: translateY(6px);
    filter: blur(8px);
    letter-spacing: var(--tracking-caps);
  }
  to {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
    letter-spacing: var(--tracking-tight);
  }
}

@keyframes _taglineEnter_hd6q2_1 {
  from {
    opacity: 0;
    letter-spacing: var(--tracking-wide);
    transform: translateY(4px);
  }
  to {
    opacity: 1;
    letter-spacing: var(--tracking-caps);
    transform: translateY(0);
  }
}

@keyframes _formBlockEnter_hd6q2_1 {
  from {
    opacity: 0;
    transform: translateY(22px);
    filter: blur(6px);
  }
  55% {
    filter: blur(0);
  }
  to {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
  }
}

/* Arc lifecycle — the whole group (path + dots + label) fades in,
 * holds at its per-arc peak, then fades out. Peak opacity is driven
 * by a per-arc CSS variable so each leg settles at its own
 * intensity without flattening into a uniform mat. */
@keyframes _arcLife_hd6q2_1 {
  0% {
    opacity: 0;
  }
  18% {
    opacity: var(--arc-peak, 0.2);
  }
  72% {
    opacity: var(--arc-peak, 0.2);
  }
  100% {
    opacity: 0;
  }
}

@keyframes _missionEnter_hd6q2_1 {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* Mission line tracing — slow draw across, hold, fade-out via
 * dashoffset, then loop. Long duration so it feels deliberate. */
@keyframes _missionTrace_hd6q2_1 {
  0% {
    stroke-dashoffset: 1400;
  }
  35% {
    stroke-dashoffset: 0;
  }
  75% {
    stroke-dashoffset: 0;
    opacity: 0.85;
  }
  100% {
    stroke-dashoffset: -1400;
    opacity: 0;
  }
}

._form_1u5gn_1 {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

._field_1u5gn_7 {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

._label_1u5gn_13 {
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  font-size: var(--font-size-2xs);
  font-weight: var(--weight-semibold);
  color: rgb(from var(--text-primary) r g b / 0.5);
}

._select_1u5gn_21 {
  appearance: none;
  background: var(--section-bg);
  border: var(--border-hairline) solid var(--section-border-faint);
  border-radius: var(--radius-default);
  padding: var(--space-xs) var(--space-sm);
  font-family: var(--font);
  font-size: var(--font-size-sm);
  color: var(--text-primary);
  cursor: pointer;
}

._select_1u5gn_21:focus-visible {
  outline: var(--border-emphasis) solid var(--text-accent);
  outline-offset: var(--border-emphasis);
}

._dropzone_1u5gn_38 {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  text-align: center;
  border: 1.5px dashed var(--section-border-faint);
  border-radius: var(--radius-default);
  padding: var(--space-lg) var(--space-md);
  cursor: pointer;
  color: var(--text-tertiary);
  font-size: var(--font-size-sm);
  transition:
    border-color 200ms ease,
    background-color 200ms ease;
}

._dropzone_1u5gn_38:hover,
._dropzoneActive_1u5gn_57 {
  border-color: var(--text-accent);
  background: rgb(from var(--text-accent) r g b / 0.06);
}

._dropzone_1u5gn_38:focus-within {
  outline: var(--border-emphasis) solid var(--text-accent);
  outline-offset: var(--border-emphasis);
}

._fileName_1u5gn_67 {
  font-family: var(--mono);
  font-size: var(--font-size-sm);
  color: var(--text-primary);
  overflow-wrap: anywhere;
}

._hint_1u5gn_74 {
  font-size: var(--font-size-xs);
  color: var(--text-tertiary);
}

._hiddenInput_1u5gn_79 {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;/* deliberate display literal */
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

._actions_1u5gn_91 {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-xs);
}

._result_1u5gn_97 {
  font-size: var(--font-size-sm);
  color: var(--status-success);
  overflow-wrap: anywhere;
}

._resultError_1u5gn_103 {
  font-size: var(--font-size-sm);
  color: var(--status-urgent);
  overflow-wrap: anywhere;
}

._empty_1u5gn_109 {
  font-size: var(--font-size-sm);
  color: var(--text-tertiary);
}

/* Dropped-row report. Scrolls rather than growing the modal past the viewport
   — a systematically bad file reports up to fifty rows. */
._issues_1u5gn_116 {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  max-height: 12rem;
  overflow-y: auto;
  padding: var(--space-xs) var(--space-sm);
  border: var(--border-hairline) solid var(--section-border-faint);
  border-radius: var(--radius-default);
  background: var(--section-bg-alt);
}

._issuesTitle_1u5gn_128 {
  font-size: var(--font-size-xs);
  font-weight: var(--weight-semibold);
  color: var(--text-secondary);
}

._issue_1u5gn_116 {
  display: flex;
  gap: var(--space-xs);
  font-size: var(--font-size-xs);
  color: var(--text-secondary);
  overflow-wrap: anywhere;
}

._issueLine_1u5gn_142 {
  flex: none;
  font-family: var(--mono);
  color: var(--text-tertiary);
}
._form_r2ds1_1 {
  display: contents;
}

._subjectLine_r2ds1_5 {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  margin: 0 0 var(--space-xs);
}

/* `overflow-wrap: anywhere` allows breaking inside an unspaced string
 * (long display names, pasted gibberish, very long emails). Without
 * it the text overflows the dialog. `min-width: 0` lets the flex
 * column give up shrink-floor so the browser actually breaks rather
 * than pushing siblings sideways. */
._subjectName_r2ds1_17 {
  font-family: var(--font);
  font-size: var(--font-size-base);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
  overflow-wrap: anywhere;
  min-width: 0;
}

._subjectEmail_r2ds1_26 {
  font-size: var(--font-size-xs);
  color: var(--text-tertiary);
  overflow-wrap: anywhere;
  min-width: 0;
}

._note_r2ds1_33 {
  font-size: var(--font-size-sm);
  color: rgb(from var(--text-primary) r g b / 0.7);
  line-height: var(--leading-normal);
  margin: 0 0 var(--space-xs);
}

._field_r2ds1_40 {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

._label_r2ds1_46 {
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  font-size: var(--font-size-2xs);
  font-weight: var(--weight-semibold);
  color: rgb(from var(--text-primary) r g b / 0.5);
}

._inputWrap_r2ds1_54 {
  position: relative;
  display: flex;
  align-items: center;
}

._input_r2ds1_54 {
  flex: 1;
  background: var(--section-bg);
  border: var(--border-hairline) solid var(--section-line-faint);
  border-radius: var(--radius-default);
  padding: var(--space-xs) var(--space-xl) var(--space-xs) var(--space-sm);
  font-family: var(--font);
  font-size: var(--font-size-sm);
  color: var(--text-primary);
  letter-spacing: var(--tracking-wide);
  transition: border-color 200ms ease, box-shadow 200ms ease;
}

._input_r2ds1_54:focus-visible {
  outline: none;
  border-color: var(--text-accent);
  box-shadow: 0 0 0 var(--rail) rgb(from var(--text-accent) r g b / 0.18);
}

._input_r2ds1_54:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

._eyeButton_r2ds1_84 {
  position: absolute;
  right: 0.5rem;
  top: 50%;
  transform: translateY(-50%);
  background: transparent;
  border: none;
  color: var(--text-tertiary);
  width: 1.8rem;
  height: 1.8rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-default);
  cursor: pointer;
  transition: color 160ms ease, background-color 160ms ease;
}

._eyeButton_r2ds1_84:hover:not(:disabled) {
  color: var(--text-primary);
  background: rgb(from var(--text-primary) r g b / 0.06);
}

._eyeButton_r2ds1_84:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

._hint_r2ds1_112 {
  font-size: var(--font-size-xs);
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}

._hintWarn_r2ds1_118 {
  color: var(--status-warning);
}

._error_r2ds1_122 {
  font-size: var(--font-size-sm);
  color: var(--status-urgent);
  background: rgb(from var(--status-urgent) r g b / 0.1);
  padding: var(--space-xs) var(--space-sm);
  border-radius: var(--radius-default);
  margin: 0;
  line-height: var(--leading-snug);
}

._success_r2ds1_132 {
  font-size: var(--font-size-sm);
  color: var(--status-success);
  background: rgb(from var(--status-success) r g b / 0.12);
  padding: var(--space-xs) var(--space-sm);
  border-radius: var(--radius-default);
  margin: 0;
  font-weight: var(--weight-medium);
}

._btn_r2ds1_142 {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  background: var(--text-accent);
  border: var(--border-hairline) solid var(--text-accent);
  color: var(--text-light);
  padding: var(--space-xs) var(--space-md);
  border-radius: var(--radius-default);
  font-family: var(--font);
  font-size: var(--font-size-sm);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-snug);
  cursor: pointer;
  transition:
    background-color 200ms ease,
    border-color 200ms ease,
    opacity 200ms ease;
}

._btn_r2ds1_142:hover:not(:disabled) {
  background: color-mix(in srgb, var(--text-accent) 88%, var(--text-light));
  border-color: color-mix(in srgb, var(--text-accent) 88%, var(--text-light));
}

._btn_r2ds1_142:focus-visible {
  outline: var(--border-emphasis) solid var(--text-accent);
  outline-offset: var(--border-emphasis);
}

._btn_r2ds1_142:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

._btnGhost_r2ds1_177 {
  background: transparent;
  color: var(--text-h);
  border-color: var(--section-line-faint);
}

._btnGhost_r2ds1_177:hover:not(:disabled) {
  background: rgb(from var(--text-h) r g b / 0.04);
  border-color: var(--text-h);
}
._form_f8mob_1 {
  display: contents;
}

._subjectLine_f8mob_5 {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  margin: 0 0 var(--space-xs);
}

._subjectName_f8mob_12 {
  font-family: var(--font);
  font-size: var(--font-size-base);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
  overflow-wrap: anywhere;
  min-width: 0;
}

._subjectEmail_f8mob_21 {
  font-size: var(--font-size-xs);
  color: var(--text-tertiary);
  overflow-wrap: anywhere;
  min-width: 0;
}

._note_f8mob_28 {
  font-size: var(--font-size-sm);
  color: rgb(from var(--text-primary) r g b / 0.7);
  line-height: var(--leading-normal);
  margin: 0 0 var(--space-xs);
}

/* Two-column grid lays the 6 roles out as 3 rows × 2 cols on the md
 * modal. On narrow viewports the grid collapses to a single column so
 * each option keeps room for its title + description. */
._list_f8mob_38 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-xs);
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (max-width: 900px) /* BP_COMPACT */ {
  ._list_f8mob_38 {
    grid-template-columns: 1fr;
  }
}

/* Each row is a clickable label wrapping a hidden native radio. The
 * radio itself is positioned off-screen but kept focusable so keyboard
 * users get arrow-key navigation + focus rings on the label. */
._option_f8mob_56 {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);
  padding: var(--space-sm) var(--space-sm);
  border: var(--border-hairline) solid var(--section-line-faint);
  border-radius: var(--radius-default);
  background: var(--section-bg);
  cursor: pointer;
  transition:
    border-color 200ms ease,
    background-color 200ms ease,
    box-shadow 200ms ease;
}

._option_f8mob_56:hover:not(._optionDisabled_f8mob_71) {
  border-color: rgb(from var(--text-h) r g b / 0.35);
  background: rgb(from var(--text-h) r g b / 0.04);
}

._optionSelected_f8mob_76 {
  border-color: var(--text-accent);
  background: rgb(from var(--text-accent) r g b / 0.08);
  box-shadow: 0 0 0 var(--rail) rgb(from var(--text-accent) r g b / 0.12);
}

._optionDisabled_f8mob_71 {
  opacity: 0.55;
  cursor: not-allowed;
}

._optionCurrent_f8mob_87 {
  border-color: rgb(from var(--text-primary) r g b / 0.25);
}

/* Custom radio mark — replaces the native circle to keep the row's
 * visual rhythm calm. We still rely on the native input for focus +
 * keyboard, hiding it via the wrapping label. */
._radio_f8mob_94 {
  position: relative;
  flex-shrink: 0;
  width: 1rem;
  height: 1rem;
  border-radius: 50%;
  border: 1.5px solid rgb(from var(--text-primary) r g b / 0.35);
  margin-top: var(--space-2xs);
  transition: border-color 160ms ease;
}

._optionSelected_f8mob_76 ._radio_f8mob_94 {
  border-color: var(--text-accent);
}

._optionSelected_f8mob_76 ._radio_f8mob_94::after {
  content: "";
  position: absolute;
  inset: 2.5px;
  border-radius: 50%;
  background: var(--text-accent);
}

._nativeRadio_f8mob_117 {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* Focus ring on the parent label when the hidden radio has focus. */
._option_f8mob_56:has(._nativeRadio_f8mob_117:focus-visible) {
  outline: var(--border-emphasis) solid var(--text-accent);
  outline-offset: var(--border-emphasis);
}

._optionBody_f8mob_131 {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  min-width: 0;
}

._optionTitle_f8mob_138 {
  display: flex;
  align-items: baseline;
  gap: var(--space-xs);
  font-size: var(--font-size-sm);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
}

._currentChip_f8mob_147 {
  font-size: var(--font-size-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  padding: var(--space-2xs) var(--space-xs);
  border-radius: var(--radius-default);
  background: rgb(from var(--text-primary) r g b / 0.1);
  color: rgb(from var(--text-primary) r g b / 0.7);
}

._optionDesc_f8mob_158 {
  font-size: var(--font-size-xs);
  color: rgb(from var(--text-primary) r g b / 0.62);
  line-height: var(--leading-snug);
}

._error_f8mob_164 {
  font-size: var(--font-size-sm);
  color: var(--status-urgent);
  background: rgb(from var(--status-urgent) r g b / 0.1);
  padding: var(--space-xs) var(--space-sm);
  border-radius: var(--radius-default);
  margin: var(--space-xs) 0 0;
  line-height: var(--leading-snug);
}

._warn_f8mob_174 {
  font-size: var(--font-size-xs);
  color: var(--status-warning);
  background: rgb(from var(--status-warning) r g b / 0.12);
  padding: var(--space-xs) var(--space-sm);
  border-radius: var(--radius-default);
  margin: var(--space-xs) 0 0;
  line-height: var(--leading-snug);
}

._success_f8mob_184 {
  font-size: var(--font-size-sm);
  color: var(--status-success);
  background: rgb(from var(--status-success) r g b / 0.12);
  padding: var(--space-xs) var(--space-sm);
  border-radius: var(--radius-default);
  margin: var(--space-xs) 0 0;
  font-weight: var(--weight-medium);
}

._btn_f8mob_194 {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  background: var(--text-accent);
  border: var(--border-hairline) solid var(--text-accent);
  color: var(--text-light);
  padding: var(--space-xs) var(--space-md);
  border-radius: var(--radius-default);
  font-family: var(--font);
  font-size: var(--font-size-sm);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-snug);
  cursor: pointer;
  transition:
    background-color 200ms ease,
    border-color 200ms ease,
    opacity 200ms ease;
}

._btn_f8mob_194:hover:not(:disabled) {
  background: color-mix(in srgb, var(--text-accent) 88%, var(--text-light));
  border-color: color-mix(in srgb, var(--text-accent) 88%, var(--text-light));
}

._btn_f8mob_194:focus-visible {
  outline: var(--border-emphasis) solid var(--text-accent);
  outline-offset: var(--border-emphasis);
}

._btn_f8mob_194:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* Armed-confirmation state for admin downgrade. Mirrors the danger
 * palette used by ConfirmButton when arming, so the visual language is
 * consistent across the admin surface. */
._btnArmed_f8mob_232 {
  background: var(--status-urgent);
  border-color: var(--status-urgent);
}

._btnArmed_f8mob_232:hover:not(:disabled) {
  background: color-mix(in srgb, var(--status-urgent) 88%, #000); /* deliberate display literal */
  border-color: color-mix(in srgb, var(--status-urgent) 88%, #000); /* deliberate display literal */
}

._btnGhost_f8mob_242 {
  background: transparent;
  color: var(--text-h);
  border-color: var(--section-line-faint);
}

._btnGhost_f8mob_242:hover:not(:disabled) {
  background: rgb(from var(--text-h) r g b / 0.04);
  border-color: var(--text-h);
}
