/*
 * theme.css — design tokens.
 *
 * Source of truth: specs/DESIGN_SYSTEM.md §5–7.
 * Every color, spacing value, radius, shadow, and font stack used in the
 * product comes from this file. Components reference tokens via
 * ``var(--token-name)`` and never use hardcoded values.
 *
 * Layout uses CSS logical properties exclusively so LTR/RTL flips
 * automatically via ``<html dir="rtl">``.
 */

:root {
  /* ─── Colors — primary palette (Soolo purple) ─────────────────────── */
  --color-primary-900: #1d0033;  /* darkest — header, table header bg */
  --color-primary-700: #2c0052;  /* primary button bg */
  --color-primary-500: #5a2d82;  /* brand, links, accents */
  --color-primary-300: #b89ad4;  /* secondary hover tint, toggles */

  /* ─── Colors — surfaces ───────────────────────────────────────────── */
  --color-body-bg:          #e3ddea;
  --color-bg:               #ffffff;
  --color-bg-soft:          #f7f5fa;
  --color-surface:          #ffffff;
  --color-surface-alt:      #f2eef7;
  --color-surface-alt-gray: #d6d0dc;

  /* ─── Colors — structure ──────────────────────────────────────────── */
  --color-border:      #e3ddea;
  --color-text:        #1a1a1a;
  --color-text-muted:  #6b6472;
  --color-text-on-primary: #ffffff;

  /* ─── Colors — status ─────────────────────────────────────────────── */
  --color-success:     #2e9b4f;
  --color-warning:     #e6a700;
  --color-error:       #d92d20;
  --color-info:        #2f80ed;

  /* ─── Colors — interaction ────────────────────────────────────────── */
  --color-focus:       #7c3aed;
  --color-destructive: var(--color-error);

  /* State tokens derived from the palette. */
  --color-primary-hover:    #3a1666;
  --color-primary-active:   #220044;
  --color-primary-disabled: var(--color-primary-300);

  --color-border-default: var(--color-border);
  --color-border-hover:   #c9bed6;
  --color-border-focus:   var(--color-focus);
  --color-border-error:   var(--color-error);

  --color-focus-background: rgba(255,255,255,0.25);
  --color-focus-ring:     rgba(124, 58, 237, 0.28);
  --color-disabled-bg:    #f0edf5;
  --color-disabled-text:  #a49daf;

  --color-error-bg:       #fdecea;
  --color-error-text:     #811f16;
  --color-error-hover:    #B71C1C;

  --color-success-bg:     #dcfce7;
  --color-success-text:   #15803d;
  --color-success-border: #86efac;

  --color-info-bg:        #dbeafe;
  --color-info-text:      #1d4ed8;
  --color-info-border:    #93c5fd;

  --color-warning-bg:     #fef3c7;
  --color-warning-text:   #92400e;

  --color-primary-50:     #f5f3ff;

  /* ─── Table tokens ────────────────────────────────────────────────── */
  --color-table-bg:           var(--color-surface);
  --color-table-row-alt:      var(--color-surface-alt);
  --color-table-row-hover:    #eee7f6;
  --color-table-header-bg:    var(--color-primary-900);
  --color-table-header-text:  #ffffff;

  /* ─── Chart palette ───────────────────────────────────────────────── */
  --color-chart-1: #4dc9f6;
  --color-chart-2: #f67019;
  --color-chart-3: #f53794;
  --color-chart-4: #acc236;
  --color-chart-5: #166a8f;
  --color-chart-6: #00a950;

  /* ─── Spacing scale (8 px base with a few half-steps) ─────────────── */
  --space-0: 0;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 18px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;

  /* ─── Typography ──────────────────────────────────────────────────── */
  --font-ui:      "Inter", "Noto Sans Arabic", system-ui, -apple-system,
                  "Segoe UI", Roboto, sans-serif;
  --font-display: "Montserrat", "Noto Sans Arabic", system-ui, -apple-system,
                  "Segoe UI", Roboto, sans-serif;
  --font-mono:    ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --font-size-body:    16px;
  --font-size-small:   14px;
  --font-size-caption: 12px;
  --line-height-body:  1.6;
  --line-height-heading: 1.25;
  --letter-spacing-ui: 0.03em;

  /* ─── Radius tokens ───────────────────────────────────────────────── */
  --radius-sm:    4px;
  --radius-md:    8px;
  --radius-input: 12px;
  --radius-panel: 12px;
  --radius-card:  16px;
  --radius-full:  999px;

  /* ─── Shadows ─────────────────────────────────────────────────────── */
  --shadow-card:  0 2px 8px rgba(26, 0, 51, 0.06),
                  0 1px 2px rgba(26, 0, 51, 0.04);
  --shadow-modal: 0 12px 40px rgba(26, 0, 51, 0.18),
                  0 4px 12px rgba(26, 0, 51, 0.08);
  --shadow-focus: 0 0 0 4px var(--color-focus-ring);

  /* ─── Z-index scale ───────────────────────────────────────────────── */
  --z-sticky: 900;
  --z-dropdown: 1000;
  --z-header: 1100;
  --z-modal-backdrop: 10000;
  --z-modal: 10010;
  --z-toast: 10100;

  /* ─── Named breakpoints (also referenced from JS) ─────────────────── */
  --bp-sm: 600px;
  --bp-md: 720px;
  --bp-lg: 860px;

  /* ─── Layout constants ────────────────────────────────────────────── */
  --header-height: 56px;
  --header-height-large: 72px;
  --card-max-width: 1200px;
  /* Standard width for single-column form/report cards (device settings,
     user create/edit, profile, reports). Opt in via <app-card width="form">
     or by setting this on a shell wrapper. Shrinks to fit on narrow screens. */
  --form-card-width: 800px;

  /* ─── Search field sizing (spec §13.1.1) ─────────────────────────── */
  --search-min-width: 200px;
  --search-max-width: 360px;          /* default / main search */
  --search-max-width-compact: 320px;  /* toolbars, cards, narrow areas */
  --search-max-width-xcompact: 300px; /* very narrow panels/sidebars */

  /* ─── Touch targets (spec MOBILE_RESPONSIVE.md §3) ────────────────── */
  --touch-min: 44px;
  --touch-gap: 8px;

  /* ─── Safe-area insets (spec MOBILE_RESPONSIVE.md §15) ────────────── */
  --safe-top:    env(safe-area-inset-top, 0px);
  --safe-right:  env(safe-area-inset-right, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left:   env(safe-area-inset-left, 0px);

  /* Keyboard-controller exposes the keyboard offset on <html> when an
     on-screen keyboard is shown; defaults to 0 when no keyboard. */
  --keyboard-offset: 0px;

  /* ─── Transitions ─────────────────────────────────────────────────── */
  --transition-hover: 150ms ease-in-out;
  --transition-active: 100ms ease-in-out;
  --transition-toggle: 200ms ease-in-out;
  --transition-modal: 250ms ease-in-out;
}

/* ─── Reset + base ──────────────────────────────────────────────────── */

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

html {
  -webkit-text-size-adjust: 100%;
}

html,
body {
  margin: 0;
  padding: 0;
  background: var(--color-bg-soft);
  color: var(--color-text);
  font-family: var(--font-ui);
  font-size: var(--font-size-body);
  line-height: var(--line-height-body);
  letter-spacing: var(--letter-spacing-ui);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  overscroll-behavior-y: contain;
}

@media (max-width: 720px) {
  html,
  body {
    font-size: 14px;
  }
}

/* FOUC guard for inline icons.
   Many components load their stylesheet asynchronously (injectStyles
   appends a <link> at runtime). Inline <svg> icons rendered before that
   stylesheet arrives would otherwise fall back to the SVG default size
   of 300x150 and flash huge for a frame. Constrain any unsized SVG to
   1em as a fallback; component CSS overrides this once it loads. */
svg:not([width]):not([height]) {
  inline-size: 1em;
  block-size: 1em;
}

/* The boot-time visibility/animation guards live inline in index.html
   so they're applied before any other stylesheet loads. See the
   .is-preload rules there. */

/* ─── Sticky action bar (spec §6.5) ────────────────────────────────────
   Utility class for forms/views that need a sticky save/cancel bar at
   the bottom of the viewport on mobile. Pin to the bottom of the
   nearest scroll container; padding accounts for safe-area-inset.
*/
.app-sticky-action-bar {
  position: sticky;
  inset-block-end: 0;
  inset-inline: 0;
  display: flex;
  gap: var(--space-3);
  align-items: center;
  justify-content: flex-end;
  padding: var(--space-3) var(--space-4);
  padding-block-end: calc(var(--space-3) + var(--safe-bottom));
  background: var(--color-surface);
  border-block-start: 1px solid var(--color-border);
  box-shadow: 0 -2px 8px rgba(26, 0, 51, 0.06);
  z-index: var(--z-sticky);
}

@media (min-width: 721px) {
  .app-sticky-action-bar {
    /* On desktop, the bar stays visible but does not need the elevated
       sticky treatment — render inline at the bottom of the form. */
    position: static;
    box-shadow: none;
    background: transparent;
    border-block-start: none;
    padding-block-end: var(--space-3);
  }
}

/* ─── Horizontal-scroll utility (spec §5.4) ────────────────────────────
   For overflowing toolbars and tab bars on mobile. Snap-scrolls one
   item at a time; overscroll contained so it does not bounce the
   parent scroller.
*/
.h-scroll {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--space-2);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.h-scroll::-webkit-scrollbar { display: none; }
.h-scroll > * {
  scroll-snap-align: start;
  flex: 0 0 auto;
}

iot-app {
  display: block;
  min-block-size: 100dvh;
}

button {
  font: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}

button:focus-visible,
a:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
  box-shadow: var(--shadow-focus);
}

a {
  color: var(--color-primary-500);
  text-decoration: none;
}
a:hover {
  text-decoration: underline;
}

/* SPA-link wrapper: a real <a href> wrapping a styled child (e.g. an
   <app-button>) so middle-click / Ctrl+click / right-click "Open in new
   tab" all work natively. The anchor itself contributes no box, so the
   inner element's own styling/sizing is preserved. See
   core/static/lib/spa-link.js and CLAUDE.md "Navigation and link
   openability". */
.app-link-wrap,
.app-link-wrap:hover {
  display: contents;
  color: inherit;
  text-decoration: none;
}

/* Direction-aware icons mirror under RTL. */
html[dir="rtl"] .icon--directional {
  transform: scaleX(-1);
}

