/* Copyright 2026 Adibyte Ltd. SPDX-License-Identifier: Apache-2.0 */
/**
 * Adibyte Design System — token layer
 * -----------------------------------
 * Extracted from src/theme.ts and src/app.css. This file is the single
 * CSS-side source of truth for colors, type, spacing, radius, elevation,
 * motion, and z-index. Import it once, before app.css.
 *
 *   import "./design-tokens.css";
 *   import "./app.css";
 *
 * Naming: --ab-<group>-<token>. Semantic aliases live at the bottom so
 * component code reads intent (--ab-surface-card) rather than raw hue.
 * Contains no rules — only custom properties.
 */

:root {
  /* ---------- Color: neutrals (canvas + surfaces) ---------- */
  --ab-canvas: #030305;
  --ab-canvas-elevated: #06060c;
  --ab-surface: #0a0a0f;
  --ab-surface-glass: #0b0b12;
  --ab-surface-drawer: rgba(10, 10, 15, 0.95);

  /* ---------- Color: brand accent (indigo) ---------- */
  --ab-accent: #4f46e5;
  --ab-accent-light: #818cf8;
  --ab-accent-dark: #3730a3;
  --ab-accent-deep: #4338ca;

  /* ---------- Color: brand secondary (cyan) ---------- */
  --ab-secondary: #06b6d4;
  --ab-secondary-light: #22d3ee;
  --ab-secondary-dark: #0891b2;

  /* ---------- Color: text ---------- */
  --ab-text: #f8fafc;
  --ab-text-muted: #94a3b8;
  --ab-text-subtle: #7c8798;
  --ab-on-accent: #ffffff;

  /* ---------- Color: opaque borders ---------- */
  --ab-border: #16161f;
  --ab-border-strong: #26262f;

  /* ---------- Color: translucent glass borders / overlays ---------- */
  --ab-glass-fill: rgba(255, 255, 255, 0.02);
  --ab-glass-fill-hover: rgba(255, 255, 255, 0.04);
  --ab-border-hairline: rgba(255, 255, 255, 0.04);
  --ab-border-glass: rgba(255, 255, 255, 0.05);
  --ab-border-control: rgba(255, 255, 255, 0.1);
  --ab-border-outlined: rgba(255, 255, 255, 0.15);
  --ab-border-accent: rgba(79, 70, 229, 0.25);
  --ab-border-accent-strong: rgba(79, 70, 229, 0.4);

  /* ---------- Color: semantic status ---------- */
  --ab-success: #34d399;
  --ab-success-border: rgba(52, 211, 153, 0.25);
  --ab-success-fill: rgba(52, 211, 153, 0.06);
  --ab-warning: #fbbf24;
  --ab-danger: #f87171;
  --ab-danger-border: rgba(248, 113, 113, 0.25);
  --ab-danger-fill: rgba(248, 113, 113, 0.06);

  /* ---------- Backdrop ----------
   * The aurora behind every page and the film-grain strength over it. Themes
   * override these; app.css and any consuming page read them, never literals. */
  --ab-backdrop-aurora:
    radial-gradient(
      ellipse 60% 45% at 15% 40%,
      rgba(79, 70, 229, 0.14) 0%,
      transparent 60%
    ),
    radial-gradient(
      ellipse 50% 40% at 85% 15%,
      rgba(6, 182, 212, 0.1) 0%,
      transparent 60%
    ),
    radial-gradient(
      ellipse 55% 45% at 70% 85%,
      rgba(129, 140, 248, 0.09) 0%,
      transparent 60%
    ),
    radial-gradient(
      ellipse 40% 35% at 35% 90%,
      rgba(34, 211, 238, 0.06) 0%,
      transparent 60%
    );
  --ab-grain-opacity: 0.035;

  /* ---------- Gradients ---------- */
  --ab-gradient-brand: linear-gradient(135deg, #4f46e5 0%, #06b6d4 100%);
  --ab-gradient-brand-hover: linear-gradient(135deg, #4338ca 0%, #0891b2 100%);
  --ab-gradient-text: linear-gradient(135deg, #818cf8 0%, #22d3ee 100%);
  --ab-gradient-ring: linear-gradient(
    135deg,
    rgba(79, 70, 229, 0.5),
    rgba(6, 182, 212, 0.5)
  );

  /* ---------- Typography: families ---------- */
  --ab-font-display: "Outfit", "Segoe UI", sans-serif;
  --ab-font-body: "Inter", "Segoe UI", sans-serif;
  --ab-font-mono: "JetBrains Mono", "SFMono-Regular", Consolas, monospace;

  /* ---------- Typography: display scale ---------- */
  --ab-text-display-xl: 4rem; /* 64 */
  --ab-text-display-lg: 3.2rem; /* 51 */
  --ab-text-display-md: 2.4rem; /* 38 */
  --ab-text-heading: 1.5rem; /* 24 */
  --ab-text-title: 1.25rem; /* 20 */
  --ab-text-subtitle: 1rem; /* 16 */

  /* ---------- Typography: working scale ---------- */
  --ab-text-body: 1.05rem; /* 17 */
  --ab-text-body-sm: 0.875rem; /* 14 */
  --ab-text-eyebrow: 0.8rem; /* 13 */
  --ab-text-button: 0.95rem; /* 15 */
  --ab-text-stat: 3.4rem; /* 54 */

  /* ---------- Typography: weights ---------- */
  --ab-weight-regular: 400;
  --ab-weight-medium: 500;
  --ab-weight-semibold: 600;
  --ab-weight-bold: 700;

  /* ---------- Typography: line heights ---------- */
  --ab-leading-tight: 1.1;
  --ab-leading-display: 1.15;
  --ab-leading-snug: 1.3;
  --ab-leading-body: 1.6;
  --ab-leading-prose: 1.7;

  /* ---------- Typography: tracking ---------- */
  --ab-tracking-display-xl: -0.04em;
  --ab-tracking-display-lg: -0.03em;
  --ab-tracking-display-md: -0.02em;
  --ab-tracking-heading: -0.01em;
  --ab-tracking-button: 0.02em;
  --ab-tracking-eyebrow: 0.2em;

  /* ---------- Spacing (8px base unit) ---------- */
  --ab-space-xs: 4px;
  --ab-space-sm: 8px;
  --ab-space-md: 16px;
  --ab-space-lg: 24px;
  --ab-space-xl: 32px;
  --ab-space-2xl: 48px;
  --ab-space-3xl: 64px;
  --ab-space-4xl: 96px;

  /* ---------- Radius ---------- */
  --ab-radius-sm: 8px;
  --ab-radius-md: 10px;
  --ab-radius-lg: 12px;
  --ab-radius-xl: 16px;
  --ab-radius-glass: 22px;
  --ab-radius-pill: 999px;

  /* ---------- Elevation & depth ---------- */
  --ab-blur-glass: blur(24px);
  --ab-blur-header: blur(24px);
  --ab-blur-footer: blur(10px);
  --ab-shadow-glass: 0 8px 32px rgba(0, 0, 0, 0.2);
  --ab-shadow-card-hover: 0 20px 40px rgba(0, 0, 0, 0.4);
  --ab-shadow-accent: none;
  --ab-shadow-accent-hover: none;
  --ab-shadow-header: 0 8px 32px rgba(0, 0, 0, 0.4);
  --ab-shadow-heading: 0 4px 30px rgba(0, 0, 0, 0.9);
  --ab-glow-dot: 0 0 8px rgba(34, 211, 238, 0.6);
  --ab-glow-text: 0 0 24px rgba(34, 211, 238, 0.5);

  /* ---------- Materials: liquid glass ----------
   * Reference direction: dark tinted optical glass with a clear body,
   * chromatic edge refraction and a restrained specular highlight. The
   * material must stay smooth: procedural frost/noise is an optional texture,
   * never the default glass surface.
   *
   * Five cues work together: transparent tinted body, backdrop refraction,
   * chromatic rim, internal specular highlight and grounded contact shadow.
   * Blur alone is not glass and an opaque fill becomes a coloured panel.
   */
  --ab-glass-fill-thin: rgba(14, 20, 54, 0.22);
  --ab-glass-fill-default: rgba(17, 24, 66, 0.32);
  --ab-glass-fill-thick: rgba(20, 27, 76, 0.42);
  --ab-glass-fill-dense: rgba(24, 31, 88, 0.5);

  /* Optical colour inside the pane. These use the existing indigo/cyan
   * palette rather than introducing a separate neon-magenta accent. */
  --ab-glass-optic:
    radial-gradient(
      90% 120% at 4% -12%,
      rgba(255, 255, 255, 0.2) 0%,
      rgba(129, 140, 248, 0.12) 24%,
      transparent 52%
    ),
    radial-gradient(
      85% 100% at 108% 105%,
      rgba(34, 211, 238, 0.11) 0%,
      rgba(79, 70, 229, 0.08) 34%,
      transparent 68%
    ),
    linear-gradient(
      145deg,
      rgba(129, 140, 248, 0.12) 0%,
      rgba(79, 70, 229, 0.08) 48%,
      rgba(6, 182, 212, 0.055) 100%
    );
  --ab-glass-optic-strong:
    radial-gradient(
      95% 120% at 4% -12%,
      rgba(255, 255, 255, 0.24) 0%,
      rgba(129, 140, 248, 0.16) 25%,
      transparent 54%
    ),
    radial-gradient(
      90% 105% at 108% 105%,
      rgba(34, 211, 238, 0.14) 0%,
      rgba(79, 70, 229, 0.11) 38%,
      transparent 70%
    ),
    linear-gradient(
      145deg,
      rgba(129, 140, 248, 0.16) 0%,
      rgba(79, 70, 229, 0.11) 48%,
      rgba(6, 182, 212, 0.075) 100%
    );

  /* Refraction stays crisp enough to read as a pane rather than a fogged
   * panel. Saturation restores the colour that backdrop blur otherwise loses. */
  --ab-glass-filter-raised: blur(18px) saturate(175%) brightness(108%);
  --ab-glass-filter-header: blur(22px) saturate(180%) brightness(106%);
  --ab-glass-filter-overlay: blur(28px) saturate(190%) brightness(110%);

  /* Gradient rim gives the liquid-glass edge its blue/indigo/cyan refraction.
   * The ordinary rim token remains as a fallback for contexts without masks. */
  --ab-glass-rim: rgba(179, 189, 255, 0.22);
  --ab-glass-rim-strong: rgba(197, 206, 255, 0.32);
  --ab-glass-rim-gradient: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.58) 0%,
    rgba(129, 140, 248, 0.5) 24%,
    rgba(79, 70, 229, 0.24) 51%,
    rgba(34, 211, 238, 0.42) 78%,
    rgba(255, 255, 255, 0.18) 100%
  );
  --ab-glass-rim-gradient-strong: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.7) 0%,
    rgba(129, 140, 248, 0.62) 24%,
    rgba(79, 70, 229, 0.32) 51%,
    rgba(34, 211, 238, 0.5) 78%,
    rgba(255, 255, 255, 0.24) 100%
  );
  --ab-specular-top:
    inset 0 1px 0 rgba(255, 255, 255, 0.22),
    inset 0 -1px 0 rgba(34, 211, 238, 0.08);
  --ab-specular-top-strong:
    inset 0 1px 0 rgba(255, 255, 255, 0.3),
    inset 0 -1px 0 rgba(34, 211, 238, 0.12);

  /* Contact shadows are deliberately dark; the chromatic glow is confined to
   * the optical edge rather than becoming a neon halo around the component. */
  --ab-shadow-glass-raised:
    0 2px 3px rgba(0, 0, 0, 0.5), 0 18px 44px rgba(0, 0, 0, 0.34);
  --ab-shadow-glass-header:
    0 2px 3px rgba(0, 0, 0, 0.5), 0 14px 38px rgba(0, 0, 0, 0.4);
  --ab-shadow-glass-overlay:
    0 3px 5px rgba(0, 0, 0, 0.55), 0 28px 68px rgba(0, 0, 0, 0.5);
  --ab-shadow-glass-hover:
    0 3px 5px rgba(0, 0, 0, 0.5), 0 24px 54px rgba(0, 0, 0, 0.42);

  /* ---------- Materials: metal ----------
   * Metal is opaque, so blur does nothing for it. It reflects rather than
   * refracts, and it needs three things: a directional sheen, a lit edge and
   * a brushed grain. Every sheen in the system shares ONE light angle,
   * 158deg (upper-left), so highlights agree across a page.
   *
   * `--ab-metal-fill` and `--ab-metal-grain` are gradient layers, so they are
   * always composed in front of the substrate:
   *   background: var(--ab-metal-grain), var(--ab-metal-fill), var(--ab-metal-base);
   * Both gradient strings are the materialised dial defaults of
   * `design-system/materials.html` (`metalSheen: 100`, `metalGrain: 100`).
   *
   * Sourcing matters here. Before this group existed, the page's own hover
   * rules composed `var(--ab-metal-fill-hover)`, which was declared nowhere,
   * so the entire `background` declaration was invalid and metal hover was a
   * silent no-op. `--ab-metal-fill-hover` is the same sheen one stop up: the
   * dial at `metalSheen: 150`.
   *
   * Metal is reserved for controls and focal accents. Never lay a whole
   * content section in metal. */
  --ab-metal-base: #12121a;
  --ab-metal-fill: linear-gradient(
    158deg,
    rgba(255, 255, 255, 0.11) 0%,
    rgba(255, 255, 255, 0.025) 38%,
    rgba(129, 140, 248, 0.07) 66%,
    rgba(6, 182, 212, 0.06) 100%
  );
  --ab-metal-fill-hover: linear-gradient(
    158deg,
    rgba(255, 255, 255, 0.165) 0%,
    rgba(255, 255, 255, 0.038) 38%,
    rgba(129, 140, 248, 0.105) 66%,
    rgba(6, 182, 212, 0.09) 100%
  );
  /* Brushed finish: 1px lines on a 3px pitch. The grain runs at 90deg — the
   * 158deg angle is the SHEEN angle, and crossed grain reads as fabric rather
   * than metal. */
  --ab-metal-grain: repeating-linear-gradient(
    90deg,
    rgba(255, 255, 255, 0.022) 0px,
    rgba(255, 255, 255, 0.022) 1px,
    transparent 1px,
    transparent 3px
  );
  --ab-metal-edge-light: rgba(255, 255, 255, 0.16);
  --ab-metal-edge-dark: rgba(0, 0, 0, 0.55);

  /* ---------- Materials: chrome ----------
   * Chrome is the two fused: a metallic rim lit by the brand gradient around
   * a glass interior. It is reserved for controls that should feel machined.
   * The rim is a gradient BORDER, so it is drawn by a `::before` plate inset
   * by -1px behind a `background-clip: padding-box` element. */
  --ab-chrome-fill: rgba(11, 11, 18, 0.62);
  --ab-chrome-rim: linear-gradient(
    135deg,
    rgba(129, 140, 248, 0.55) 0%,
    rgba(255, 255, 255, 0.14) 45%,
    rgba(6, 182, 212, 0.45) 100%
  );
  --ab-chrome-specular: inset 0 1px 0 rgba(255, 255, 255, 0.18);

  /* ---------- Materials: textures ----------
   * Procedural, resolution-independent surface textures. Each is an SVG
   * feTurbulence tile inlined as a data URI, so there is no image asset to
   * ship, nothing to fetch and nothing that blurs on a high-DPI display.
   *
   * Textures are LAYERS, never fills. Compose them above a base colour and
   * blend them in, or they flatten the surface to grey:
   *   background: var(--ab-alu-anisotropy), var(--ab-texture-brushed),
   *               var(--ab-alu-fill-anodised);
   *   background-blend-mode: soft-light, overlay, normal;
   *
   * `brushed` is anisotropic noise: a very low x-frequency against a high
   * y-frequency stretches the grain into long horizontal filaments, which is
   * what a linished (brushed) metal surface looks like at normal viewing
   * distance. It is mid-grey, so `overlay` darkens and lightens in equal
   * measure. `brushed-fine` is the same filament at twice the pitch, for
   * small controls where the coarse grain would read as stripes.
   * `frost` is an OPTIONAL micro-etch texture. It is deliberately much
   * softer than the metal grain and must never be applied to ordinary liquid
   * glass. Use it only when an explicitly frosted/etched surface is required. */
  --ab-texture-brushed: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='512' height='512'%3E%3Cfilter id='b' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.004 0.9' numOctaves='3' seed='11' stitchTiles='stitch'/%3E%3CfeColorMatrix values='1.5 0 0 0 -0.25 1.5 0 0 0 -0.25 1.5 0 0 0 -0.25 0 0 0 0 1'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23b)'/%3E%3C/svg%3E");
  --ab-texture-brushed-fine: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='256' height='256'%3E%3Cfilter id='b' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.006 1.8' numOctaves='2' seed='4' stitchTiles='stitch'/%3E%3CfeColorMatrix values='1.4 0 0 0 -0.2 1.4 0 0 0 -0.2 1.4 0 0 0 -0.2 0 0 0 0 1'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23b)'/%3E%3C/svg%3E");
  --ab-texture-frost: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='320' height='320'%3E%3Cfilter id='f' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.18' numOctaves='1' seed='17' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0.025 0.025 0.025 0 0.004'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23f)'/%3E%3C/svg%3E");
  --ab-texture-brushed-size: 512px 512px;
  --ab-texture-brushed-fine-size: 256px 256px;
  --ab-texture-frost-size: 320px 320px;

  /* ---------- Materials: aluminium ----------
   * Two finishes of the same metal. Natural is bare brushed aluminium: light,
   * cool, and carries DARK text. Anodised is the same metal dyed graphite: it
   * sits on the dark canvas without glaring and carries LIGHT text. Pair the
   * finish with its `--ab-on-alu-*` ink; never put light text on natural.
   *
   * Real brushed metal has an anisotropic highlight: the filaments stretch a
   * point reflection into a band perpendicular to the brushing, so the
   * sheen is a conic fan rather than a linear gradient. `--ab-alu-anisotropy`
   * is that fan. It is the part of the finish that makes the texture read as
   * metal rather than as noise. */
  --ab-alu-natural-hi: #dde1e8;
  --ab-alu-natural-mid: #a9afba;
  --ab-alu-natural-lo: #717884;
  --ab-alu-anodised-hi: #4d525e;
  --ab-alu-anodised-mid: #2f333d;
  --ab-alu-anodised-lo: #1a1c23;
  --ab-alu-fill-natural: linear-gradient(
    158deg,
    var(--ab-alu-natural-hi) 0%,
    var(--ab-alu-natural-mid) 48%,
    var(--ab-alu-natural-lo) 100%
  );
  --ab-alu-fill-anodised: linear-gradient(
    158deg,
    var(--ab-alu-anodised-hi) 0%,
    var(--ab-alu-anodised-mid) 48%,
    var(--ab-alu-anodised-lo) 100%
  );
  --ab-alu-anisotropy: conic-gradient(
    from 160deg at 50% 50%,
    rgba(255, 255, 255, 0) 0deg,
    rgba(255, 255, 255, 0.34) 38deg,
    rgba(255, 255, 255, 0) 84deg,
    rgba(255, 255, 255, 0) 180deg,
    rgba(255, 255, 255, 0.26) 218deg,
    rgba(255, 255, 255, 0) 264deg,
    rgba(255, 255, 255, 0) 360deg
  );
  --ab-alu-edge-light: rgba(255, 255, 255, 0.55);
  --ab-alu-edge-dark: rgba(0, 0, 0, 0.5);
  --ab-on-alu-natural: #0b0b12;
  --ab-on-alu-anodised: #f8fafc;
  --ab-shadow-alu-raised:
    inset 0 1px 0 var(--ab-alu-edge-light),
    inset 0 -1px 0 var(--ab-alu-edge-dark), 0 1px 2px rgba(0, 0, 0, 0.5),
    0 10px 24px rgba(0, 0, 0, 0.38);

  /* ---------- Components: form fields ----------
   * A field is a recessed well, so it is lit from the opposite side to a
   * raised surface: the inset shadow darkens the TOP edge. */
  --ab-field-height: 48px;
  --ab-field-fill: var(--ab-glass-fill-default);
  --ab-field-fill-hover: var(--ab-glass-fill-thick);
  --ab-field-fill-disabled: var(--ab-glass-fill-thin);
  --ab-field-border: var(--ab-border-control);
  --ab-field-border-hover: rgba(79, 70, 229, 0.5);
  --ab-field-border-focus: var(--ab-accent);
  --ab-field-border-error: var(--ab-danger);
  --ab-field-well: inset 0 2px 4px rgba(0, 0, 0, 0.35);
  --ab-text-placeholder: var(--ab-text-subtle);
  --ab-text-disabled: rgba(148, 163, 184, 0.45);

  /* ---------- Components: selection + status fills ---------- */
  --ab-accent-fill: rgba(79, 70, 229, 0.14);
  --ab-accent-fill-strong: rgba(79, 70, 229, 0.24);
  --ab-warning-border: rgba(251, 191, 36, 0.25);
  --ab-warning-fill: rgba(251, 191, 36, 0.06);
  --ab-info: var(--ab-secondary-light);
  --ab-info-border: rgba(34, 211, 238, 0.25);
  --ab-info-fill: rgba(34, 211, 238, 0.06);
  --ab-focus-ring-danger: 0 0 0 4px rgba(248, 113, 113, 0.2);
  --ab-focus-outline: 2px solid var(--ab-accent-light);
  --ab-scrim: rgba(3, 3, 5, 0.6);

  /* ---------- Components: tables ---------- */
  --ab-table-row-height: 52px;
  --ab-table-cell-x: 16px;
  --ab-table-header-fill: rgba(255, 255, 255, 0.03);
  --ab-table-row-hover: rgba(255, 255, 255, 0.035);
  --ab-table-row-selected: var(--ab-accent-fill);
  --ab-table-divider: rgba(255, 255, 255, 0.06);

  /* ---------- Components: menus, dropdowns, popovers ---------- */
  --ab-menu-min-width: 200px;
  --ab-menu-item-height: 40px;
  --ab-menu-item-hover: rgba(255, 255, 255, 0.06);
  --ab-menu-item-selected: var(--ab-accent-fill);
  --ab-menu-divider: rgba(255, 255, 255, 0.08);

  /* ---------- Motion ---------- */
  --ab-ease-entrance: cubic-bezier(0.16, 1, 0.3, 1);
  --ab-ease-state: cubic-bezier(0.4, 0, 0.2, 1);
  --ab-ease-tilt: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ab-duration-fast: 0.25s;
  --ab-duration-base: 0.3s;
  --ab-duration-slow: 0.4s;
  --ab-duration-enter: 0.8s;
  --ab-duration-shimmer: 5s;
  --ab-duration-marquee: 32s;
  --ab-duration-aurora: 24s;

  /* ---------- Layout ---------- */
  --ab-container-md: 900px;
  --ab-container-lg: 1200px;
  --ab-appbar-height: 84px;
  --ab-page-offset: 80px;
  --ab-drawer-width: 250px;
  --ab-measure-prose: 540px;

  /* ---------- Z-index ladder ---------- */
  --ab-z-backdrop: -2;
  --ab-z-base: 1;
  --ab-z-content: 2;
  --ab-z-header: 1000;
  --ab-z-header-dim: 1010;
  --ab-z-drawer: 1200;
  --ab-z-grain: 100;
  --ab-z-overlay: 1300; /* menus, popovers, modals (MUI default) */
  --ab-z-toast: 1400;
  --ab-z-tooltip: 1500;
}

