/* ⚠️  GENERATED FILE — DO NOT EDIT BY HAND.
   Source of truth: design/tokens.json
   Regenerate:      node next-os/design/generate-tokens.mjs
   CI gate:         ./gradlew :composeApp:checkDesignTokens (fails on drift)

   These CSS custom properties mirror the Compose theme so Phase 4's DOM <input>
   overlays (HtmlElementView) can be styled to match the canvas exactly. Brand
   seeds are the DEFAULTS; a tenant brandColor overrides --vf-brand-primary at
   runtime (set on :root from JS), just as it overrides primary in Compose. */

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('inter-variable.woff2') format('woff2');
}

:root {
  color-scheme: light dark;

  /* Brand seeds (tenant-overridable) */
  --vf-brand-primary: #5B6CFF;
  --vf-brand-secondary: #8B5CF6;
  --vf-brand-accent: #22C7D9;

  /* Font */
  --vf-font-family: 'Inter', system-ui, -apple-system, sans-serif;
  --vf-font-feature-tabular: 'tnum' 1;

  /* Spacing */
  --vf-space-xxs: 2px;
  --vf-space-xs: 4px;
  --vf-space-sm: 8px;
  --vf-space-md: 12px;
  --vf-space-lg: 16px;
  --vf-space-xl: 20px;
  --vf-space-xxl: 24px;
  --vf-space-xxxl: 32px;
  --vf-space-gutter: 20px;

  /* Radii */
  --vf-radius-xs: 4px;
  --vf-radius-sm: 6px;
  --vf-radius-md: 8px;
  --vf-radius-lg: 12px;
  --vf-radius-pill: 999px;

  /* Motion */
  --vf-motion-instant: 80ms;
  --vf-motion-fast: 140ms;
  --vf-motion-normal: 220ms;
  --vf-motion-slow: 360ms;

  /* Typography scale */
  --vf-type-display-small-size: 26px;
  --vf-type-display-small-line: 31px;
  --vf-type-display-small-tracking: -0.45px;
  --vf-type-display-small-weight: 700;
  --vf-type-headline-medium-size: 24px;
  --vf-type-headline-medium-line: 28px;
  --vf-type-headline-medium-tracking: -0.4px;
  --vf-type-headline-medium-weight: 700;
  --vf-type-headline-small-size: 20px;
  --vf-type-headline-small-line: 24px;
  --vf-type-headline-small-tracking: -0.25px;
  --vf-type-headline-small-weight: 700;
  --vf-type-title-large-size: 22px;
  --vf-type-title-large-line: 26px;
  --vf-type-title-large-tracking: -0.4px;
  --vf-type-title-large-weight: 700;
  --vf-type-title-medium-size: 15px;
  --vf-type-title-medium-line: 20px;
  --vf-type-title-medium-tracking: -0.1px;
  --vf-type-title-medium-weight: 600;
  --vf-type-title-small-size: 13px;
  --vf-type-title-small-line: 18px;
  --vf-type-title-small-tracking: 0px;
  --vf-type-title-small-weight: 600;
  --vf-type-body-large-size: 15px;
  --vf-type-body-large-line: 21px;
  --vf-type-body-large-tracking: 0px;
  --vf-type-body-large-weight: 400;
  --vf-type-body-medium-size: 13px;
  --vf-type-body-medium-line: 18px;
  --vf-type-body-medium-tracking: 0px;
  --vf-type-body-medium-weight: 400;
  --vf-type-body-small-size: 12px;
  --vf-type-body-small-line: 16px;
  --vf-type-body-small-tracking: 0.1px;
  --vf-type-body-small-weight: 400;
  --vf-type-label-large-size: 13px;
  --vf-type-label-large-line: 16px;
  --vf-type-label-large-tracking: 0.1px;
  --vf-type-label-large-weight: 600;
  --vf-type-label-medium-size: 11px;
  --vf-type-label-medium-line: 14px;
  --vf-type-label-medium-tracking: 0.4px;
  --vf-type-label-medium-weight: 600;
  --vf-type-label-small-size: 10px;
  --vf-type-label-small-line: 13px;
  --vf-type-label-small-tracking: 0.6px;
  --vf-type-label-small-weight: 600;
}

/* Light mode (default) neutrals + semantic + flat cockpit surfaces */
:root, :root[data-theme='light'] {
  --vf-neutral-page: #F4F6F9;
  --vf-neutral-card: #FFFFFF;
  --vf-neutral-raised: #F8FAFC;
  --vf-neutral-overlay: #FFFFFF;
  --vf-neutral-border: #C6D0DC;
  --vf-neutral-border-variant: #D9E0E8;
  --vf-neutral-on-surface: #121821;
  --vf-neutral-on-surface-variant: #5B6675;
  --vf-neutral-rail: #EEF1F5;
  --vf-neutral-surface-hover: #E9EEF5;
  --vf-neutral-text-faint: #657386;
  --vf-success-container: #E3F1E8;
  --vf-success-on: #11663C;
  --vf-warning-container: #FBEEDA;
  --vf-warning-on: #8A4B0A;
  --vf-danger-container: #FBE7E4;
  --vf-danger-on: #9B1C1C;
  --vf-info-container: #E6ECF9;
  --vf-info-on: #2647A6;
  --vf-error-strong: #B42318;
  --vf-background: #F4F6F9;
  --vf-rail: #EEF1F5;
  --vf-surface: #FFFFFF;
  --vf-surface-raised: #F8FAFC;
  --vf-surface-hover: #E9EEF5;
  --vf-border-strong: #C6D0DC;
  --vf-text: #121821;
  --vf-text-muted: #5B6675;
  --vf-text-faint: #657386;
  --vf-success: #11663C;
  --vf-warning: #8A4B0A;
  --vf-danger: #9B1C1C;
  --vf-info: #2647A6;
}

