/*
 * Design tokens, reset, base elements and the 19 keyframes used across the
 * theme. Nothing outside this file may hard-code a hex value -- see
 * docs/superpowers/specs/2026-08-15-olt-admin-theme-design.md.
 */

:root {
  /* ---------------------------------------------------------------------
     These are ALIASES, not a second palette.

     The NowaCRM theme (assets/css/nowacrm/base/variables.css) owns every
     shared value in this product. This file used to restate all of them as
     literal hex, which meant two names for one colour and two places to
     change it. Each token below now points at its NowaCRM source, so
     `--ink` and `--text-primary` can never drift apart again.

     A token still carries a literal only where NowaCRM has no equivalent
     for it; those are marked `no NowaCRM equivalent`. Nothing outside this
     file may hard-code a hex value -- see
     docs/superpowers/specs/2026-08-15-olt-admin-theme-design.md.
     --------------------------------------------------------------------- */

  /* accent -- the one interactive hue (NowaCRM indigo) */
  --accent: var(--primary-500);
  --accent-dark: var(--primary-600);
  --accent-deep: var(--primary-700);
  --accent-bright: var(--primary-400);
  --accent-lift: var(--primary-300);
  --accent-grad-a: var(--primary-600);
  --accent-soft: var(--primary-50);
  --accent-tint: #f5f6ff;          /* no NowaCRM equivalent -- between primary-50 and white */
  --accent-wash: #f9faff;          /* no NowaCRM equivalent */
  --accent-hover: #f0f2ff;         /* no NowaCRM equivalent */
  --accent-avatar: var(--primary-100);
  --accent-ink: var(--primary-800);
  --accent-line: var(--primary-200);
  --accent-line-strong: var(--primary-300);
  --accent-line-hover: #c3cbfc;    /* no NowaCRM equivalent */
  --accent-ring: rgba(99, 102, 241, .18);

  /* ink (NowaCRM slate) */
  --ink: var(--text-primary);
  --ink-2: var(--gray-700);
  --ink-3: var(--text-secondary);
  --muted: var(--text-tertiary);
  --muted-2: var(--text-muted);
  --muted-3: var(--gray-300);
  --muted-4: var(--gray-400);

  /* surfaces */
  --canvas: var(--surface-secondary);
  --paper: var(--surface-primary);
  --sunken: var(--surface-secondary);
  --sunken-2: var(--surface-tertiary);
  --line: var(--border-color);
  --line-2: var(--border-light);
  --line-3: var(--border-dark);
  --line-4: var(--gray-50);

  /* state */
  --ok: var(--success-500);
  --ok-dark: var(--success-600);
  --ok-bright: #34d399;            /* no NowaCRM equivalent -- success-400 */
  --ok-soft: var(--success-50);
  --ok-wash: #f0fdf4;              /* no NowaCRM equivalent */
  --ok-line: #a7f3d0;              /* no NowaCRM equivalent -- success-200 */
  --warn: var(--warning-500);
  --warn-bright: #fbbf24;          /* no NowaCRM equivalent -- warning-400 */
  --warn-soft: var(--warning-50);
  --warn-wash: #fefce8;            /* no NowaCRM equivalent */
  --warn-line: #fde68a;            /* no NowaCRM equivalent -- warning-200 */
  --crit: var(--danger-500);
  --crit-dark: var(--danger-600);
  --crit-bright: #f87171;          /* no NowaCRM equivalent -- danger-400 */
  --crit-soft: var(--danger-50);
  --crit-wash: #fff5f5;            /* no NowaCRM equivalent */
  --crit-line: #fecaca;            /* no NowaCRM equivalent -- danger-200 */

  /* info is deliberately NOT NowaCRM's --info-500 (#06b6d4, cyan). This
     product's info tone is sky, and the two read differently against the
     status badges that sit beside it. */
  --info: #0ea5e9;
  --info-dark: #0284c7;
  --info-bright: #38bdf8;
  --info-soft: #f0f9ff;
  --info-wash: #e0f2fe;
  --info-line: #bae6fd;

  --sev-crit: var(--danger-500);
  --sev-warn: var(--warning-500);
  --sev-info: var(--success-500);

  /* radii -- this product's control scale is tighter than NowaCRM's
     4/6/8/12/16 step, so these stay literal rather than snapping geometry
     across every page that already uses them. */
  --r-xs: 5px;
  --r-sm: 7px;
  --r: 9px;
  --r-md: 10px;
  --r-lg: 11px;
  --r-xl: 12px;
  --r-2xl: 14px;
  --r-3xl: 16px;
  --r-pill: var(--radius-full);

  /* elevation */
  --sh-1: var(--shadow-sm);
  --sh-2: var(--shadow);
  --sh-3: 0 10px 15px -3px rgba(99, 102, 241, .15), 0 4px 6px -4px rgba(99, 102, 241, .1);
  --sh-pop: 0 14px 38px rgba(15, 23, 42, .14);
  --sh-modal: 0 26px 60px rgba(15, 23, 42, .24);
  --sh-toast: 0 12px 30px rgba(15, 23, 42, .14);
  --sh-accent: 0 4px 14px rgba(99, 102, 241, .28);
  --sh-accent-lift: 0 8px 20px rgba(99, 102, 241, .36);

  /* chassis -- the 1U faceplate visualiser on the OLT page is deliberately
     dark whatever the page theme, the way real front-panel photography and
     every vendor's own EMS renders it. These are the only shades in the
     product that are NOT drawn from the surface ramp, because a faceplate
     that follows the page background stops reading as hardware. */
  --chassis-face: var(--gray-900);
  --chassis-edge: var(--gray-700);
  --chassis-ink: var(--gray-300);
  --chassis-label: var(--gray-500);
  --chassis-well: #090d16;          /* the recessed port bay, darker than gray-900 */
  --chassis-socket: #182234;        /* an unlit RJ45/SFP cage */
  --chassis-socket-lit: #273549;    /* the same cage on hover */
  --chassis-socket-fault: #23161c;  /* a cage whose port is down -- red-shifted, not red */

  /* type */
  --font: var(--font-sans);
  --mono: 'JetBrains Mono', ui-monospace, monospace;

  /* motion */
  --t-fast: var(--transition-fast);
  --t: var(--transition-base);
  --t-slow: .22s ease;              /* NOT --transition-slow (350ms): 59% slower, visibly draggier */
}