/* ------------------------------------------------------------------
 * WebGL / react-three-fiber scene layer
 * Harvested from src/components/*-background-3d.tsx. Every scene reads
 * these instead of literal hexes, so the 3D layer stays inside the
 * indigo→cyan system rather than drifting into new hues.
 * ------------------------------------------------------------------ */
:root {
  /* Camera framing — two shared rigs: [0,0,8] fov 45 and [0,0,10] fov 45 */
  --ab-scene-camera-near: 8;
  --ab-scene-camera-far: 10;
  --ab-scene-fov: 45;

  /* Scene opacity budget. Full-bleed scenes never exceed 0.85 so text
     contrast on the hero heading is preserved. */
  --ab-scene-opacity-hero: 0.85;
  --ab-scene-opacity-default: 0.6;
  --ab-scene-opacity-density: 0.55;
  --ab-scene-opacity-quiet: 0.5;

  /* Lighting — ambient floor plus one key and one counter point light */
  --ab-scene-ambient: 0.4;
  --ab-scene-ambient-lifted: 0.5;
  --ab-scene-light-key: 3;
  --ab-scene-light-fill: 2;
  --ab-scene-light-ring: 1;
  --ab-scene-light-counter: 0.8;

  /* Material vocabulary — physical, glassy, low-roughness */
  --ab-material-emissive: 0.4;
  --ab-material-emissive-soft: 0.2;
  --ab-material-emissive-faint: 0.1;
  --ab-material-metal: 0.6;
  --ab-material-metal-high: 0.7;
  --ab-material-rough: 0.3;
  --ab-material-rough-smooth: 0.2;
  --ab-material-glass-opacity: 0.3;
  --ab-material-ior: 1.2;
  --ab-material-thickness: 2;
  --ab-material-transmission: 0.9;
  --ab-material-clearcoat: 1;

  /* Primitive opacities */
  --ab-primitive-wireframe: 0.5;
  --ab-primitive-ring: 0.35;
  --ab-primitive-solid: 0.7;

  /* Particle density — Stars and Sparkles counts */
  --ab-particles-star-dense: 2000;
  --ab-particles-star: 1500;
  --ab-particles-star-sparse: 1200;
  --ab-particles-sparkle-dense: 100;
  --ab-particles-sparkle: 80;
  --ab-particles-sparkle-sparse: 60;
  --ab-particles-sparkle-faint: 50;

  /* Rotation and drift rates (radians/second multipliers) */
  --ab-scene-spin-slow: 0.1;
  --ab-scene-spin-base: 0.15;
  --ab-scene-spin-fast: 0.25;
  --ab-scene-orbit-slow: 0.12;
  --ab-scene-orbit-base: 0.18;
  --ab-scene-orbit-fast: 0.25;
  --ab-scene-float-soft: 1.5;
  --ab-scene-float-strong: 2;
  --ab-scene-float-intense: 3;
  --ab-scene-drift-speed: 0.4;
  --ab-scene-drift-speed-slow: 0.2;
  --ab-scene-drift-speed-fast: 0.5;

  /* Pointer parallax on the hero rig — lerp factor 0.04 */
  --ab-scene-parallax-lerp: 0.04;
  --ab-scene-parallax-yaw: 0.25;
  --ab-scene-parallax-pitch: 0.15;

  /* Environment */
  --ab-scene-env-preset: city;
  --ab-scene-stars-deep: 50;
  --ab-scene-stars-factor: 4;
}