/* Dark mode neutrals + semantic + flat cockpit surfaces — follows the system, overridable via data-theme */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
  --vf-neutral-page: #080C12;
  --vf-neutral-card: #0D121A;
  --vf-neutral-raised: #111823;
  --vf-neutral-overlay: #232834;
  --vf-neutral-border: #2A3747;
  --vf-neutral-border-variant: #202B38;
  --vf-neutral-on-surface: #F3F6FA;
  --vf-neutral-on-surface-variant: #98A4B3;
  --vf-neutral-rail: #080B11;
  --vf-neutral-surface-hover: #172131;
  --vf-neutral-text-faint: #667384;
  --vf-success-container: #16311F;
  --vf-success-on: #74E39C;
  --vf-warning-container: #352509;
  --vf-warning-on: #F5C368;
  --vf-danger-container: #381816;
  --vf-danger-on: #F4A29B;
  --vf-info-container: #17233F;
  --vf-info-on: #9CBAF6;
  --vf-error-strong: #F87171;
  --vf-background: #080C12;
  --vf-rail: #080B11;
  --vf-surface: #0D121A;
  --vf-surface-raised: #111823;
  --vf-surface-hover: #172131;
  --vf-border-strong: #2A3747;
  --vf-text: #F3F6FA;
  --vf-text-muted: #98A4B3;
  --vf-text-faint: #667384;
  --vf-success: #74E39C;
  --vf-warning: #F5C368;
  --vf-danger: #F4A29B;
  --vf-info: #9CBAF6;
  }
}
:root[data-theme='dark'] {
  --vf-neutral-page: #080C12;
  --vf-neutral-card: #0D121A;
  --vf-neutral-raised: #111823;
  --vf-neutral-overlay: #232834;
  --vf-neutral-border: #2A3747;
  --vf-neutral-border-variant: #202B38;
  --vf-neutral-on-surface: #F3F6FA;
  --vf-neutral-on-surface-variant: #98A4B3;
  --vf-neutral-rail: #080B11;
  --vf-neutral-surface-hover: #172131;
  --vf-neutral-text-faint: #667384;
  --vf-success-container: #16311F;
  --vf-success-on: #74E39C;
  --vf-warning-container: #352509;
  --vf-warning-on: #F5C368;
  --vf-danger-container: #381816;
  --vf-danger-on: #F4A29B;
  --vf-info-container: #17233F;
  --vf-info-on: #9CBAF6;
  --vf-error-strong: #F87171;
  --vf-background: #080C12;
  --vf-rail: #080B11;
  --vf-surface: #0D121A;
  --vf-surface-raised: #111823;
  --vf-surface-hover: #172131;
  --vf-border-strong: #2A3747;
  --vf-text: #F3F6FA;
  --vf-text-muted: #98A4B3;
  --vf-text-faint: #667384;
  --vf-success: #74E39C;
  --vf-warning: #F5C368;
  --vf-danger: #F4A29B;
  --vf-info: #9CBAF6;
}

/* ── Native DOM form controls (Compose/Wasm HtmlElementView) ───────────────
   This paint is generated into the stylesheet loaded in <head>, rather than
   injected by Kotlin after Wasm starts. Inputs/selects/date controls therefore
   have their final surface before the browser can show an autofill/UA frame. */
.vf-input {
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0 var(--vf-space-lg);
  border: 1px solid var(--vf-neutral-border);
  border-radius: var(--vf-radius-md);
  background: var(--vf-neutral-card);
  color: var(--vf-neutral-on-surface);
  font-family: var(--vf-font-family);
  /* iOS Safari force-zooms the page when a focused input is < 16px and never zooms
     back out. Floor the DOM-island font at 16px to prevent the focus-jump. max() keeps
     the token when it is already >= 16px, so the design system still wins on desktop.
     THIS BELONGS HERE, NOT IN tokens.css — that file is generated and hand-edits to it
     are reverted by the next run of this script. */
  font-size: max(16px, var(--vf-type-body-large-size));
  line-height: var(--vf-type-body-large-line);
  caret-color: var(--vf-brand-primary);
  outline: none;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color var(--vf-motion-fast) ease, box-shadow var(--vf-motion-fast) ease;
}
.vf-input::placeholder {
  color: var(--vf-neutral-on-surface-variant);
  opacity: 1;
}
.vf-input:hover:not(:disabled):not(:focus) {
  border-color: var(--vf-neutral-on-surface-variant);
}
.vf-input:focus {
  border-color: var(--vf-brand-primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--vf-brand-primary) 26%, transparent);
}
.vf-input::selection {
  background: color-mix(in srgb, var(--vf-brand-primary) 34%, transparent);
}
.vf-input:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  background: var(--vf-neutral-raised);
  color: var(--vf-neutral-on-surface-variant);
}
.vf-input[readonly] { background: var(--vf-neutral-raised); }
.vf-input--multiline {
  padding: var(--vf-space-md) var(--vf-space-lg);
  resize: vertical;
  min-height: 96px;
}
.vf-input--error { border-color: var(--vf-error-strong); }
.vf-input--error:focus {
  border-color: var(--vf-error-strong);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--vf-error-strong) 26%, transparent);
}

