/*
 * Base styles — reset + global typography.
 * Imports tokens, then sets body/links/focus defaults.
 * Per-component styling lives in static/css/components/*.css.
 */
@import url("tokens.css");

html {
  font-family: var(--kw-font-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: var(--kw-fg);
  background: var(--kw-bg);
}

body {
  font-family: var(--kw-font-body);
  color: var(--kw-fg);
  /* The page colour lives on <html> (--kw-bg fills the viewport canvas, both
     themes). Body stays transparent so the fixed decorative backdrop (.kw-bg,
     z-index:-1 on dark public pages) is visible behind in-flow content. */
  background: transparent;
  min-height: 100vh;
}

/* Dark public-shell backdrop. Fixed, decorative, non-interactive, and painted
   behind all content (z-index:-1, above the <html> background). Only rendered
   on the public dark layout (components/_bg.html); harmless no-op elsewhere. */
.kw-bg {
  position: fixed;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: -1;
}
.kw-bg__ring {
  position: absolute;
  border-radius: 50%;
  border: 1px dashed rgba(77, 96, 251, 0.30);
}
.kw-bg__glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(120px);
  opacity: 0.5;
}
.kw-bg__comet { position: absolute; opacity: 0.7; }
/* Lifts content into its own stacking context above a z-index:0 backdrop —
   kept for parity with the mockups (our backdrop sits at z-index:-1, so this
   is belt-and-suspenders). */
.above { position: relative; z-index: 1; }

/* Honour reduced-motion / print: the backdrop is purely decorative. */
@media print { .kw-bg { display: none; } }

/* App-wide brand scrollbars — ONE source of truth for every scroll container
   (page canvas, catalog filter rail, table wraps, dialog bodies, horizontal
   tab strips…). Theme-aware via the two --kw-scrollbar-* tokens (tokens.css):
   translucent brand blue on light, soft white on the dark navy canvas. A
   component that intentionally differs overrides the TOKENS locally (see
   lang_picker.css / .kw-adminnav) — never re-write the ::-webkit block.
   Firefox first (standard properties), then WebKit/Chromium. Modern Chromium
   honours scrollbar-width/color and ignores the ::-webkit-* rules; older
   Chromium/Safari fall through to them — same inset rounded look either way.
   Track stays transparent so the bar reads quiet on glass surfaces. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--kw-scrollbar-thumb) transparent;
}
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--kw-scrollbar-thumb);
  border-radius: 8px;
  border: 2px solid transparent;   /* inset the thumb */
  background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover { background: var(--kw-scrollbar-thumb-hover); }
*::-webkit-scrollbar-corner { background: transparent; }

/* Brand fonts (Host Grotesk, Geist Mono, Fragment Mono) + Material Symbols are
   loaded via <link> in base.html — see comments there. We don't @import from
   CSS to keep render-blocking minimal. */

/* Global focus ring (a11y) */
:focus-visible {
  outline: 2px solid var(--kw-focus-ring);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Hide raw <details> markers — components style their own */
details > summary { list-style: none; }
details > summary::-webkit-details-marker { display: none; }

/* HTMX loading indicator (existing) */
.htmx-indicator { opacity: 0; transition: opacity 200ms; }
.htmx-request .htmx-indicator { opacity: 1; }
.htmx-request.htmx-indicator { opacity: 1; }

/* Inline spinner inside buttons during async work */
.spinner {
  width: 1em; height: 1em;
  border: 2px solid currentColor;
  border-inline-end-color: transparent;
  border-radius: 50%;
  display: inline-block;
  animation: kw-spin 0.6s linear infinite;
}
@keyframes kw-spin { to { transform: rotate(360deg); } }

/* Lucide icons (Material Symbols replacement). The icon macro emits an
   <i data-lucide> placeholder that lucide.createIcons() turns into an inline
   <svg class="kw-ico …">, transferring the size + classes onto the SVG.
   Brand rule: icons are WHITE or SIGNAL GOLD only — they inherit currentColor
   (white on the dark public theme, navy on light admin); add .kw-ico--gold for
   the gold variant, or drop the icon inside an .icon-orb (forces white/gold). */
.kw-ico {
  color: currentColor;
  stroke-width: 1.75;
  vertical-align: middle;
  flex-shrink: 0;
}
.kw-ico--gold { color: var(--kw-signal-gold); }
/* Size the placeholder before JS runs so layout doesn't jump on init. */
[data-lucide] { display: inline-block; vertical-align: middle; }
svg.lucide { stroke-width: 1.75; }

/* RTL: directional nav icons (arrow-left/right, chevron-left/right) must point
   the other way. The icon() macro auto-adds .kw-ico--flip to those names, and
   lucide.createIcons() copies the class onto the rendered <svg>, so this one
   rule mirrors them. Non-directional icons are unaffected.
   NOTE on transform precedence: a component that ALSO sets `transform` on a
   flipped icon (the only case today is the audit disclosure chevron, which
   rotates 90° when open — audit_run.css) overrides this scaleX. That is fine:
   the open state is a DOWN chevron, which is symmetric under a horizontal flip,
   so the rendered glyph is identical whether scaleX survives or not. The
   collapsed state (where the mirror matters) has no rotate and flips here. */
[dir="rtl"] .kw-ico--flip { transform: scaleX(-1); }

/* RTL: literal arrow glyphs (→) used as "more/forward" affordances in links and
   pills. The Unicode bidi algorithm treats arrows as neutral and does NOT flip
   them, so wrap them in <span class="kw-arr"> and mirror here. */
.kw-arr { display: inline-block; }
[dir="rtl"] .kw-arr { transform: scaleX(-1); }

/* RTL: the Tailwind forms plugin (tailwind.css, loaded globally before this
   file) styles every <select> with a right-pinned dropdown chevron
   (background-position: right .5rem center) and right padding (padding-right:
   2.5rem). The chevron belongs on the inline-END (trailing) edge in both
   directions — right in LTR, left in RTL — so move it to the left here. There
   is no logical `background-position`, so this is done explicitly. Scoped to
   [dir="rtl"] so LTR keeps Tailwind's output untouched; the physical paddings
   below are used (rather than `padding-inline-end`) precisely because Tailwind's
   physical `padding-right` would otherwise survive on the wrong side and
   double-pad. tailwind.css is a generated artifact excluded from the CSS lint,
   so this override is asserted directly by tests/test_rtl_layout.py. */
[dir="rtl"] select { background-position: left 0.5rem center; padding-right: 0.75rem; padding-left: 2.5rem; }
/* No chevron on multi/size selects → symmetric padding. */
[dir="rtl"] select:where([multiple]), [dir="rtl"] select:where([size]:not([size="1"])) { padding-left: 0.75rem; }

/* Container helper */
.kw-container {
  max-width: var(--kw-width-content);
  margin-inline: auto;
  padding-inline: var(--kw-space-8);
  width: 100%;
}

/* Toast notifications now live in components/states.css (.toast / .toast-region),
   rendered into #toast-region from the `flash` query param + window.kwToast(). */