/* ---------------------------------------------------------------------
   The NowaCRM theme (nowacrm/base/reset.css + typography.css) owns the
   global reset and every base element: box-sizing, html/body, headings,
   lists, links and img/svg. This file used to restate all of that, and
   because it loaded FIRST the two fought -- NowaCRM won on body, so the
   app rendered at 14px/400 on --body-bg while this file believed it was
   13px/500 on --canvas.

   NowaCRM loads LAST (see layouts/app.blade.php for why), so it wins every
   selector it defines. Only rules it has no answer for belong below --
   [hidden], ::selection, .sr-only and .skip-link. Its own :focus-visible
   already covers the focus ring.
   --------------------------------------------------------------------- */

/* `hidden` is how every enhanced control here is opened and closed. Any
   component rule that sets `display` silently beats the UA sheet and leaves
   the element on screen -- which is exactly how .modal (display:flex) ended up
   rendering every confirmation dialog open on page load. This is the one place
   !important is the right tool. */
[hidden] {
  display: none !important;
}

::selection {
  background: var(--accent-line);
  color: var(--ink);
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  top: -48px;
  left: 12px;
  z-index: 400;
  background: var(--accent);
  color: #fff;
  padding: 10px 16px;
  border-radius: var(--r-sm);
  font: 700 12px var(--font);
  transition: top var(--t-fast);
}

.skip-link:focus {
  top: 12px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

@keyframes oltPulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
@keyframes oltDrop { from { opacity: 0; transform: translateY(-6px) scale(.985); } to { opacity: 1; transform: none; } }
@keyframes oltBlink { 0%, 100% { opacity: .2; } 50% { opacity: 1; } }
@keyframes oltWave { 0% { transform: scale(.5); opacity: 0; } 30% { opacity: 1; } 100% { transform: scale(1.25); opacity: 0; } }
@keyframes oltSpin { to { transform: rotate(360deg); } }
@keyframes oltBar { 0%, 100% { transform: scaleY(.3); } 50% { transform: scaleY(1); } }
@keyframes oltSwing { 0%, 55%, 100% { transform: rotate(0); } 65% { transform: rotate(12deg); } 75% { transform: rotate(-10deg); } 85% { transform: rotate(6deg); } }
@keyframes oltDraw { from { stroke-dashoffset: 220; } to { stroke-dashoffset: 0; } }
@keyframes oltFlow { from { stroke-dashoffset: 16; } to { stroke-dashoffset: 0; } }
@keyframes oltRise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes oltSpin2 { to { transform: rotate(360deg); } }
@keyframes oltToastIn { from { opacity: 0; transform: translateX(26px) scale(.97); } to { opacity: 1; transform: none; } }
@keyframes oltModalIn { from { opacity: 0; transform: translateY(12px) scale(.97); } to { opacity: 1; transform: none; } }
@keyframes oltFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes oltShimmer { from { background-position: -320px 0; } to { background-position: 320px 0; } }
@keyframes oltIndeterminate { 0% { left: -38%; width: 38%; } 50% { width: 52%; } 100% { left: 100%; width: 34%; } }
@keyframes oltToastBar { from { transform: scaleX(1); } to { transform: scaleX(0); } }
