/* Tailwind v4 — modern utility classes + processes the SDK's
   `@theme static {}` token blocks so design tokens like
   --radius-full, --color-ring, --switch-* resolve natively
   (the SDK is built for Tailwind v4). */
@import "tailwindcss";
/* SDK CSS imported here (not from main.jsx) so Tailwind v4
   processes its @theme blocks as part of the same input chain.
   Importing as a JS module kept the SDK CSS outside Tailwind's
   pipeline and SDK design tokens silently resolved to empty. */
@import "@openai/apps-sdk-ui/css";

/* Self-hosted Inter and JetBrains Mono — served same-origin from
   /vendor/fonts/ so the shell renders correctly offline and without
   any Google Fonts network dependency. Latin subset only (covers
   all UI text); font-display: swap avoids FOIT on a cold load.
   Weights: Inter 400/500/600/700, JetBrains Mono 400/500.
   (Weight 450 appeared in the old Google Fonts URL but was never
   referenced in component CSS — omitted here.) */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/vendor/fonts/inter-400.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-036F, U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/vendor/fonts/inter-500.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-036F, U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/vendor/fonts/inter-600.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-036F, U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/vendor/fonts/inter-700.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-036F, U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/vendor/fonts/jetbrains-mono-400.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-036F, U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/vendor/fonts/jetbrains-mono-500.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-036F, U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}

/* Tailwind v4 custom variant: lets us write `light:` utility
   prefixes that compile to `[data-theme="light"]` scoped rules.
   Parallels Tailwind's built-in `dark:` variant. The `&:where(...)`
   wrap keeps specificity at 0 so utilities still lose to component
   CSS by ordinary cascade rules — only intentional `light:` usage
   layers on top. Matches both the themed element itself and any
   descendant, mirroring how the hand-written
   `[data-theme="light"] .foo` selectors work today. */
@custom-variant light (&:where([data-theme="light"], [data-theme="light"] *));

/* Universal reset, scoped to box-sizing + tap-highlight only.
   We previously zeroed margin + padding on every element — that
   overrode the apps-sdk-ui's component-layer rules like
   `.MenuList { padding: var(--menu-gutter) }` and made SDK
   menus render with no internal padding. Tailwind v4 Preflight
   already handles the common cases (body, h1, p, lists), so
   resetting everything universally was over-aggressive. */
*, *::before, *::after {
  box-sizing: border-box;
  /* Suppress the Android Chrome / iOS Safari tap-highlight on
     every interactive element. Tailwind v4 Preflight zeros
     border-radius on textareas/inputs, which makes the default
     tap-highlight render as a sharp rectangle — visible inside
     our rounded composer pill. The shell uses its own focus
     rings (`:focus-visible`) so we don't need this default. */
  -webkit-tap-highlight-color: transparent;
}

/* Manual margin/padding resets on the elements that matter to
   our layout. The previous `* { margin: 0; padding: 0 }` reset
   was a Bootstrap-era pattern that conflicts with SDK components
   shipping their own padding contracts. */
body, h1, h2, h3, h4, h5, h6, p, ul, ol, li, dl, dd, figure, blockquote, fieldset {
  margin: 0;
  padding: 0;
}

/* Restore the apps-sdk-ui components' internal padding tokens.
   Tailwind v4 Preflight emits an unlayered
   `*, ::after, ::before, ::backdrop { padding: 0 }` rule, which
   beats the SDK's component-layer `padding: var(--menu-gutter)`
   even though component-layer rules theoretically rank higher
   than base styles — Preflight is unlayered, so it actually wins.
   Targeting the SDK's hashed class-name patterns with attribute
   selectors gives us higher specificity than `*` so the SDK's
   own tokens drive component padding as intended. */
[class*=MenuList],
[class*=MenuContent] {
  padding: var(--menu-gutter, 0.375rem);
}
[class*=MenuItem]:not([class*=MenuItemContent]):not([class*=MenuItemActions]) {
  padding: var(--menu-item-padding, 0.375rem 0.5rem);
}

/* Always-hidden scrollbars across the whole app. The owner's standing
   preference: the on-scroll thin-bar reveal that lived here (toggled
   by the now-deleted useScrollbarAutohide hook via .is-scrolling on
   :root) is removed — scrollbars never show, in any surface. */
html, body, * { scrollbar-width: none; -ms-overflow-style: none; }
*::-webkit-scrollbar { width: 0; height: 0; }

/* Theme colors are injected server-side into <head> via theme.py.
   Do NOT define color variables here — they cause a flash to the
   wrong color before the server-injected theme takes effect.
   Only non-color defaults for dev mode (where server injection
   doesn't happen). */