/* ------------------------------------------------------------------
 * Brand mark — animated logo
 * Harvested from design/brand/animated-logo/README.md and the optical
 * stroke profile. The masters self-calibrate stroke weight against
 * rendered width via ResizeObserver, with a CSS media-query fallback
 * profile for <img> consumption.
 * ------------------------------------------------------------------ */
:root {
  --ab-logo-aspect-ratio: 7500 / 4280;
  --ab-logo-cycle: 4s;
  --ab-logo-min-width: 32px;
  --ab-logo-max-width: 1600px;

  /* Default optical profile, sampled at a 256px rendered width */
  --ab-logo-mark-draw-stroke: 11.0303;
  --ab-logo-word-draw-stroke: 7;
  --ab-logo-word-fill-stroke: 3.2;

  /* Wordmark ink. Dark masters keep the coloured symbol and switch only
     the wordmark, so these are the two sanctioned wordmark values. */
  --ab-logo-wordmark-on-dark: #f8fafc; /* = --ab-text */
  --ab-logo-wordmark-on-light: #000000;

  /* Minimum clear space, expressed as a fraction of mark height */
  --ab-logo-clearspace: 0.25;
}

/* ------------------------------------------------------------------
 * Semantic aliases
 * Read these in components so intent survives a future re-theme.
 * ------------------------------------------------------------------ */
:root {
  --ab-surface-card: var(--ab-surface-glass);
  --ab-surface-page: var(--ab-canvas);
  --ab-text-primary: var(--ab-text);
  --ab-text-help: var(--ab-text-muted);
  --ab-border-card: var(--ab-border-glass);
  --ab-accent-solid: var(--ab-accent);
  --ab-focus-ring: 0 0 0 4px rgba(79, 70, 229, 0.2);
  --ab-text-gradient: var(--ab-gradient-text);
  --ab-scene-ink: var(--ab-secondary);
  --ab-scene-ink-alt: var(--ab-accent);
  --ab-scene-ink-light: var(--ab-accent-light);
  --ab-scene-ink-light-alt: var(--ab-secondary-light);
}

/* ------------------------------------------------------------------
 * Density: the admin console and account pages are work surfaces, so
 * they use compact controls and rows. Sign-in pages keep the defaults.
 * ------------------------------------------------------------------ */
.ab-admin, .ab-account {
  --ab-field-height: 36px;
  --ab-table-row-height: 40px;
  --ab-table-cell-x: 12px;
  --ab-menu-item-height: 32px;
}