/* The event is functional, not visual: PlatformTextField listens for this 1ms
   animation to adopt password-manager values that arrive without input/change. */
@keyframes vf-autofill-detected {
  from { opacity: 0.99999; }
  to { opacity: 1; }
}

/* Autofill paint: cover the browser's yellow/blue fill from its first styled
   frame while retaining the designed text, caret, border, focus and error rings. */
.vf-input:-webkit-autofill,
.vf-input:-webkit-autofill:hover,
.vf-input:-webkit-autofill:focus,
.vf-input:-webkit-autofill:active {
  animation: vf-autofill-detected 1ms both;
  -webkit-text-fill-color: var(--vf-neutral-on-surface) !important;
  -webkit-box-shadow: 0 0 0 1000px var(--vf-neutral-card) inset !important;
  box-shadow: 0 0 0 1000px var(--vf-neutral-card) inset !important;
  caret-color: var(--vf-brand-primary);
  border-color: var(--vf-neutral-border);
  transition: background-color 9999s ease-out 0s;
}
.vf-input:-webkit-autofill:focus {
  border-color: var(--vf-brand-primary);
  -webkit-box-shadow:
    0 0 0 1000px var(--vf-neutral-card) inset,
    0 0 0 3px color-mix(in srgb, var(--vf-brand-primary) 26%, transparent) !important;
  box-shadow:
    0 0 0 1000px var(--vf-neutral-card) inset,
    0 0 0 3px color-mix(in srgb, var(--vf-brand-primary) 26%, transparent) !important;
}
.vf-input.vf-input--error:-webkit-autofill,
.vf-input.vf-input--error:-webkit-autofill:focus {
  border-color: var(--vf-error-strong);
}
.vf-input.vf-input--error:-webkit-autofill:focus {
  -webkit-box-shadow:
    0 0 0 1000px var(--vf-neutral-card) inset,
    0 0 0 3px color-mix(in srgb, var(--vf-error-strong) 26%, transparent) !important;
  box-shadow:
    0 0 0 1000px var(--vf-neutral-card) inset,
    0 0 0 3px color-mix(in srgb, var(--vf-error-strong) 26%, transparent) !important;
}
.vf-input:-moz-autofill {
  color: var(--vf-neutral-on-surface);
  box-shadow: 0 0 0 1000px var(--vf-neutral-card) inset !important;
  caret-color: var(--vf-brand-primary);
}

/* Select/date extensions share the same always-present .vf-input base. */
.vf-select {
  cursor: pointer;
  padding-right: calc(var(--vf-space-lg) + 18px);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%23808080' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right var(--vf-space-lg) center;
}
.vf-select:disabled { cursor: not-allowed; }
.vf-date { cursor: pointer; }
.vf-date::-webkit-calendar-picker-indicator { cursor: pointer; opacity: 0.7; }
.vf-date::-webkit-calendar-picker-indicator:hover { opacity: 1; }
:root[data-theme='dark'] .vf-date::-webkit-calendar-picker-indicator { filter: invert(1); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .vf-date::-webkit-calendar-picker-indicator { filter: invert(1); }
}

/* ── Canvas-overlay island suppression ────────────────────────────────────
   The whole UI paints into one Skiko <canvas>; text/select/date fields are the
   exception — real DOM elements (all carry .vf-input) mounted OVER the canvas, so they
   ALWAYS paint above it. A Compose overlay drawn INTO the canvas (the Modules sheet, the
   rail label panel) would therefore be punched through by any field beneath it. While
   such an overlay is open, Kotlin sets this body class (CanvasOverlayEffect,
   reference-counted); hide every island so the scrim + panel are the topmost thing and
   nothing bleeds through or steals a tap. visibility:hidden (not display:none) keeps
   Compose's interop layout stable, so the fields reappear in place the instant the
   overlay closes. Body-level DOM overlays (PlatformActionMenu / PlatformCommandPalette)
   do NOT set this class — they already sit above the islands at z-index 2147483000.
   scripts/ci/lint-nextos-overlay-layering.mjs asserts this rule exists. */
body.vf-canvas-overlay-open .vf-input:not(.vf-command-palette-input) {
  visibility: hidden !important;
  pointer-events: none !important;
}