:root {
  --font: 'Inter', system-ui, -apple-system, sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, 'SF Mono', monospace;
  /* Default to dark. Light-mode override below keeps native UA
     widgets (scrollbars, date picker, autofill background) in
     sync with the active theme. */
  color-scheme: dark;
  /* The SDK uses `--color-ring` as its keyboard focus-ring color.
     Map it to the Mobius accent so SDK controls + bespoke widgets
     share one focus language. (Tailwind v4 + the SDK's @theme
     define everything else we consume — radius, motion, switch
     defaults — so we only set what we want to OVERRIDE.) */
  --color-ring: var(--accent);
}

:root[data-theme="light"] {
  color-scheme: light;
}

html, body, #root {
  height: 100%;
  overflow: hidden;
  position: fixed;
  inset: 0;
  width: 100%;
}

/* Prevent iOS Safari (which ignores user-scalable=no in the viewport
   meta) from intercepting two-finger spread as a page-level pinch-zoom.
   pan-x pan-y allows one-finger scrolling; pinch-zoom is blocked at the
   document root. Elements that implement their own pinch (e.g.
   .lightbox-image) declare touch-action: none directly and override this. */
html, body {
  touch-action: pan-x pan-y;
}

/* Accessibility: respect prefers-reduced-motion. Collapses all
   transitions and animations to near-instant — the user has asked
   the OS to suppress non-essential motion. The shell + drawer +
   composer popovers all rely on transitions, so this rule has to
   live at the global level rather than per-component. Keeps a
   1ms duration (not 0) so transitionend events still fire and any
   logic gated on them continues to work. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}


/*
 * Shell fade-in animation.
 *
 * !! CRITICAL: DO NOT change "from { opacity: 0.95 }" to "opacity: 0" !!
 *
 * If the shell starts at opacity 0, the BODY background shows through.
 * The body background may not match the active theme (the CSS file's
 * default --bg loads before the server-injected theme CSS).  This
 * caused a "fade to dark/black" bug.
 *
 * Starting at 0.95 gives a subtle fade-in without ever exposing the
 * potentially-wrong body color underneath.
 */
.shell {
  animation: shellFadeIn 0.15s ease-out;
}

@keyframes shellFadeIn {
  from { opacity: 0.95; }
  to { opacity: 1; }
}

/* Prevent iOS auto-zoom on input focus (requires font-size >= 16px). */
input, textarea, select {
  font-size: 16px;
}

body {
  /* background is set inline on <body> and injected by the server
     to match the active theme.  Do NOT set it here — it causes a
     flash to the default color before the theme CSS loads. */
  color: var(--text);
  font-family: var(--font);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: 'cv01', 'ss01';
}

button {
  cursor: pointer;
  font-family: inherit;
  font-size: inherit;
  /* Mobile: kill the default translucent tap-highlight that flashes
     a selection-colored overlay around every button on press. We use
     :active for press feedback (see "Tap feedback" below) which is
     deliberate and theme-aware. */
  -webkit-tap-highlight-color: transparent;
  /* Prevent a button press from accidentally selecting the button's
     text content (long-press on mobile, drag on desktop). Doesn't
     block keyboard focus or click handlers. */
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

input, textarea {
  font-family: inherit;
  font-size: inherit;
}

/* Accessibility: keyboard-only focus ring on text inputs. Forms across
   the app (Setup, Login, Settings, Gemini key) remove the native
   outline and only swap border-color — fine for mouse/touch focus,
   but invisible to keyboard users on themes where the border color
   is close to the background. :focus-visible only fires for keyboard
   navigation (or screen-reader / programmatic focus), so the click
   path stays unchanged. */
input:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--accent, #8b6cf7);
  outline-offset: 1px;
}

/* ── Visual refinements ──
   Motion, gradients, selection, and drawer scrollbar rules. Kept in
   index.css rather than theme.css so the theme toggle (which rewrites
   theme.css with regenerated colors) doesn't strip them. */

:root {
  --spring: cubic-bezier(0.16, 1, 0.3, 1);
}

/* Message entry animation */
@keyframes msg-enter {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}
.chat__msg { animation: msg-enter 280ms var(--spring); }

/* Tool block entry — opacity only so height stays stable for spacer
   math (see CLAUDE.md "Chat UX — non-negotiable constraints"). */
@keyframes tool-enter {
  from { opacity: 0; }
  to { opacity: 1; }
}
.chat__tool { animation: tool-enter 200ms ease-out; }

/* Tap feedback on shell-bar buttons. Component-specific transitions
   for .chat__send, .chat__mic, .chat__stop, .drawer__item live in
   their own CSS files — `transition` is a shorthand that REPLACES,
   not extends, so listing them here would clobber the component
   contracts. The :active scale below still applies via the per-class
   selectors. */
.shell__bar button {
  transition: transform 100ms ease, background 180ms ease,
              color 180ms ease, border-color 180ms ease,
              box-shadow 180ms ease;
}
.chat__send:active,
.chat__mic:active,
.drawer__item:active,
.shell__bar button:active {
  transform: scale(0.96);
}

/* Drawer slide transition is owned by Drawer.css (SDK motion tokens). */

/* NOTE: the `.chat__form:focus-within` box-shadow that lived here
   was REMOVED. It drew an outer rectangle around the pill + +
   button when the textarea was focused — visible as a "bounding
   box" larger than the pill itself. The composer contract
   (ChatView.css invariant #6) says ONE focus halo, on
   `.chat__pill:focus-within` only. Do not reintroduce a form-
   level focus ring without re-reading that contract. */

/* Hide drawer scrollbars cleanly */
.drawer,
.drawer__body,
.drawer__group,
.drawer *[class*="scroll"] {
  scrollbar-width: none;
}
.drawer::-webkit-scrollbar,
.drawer__body::-webkit-scrollbar,
.drawer__group::-webkit-scrollbar,
.drawer *[class*="scroll"]::-webkit-scrollbar {
  width: 0;
  height: 0;
}

/* Gradient wordmark in the shell bar */
.shell__wordmark {
  background: linear-gradient(135deg, var(--text) 30%, var(--accent) 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

/* Gradient user message bubbles, white text */
.chat__text--user {
  background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 78%, black));
  color: #ffffff;
  box-shadow: 0 2px 14px -4px var(--accent-dim);
}

/* Gradient empty-state title */
.chat__empty-title {
  font-size: 30px;
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1.05;
  background: linear-gradient(135deg, var(--text) 30%, var(--accent) 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

/* High-contrast text selection so the highlight is visible on every
   theme (including custom dark themes). The accent-on-text combination
   was ~2.6:1 in dark mode — below AA for selection highlights. The
   color-mix treatment below matches the user-bubble override logic:
   a near-white (14% accent tint) background paired with a dark-accent
   foreground gives ~6:1 contrast on both dark and light themes. */
::selection {
  background: color-mix(in srgb, var(--accent, #8b6cf7) 14%, #fff);
  color: color-mix(in srgb, var(--accent, #8b6cf7) 78%, #000);
}

/* Your OWN messages sit on the accent-gradient bubble (see
   .chat__text--user), so the accent ::selection above is accent-on-accent
   — invisible. Invert it just here: a near-white (faint accent tint)
   highlight with dark-accent text, so the selection clearly pops against
   the purple bubble while staying on-brand. Scoped to the bubble so the
   global rule still governs selection everywhere else. */
.chat__text--user::selection,
.chat__text--user ::selection {
  background: color-mix(in srgb, var(--accent) 14%, #fff);
  color: color-mix(in srgb, var(--accent) 78%, #000);
}

/* ── Native-feel UI chrome pass ─────────────────────────
   user-select: none on non-content interactive surfaces so long-press
   and drag over them doesn't produce a text selection box.  Message /
   tool block content is EXCLUDED (stays selectable) — only shell
   chrome gets the lock.  buttons already get this via the rule above;
   these selectors cover labelled containers that aren't `<button>`. */

/* Shell header (logo, wordmark, brand area, offline pill). */
.shell__bar,
.shell__brand,
.shell__offline,
.shell__wordmark {
  user-select: none;
  -webkit-user-select: none;
}

/* Tool block header row (collapse toggle, status badge).  The block
   body that shows code / tool output stays selectable. */
.chat__tool-header,
.tool-block__header {
  user-select: none;
  -webkit-user-select: none;
}

/* Drawer header label rows, section labels, and action buttons. */
.drawer__label,
.drawer__new-label {
  user-select: none;
  -webkit-user-select: none;
}

/* ── Active-state press feedback ─────────────────────────
   Drawer items already get scale(0.96) from .drawer__item:active
   (defined in index.css above).  The send button (.chat__send) gets it
   too.  Ensure the shell-bar menu button also has a press scale so it
   reads as tappable on mobile. */
.menu-btn:active { transform: scale(0.93); }

/* ── @media (hover:hover) guard audit ─────────────────────
   Hover rules on shell-bar buttons are already gated via the
   .shell__bar button rule above using transition-only — no bare
   :hover fill changes exist there that need gating.  Drawer hover
   rules are already in @media (hover:hover) blocks (Drawer.css).
   No additional un-gated :hover rules were found in this file. */
