/* ==========================================================================
   dallelha admin — colour themes, "Full vibe"
   The louder half of every theme in dallelha-themes.css, chosen with the
   Tasteful | Full vibe switch in the theme menu. dallelha-themes.js adds
   data-dl-vibe="full" to <html> — only ever beside a data-dl-theme — and
   everything here hangs off it, so Tasteful is exactly that sheet alone.

   This sheet does what that one may not (glow on text, layers, motion),
   under rules of its own, each enforced by dallelha/tests_admin_themes.py:

   1. Every selector needs data-dl-vibe.
   2. Nothing moves or resizes the page. A real element gets paint only;
      geometry (position, inset, size, transform …) is for the ::before and
      ::after layers this sheet creates, which sit out of flow and never
      take a click (pointer-events: none).
   3. No left or right, as in the Tasteful sheet: no twin in admin/rtl/.
   4. All motion lives in the prefers-reduced-motion block at the end, and
      no cycle is shorter than 2 s — slow, never a flash. Only a layer is
      ever animated, and only its transform or opacity, which the compositor
      does on its own. Animating a real element's shadow instead cost a
      style recalculation on every frame of an otherwise idle page.

   Not enforceable, and the one to hold by hand: glow belongs on headings
   and chrome. Table rows, form fields and running text stay flat.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Art — what each theme paints behind the page
      sky: still, on <body>. back: the layer behind everything, which section
      4 moves. A pattern that slides (stripes, grid, stars) is alone in its
      layer and names its period in --dl-v-tile, so the loop has no seam.
   -------------------------------------------------------------------------- */

:root[data-dl-vibe="full"][data-dl-theme="neon"] {
  --dl-v-sky:
    radial-gradient(60% 45% at 50% 0%, rgba(var(--dl-t-accent), 0.14), transparent 70%),
    radial-gradient(60% 45% at 50% 100%, rgba(var(--dl-t-highlight), 0.12), transparent 70%);
  --dl-v-back:
    radial-gradient(28% 24% at 30% 34%, rgba(var(--dl-t-accent), 0.34), transparent 70%),
    radial-gradient(26% 26% at 68% 62%, rgba(var(--dl-t-highlight), 0.3), transparent 70%),
    radial-gradient(18% 16% at 58% 30%, rgba(var(--dl-t-highlight), 0.16), transparent 70%),
    radial-gradient(20% 18% at 36% 70%, rgba(var(--dl-t-accent), 0.16), transparent 70%);
}

:root[data-dl-vibe="full"][data-dl-theme="cyberpunk"] {
  --dl-v-sky:
    radial-gradient(70% 50% at 50% 0%, rgba(var(--dl-t-accent), 0.13), transparent 70%),
    radial-gradient(70% 50% at 50% 100%, rgba(var(--dl-t-highlight), 0.17), transparent 70%);
  /* 22.627px along the diagonal is 32px down the page. */
  --dl-v-back: repeating-linear-gradient(135deg, rgba(var(--dl-t-accent), 0.075) 0 3px, transparent 3px 22.627px);
  --dl-v-tile: 32px;
}

:root[data-dl-vibe="full"][data-dl-theme="cybersecurity"] {
  --dl-v-sky: radial-gradient(80% 55% at 50% 0%, rgba(var(--dl-t-accent), 0.15), transparent 70%);
  --dl-v-back:
    linear-gradient(rgba(var(--dl-t-accent), 0.11) 1px, transparent 1px),
    linear-gradient(90deg, rgba(var(--dl-t-accent), 0.11) 1px, transparent 1px);
  --dl-v-back-size: 28px 28px;
  --dl-v-tile: 28px;
}

:root[data-dl-vibe="full"][data-dl-theme="aurora"] {
  --dl-v-back:
    radial-gradient(46% 18% at 36% 26%, rgba(var(--dl-t-accent), 0.38), transparent 72%),
    radial-gradient(40% 16% at 62% 32%, rgba(var(--dl-t-highlight), 0.34), transparent 72%),
    radial-gradient(52% 14% at 50% 22%, rgba(var(--dl-t-accent), 0.18), transparent 72%),
    radial-gradient(60% 30% at 50% 82%, rgba(var(--dl-t-highlight), 0.12), transparent 70%);
}

:root[data-dl-vibe="full"][data-dl-theme="midnight"] {
  --dl-v-sky: radial-gradient(45% 38% at 50% 0%, rgba(var(--dl-t-accent), 0.2), transparent 70%);
  --dl-v-back:
    radial-gradient(1.4px 1.4px at 24px 36px, rgba(var(--dl-t-strong), 0.95), transparent),
    radial-gradient(1px 1px at 96px 128px, rgba(var(--dl-t-strong), 0.75), transparent),
    radial-gradient(1.6px 1.6px at 172px 64px, rgba(var(--dl-t-highlight), 0.95), transparent),
    radial-gradient(1px 1px at 140px 188px, rgba(var(--dl-t-strong), 0.65), transparent),
    radial-gradient(1.3px 1.3px at 56px 164px, rgba(var(--dl-t-accent), 0.9), transparent),
    radial-gradient(1px 1px at 204px 12px, rgba(var(--dl-t-strong), 0.6), transparent);
  --dl-v-back-size: 220px 220px;
  --dl-v-tile: 220px;
}

:root[data-dl-vibe="full"][data-dl-theme="graphite"] {
  --dl-v-sky:
    linear-gradient(to bottom, rgba(var(--dl-t-strong), 0.06), transparent 30%),
    repeating-linear-gradient(90deg, rgba(var(--dl-t-strong), 0.022) 0 1px, transparent 1px 4px);
  --dl-v-back: linear-gradient(115deg, transparent 38%, rgba(var(--dl-t-strong), 0.085) 50%, transparent 62%);
}

:root[data-dl-vibe="full"][data-dl-theme="ocean"] {
  --dl-v-sky: linear-gradient(to bottom, rgba(var(--dl-t-sidebar-accent), 0.32), transparent 45%);
  --dl-v-back:
    radial-gradient(26% 22% at 30% 36%, rgba(var(--dl-t-sidebar-accent), 0.55), transparent 70%),
    radial-gradient(24% 24% at 68% 60%, rgba(var(--dl-t-accent), 0.2), transparent 70%),
    radial-gradient(18% 14% at 56% 28%, rgba(255, 255, 255, 0.9), transparent 70%),
    radial-gradient(20% 16% at 38% 72%, rgba(255, 255, 255, 0.8), transparent 70%);
}

:root[data-dl-vibe="full"][data-dl-theme="sandstone"] {
  --dl-v-sky: radial-gradient(70% 48% at 50% 0%, rgba(var(--dl-t-sidebar-accent), 0.55), transparent 70%);
  /* Paper grain: one small tile of noise, rasterised once. */
  --dl-v-back:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.42 0 0 0 0 0.28 0 0 0 0 0.14 0 0 0 0.5 0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E"),
    radial-gradient(40% 30% at 50% 60%, rgba(var(--dl-t-accent), 0.12), transparent 70%);
  --dl-v-back-size: 180px 180px, auto;
}

/* Glow behind a heading. On a light page a dark glow is a smudge, so the
   two light themes get a pale halo instead. */
:root[data-dl-vibe="full"][data-bs-theme="dark"] {
  --dl-v-ink-glow: 0 0 14px rgba(var(--dl-t-accent), 0.65), 0 0 36px rgba(var(--dl-t-accent), 0.35);
}

:root[data-dl-vibe="full"][data-bs-theme="light"] {
  --dl-v-ink-glow: 0 0 18px rgba(var(--dl-t-sidebar-accent), 0.95);
}

/* --------------------------------------------------------------------------
   2. Layers
   -------------------------------------------------------------------------- */

:root[data-dl-vibe="full"] body {
  background-image: var(--dl-v-sky, none);
  background-size: auto;
}

/* Behind everything: z-index -1 is above the page colour and below all
   content, and the cards are opaque, so this only ever shows between them.
   Oversized, so that moving it never brings an edge into view. */
:root[data-dl-vibe="full"] body::before {
  content: "";
  position: fixed;
  inset: -30%;
  z-index: -1;
  pointer-events: none;
  background: var(--dl-v-back, none);
  background-size: var(--dl-v-back-size, auto);
}

/* Cybersecurity only: scanlines over the whole screen, like the tube they
   imitate. Faint enough to be a texture; the text under it stays readable. */
:root[data-dl-vibe="full"][data-dl-theme="cybersecurity"] body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 1090;
  pointer-events: none;
  background: repeating-linear-gradient(to bottom, rgba(0, 0, 0, 0.1) 0 1px, transparent 1px 3px);
}

/* --------------------------------------------------------------------------
   3. Chrome — the same treatment for every theme, in its own colours
   -------------------------------------------------------------------------- */

:root[data-dl-vibe="full"] {
  scrollbar-color: rgba(var(--dl-t-accent), 0.55) transparent;
}

:root[data-dl-vibe="full"] ::selection {
  background-color: rgba(var(--dl-t-accent), 0.35);
}

:root[data-dl-vibe="full"] #jazzy-sidebar {
  --bs-box-shadow: 0 0 34px rgba(var(--dl-t-sidebar-accent), 0.22);
  background-image: linear-gradient(to bottom, rgba(var(--dl-t-sidebar-accent), 0.16), transparent 32%, transparent 68%, rgba(var(--dl-t-highlight), 0.12));
}

:root[data-dl-vibe="full"] .sidebar-brand .brand-text {
  text-shadow: 0 0 12px rgba(var(--dl-t-sidebar-accent), 0.8), 0 0 30px rgba(var(--dl-t-sidebar-accent), 0.4);
}

:root[data-dl-vibe="full"] #jazzy-navigation .nav-icon {
  filter: drop-shadow(0 0 5px currentColor);
}

:root[data-dl-vibe="full"] #jazzy-sidebar .nav-link.active {
  box-shadow: inset 0 0 0 1px rgba(var(--dl-t-sidebar-accent), 0.5), 0 0 14px rgba(var(--dl-t-sidebar-accent), 0.28);
}

/* The part of that glow which breathes, on a layer of its own. */
:root[data-dl-vibe="full"] #jazzy-sidebar .nav-link.active::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  box-shadow: inset 0 0 0 1px rgba(var(--dl-t-sidebar-accent), 0.8), 0 0 24px rgba(var(--dl-t-sidebar-accent), 0.5);
  opacity: 0.55;
}

:root[data-dl-vibe="full"] .app-header {
  border-image: linear-gradient(90deg, rgb(var(--dl-t-accent)), rgb(var(--dl-t-highlight)), rgb(var(--dl-t-accent))) 1;
  box-shadow: 0 2px 26px rgba(var(--dl-t-accent), 0.22);
}

/* The page title, the dashboard's big numbers, card titles. */
:root[data-dl-vibe="full"] :is(.app-content-header h3, .dl-tile__count, .dl-card__title, .card-title, .login-box-msg) {
  text-shadow: var(--dl-v-ink-glow);
}

/* Cyberpunk's title splits into its two colours — the title only: a 2px
   ghost on small text is a blur. */
:root[data-dl-vibe="full"][data-dl-theme="cyberpunk"] .app-content-header h3 {
  text-shadow: -2px 0 rgba(var(--dl-t-highlight), 0.85), 2px 0 rgba(var(--dl-t-accent), 0.55), 0 0 22px rgba(var(--dl-t-accent), 0.4);
}

:root[data-dl-vibe="full"] .card {
  --dl-page-shadow: 0 12px 42px -20px rgba(var(--dl-t-accent), 0.6);
  box-shadow: 0 12px 42px -20px rgba(var(--dl-t-accent), 0.6);
}

/* A card's edge, as a ring in the theme's two colours. The ring is a filled
   box with its middle masked out, so without mask-composite it would be a
   slab of colour over the card: hence @supports, and no ring at all. */
@supports (mask-composite: exclude) {
  :root[data-dl-vibe="full"] .card::after {
    content: "";
    position: absolute;
    inset: -1px;
    padding: 1px;
    border-radius: inherit;
    pointer-events: none;
    background: linear-gradient(135deg, rgb(var(--dl-t-accent)), rgb(var(--dl-t-highlight)) 50%, rgb(var(--dl-t-accent)));
    mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
    opacity: 0.6;
  }
}

/* Not positioned, so no ring to hang on them: a glow instead. */
:root[data-dl-vibe="full"] :is(.dl-tile, .dl-jump, .dl-list-toolbar) {
  border-color: rgba(var(--dl-t-accent), 0.55);
  box-shadow: 0 0 22px rgba(var(--dl-t-accent), 0.22);
}

:root[data-dl-vibe="full"] :is(.btn-primary, .ann-btn-primary) {
  background-image: linear-gradient(135deg, rgb(var(--dl-t-accent)), rgb(var(--dl-t-highlight)));
  box-shadow: 0 0 18px rgba(var(--dl-t-accent), 0.45);
}

:root[data-dl-vibe="full"] :is(.form-control, .form-select):focus {
  box-shadow: 0 0 0 0.2rem rgba(var(--dl-t-accent), 0.28), 0 0 24px rgba(var(--dl-t-accent), 0.45);
}

/* Tables: a line under the header and a tint on hover. The rows stay flat. */
:root[data-dl-vibe="full"] .table {
  --bs-table-hover-bg: rgba(var(--dl-t-accent), 0.09);
}

:root[data-dl-vibe="full"] .table > thead th {
  box-shadow: inset 0 -2px 0 rgba(var(--dl-t-accent), 0.55);
}

:root[data-dl-vibe="full"] .dropdown-menu {
  border-color: rgba(var(--dl-t-accent), 0.45);
  box-shadow: 0 0 30px rgba(var(--dl-t-accent), 0.25);
}

:root[data-dl-vibe="full"] .login-box .card {
  box-shadow: 0 0 70px rgba(var(--dl-t-accent), 0.35);
}

:root[data-dl-vibe="full"] .login-logo img {
  filter: drop-shadow(0 0 22px rgba(var(--dl-t-accent), 0.65));
}

/* --------------------------------------------------------------------------
   4. Motion — only for people who have not asked their device for less
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  /* Movement only, no rotation or scaling: sliding a layer is a copy, where
     turning one means resampling the whole screen on every frame — the
     difference between 60 and 50 frames a second without a GPU. */
  @keyframes dl-v-float {
    from { transform: translate3d(-6%, -5%, 0); }
    to { transform: translate3d(6%, 5%, 0); }
  }

  @keyframes dl-v-sway {
    from { transform: translate3d(-7%, -1%, 0); }
    to { transform: translate3d(7%, 3%, 0); }
  }

  /* One period down the page, then again: seamless. */
  @keyframes dl-v-slide {
    to { transform: translate3d(0, var(--dl-v-tile), 0); }
  }

  @keyframes dl-v-sweep {
    from { transform: translate3d(-40%, 0, 0); }
    to { transform: translate3d(40%, 0, 0); }
  }

  @keyframes dl-v-breathe {
    from { opacity: 0.55; }
    to { opacity: 1; }
  }

  @keyframes dl-v-scan {
    from { transform: translate3d(0, -30vh, 0); }
    to { transform: translate3d(0, 130vh, 0); }
  }

  :root[data-dl-vibe="full"]:is([data-dl-theme="neon"], [data-dl-theme="ocean"]) body::before {
    animation: dl-v-float 44s ease-in-out infinite alternate;
  }

  :root[data-dl-vibe="full"][data-dl-theme="aurora"] body::before {
    animation: dl-v-sway 28s ease-in-out infinite alternate;
  }

  :root[data-dl-vibe="full"]:is([data-dl-theme="cyberpunk"], [data-dl-theme="cybersecurity"]) body::before {
    animation: dl-v-slide 8s linear infinite;
  }

  :root[data-dl-vibe="full"][data-dl-theme="midnight"] body::before {
    animation: dl-v-slide 180s linear infinite, dl-v-breathe 7s ease-in-out infinite alternate;
  }

  :root[data-dl-vibe="full"][data-dl-theme="graphite"] body::before {
    animation: dl-v-sweep 16s ease-in-out infinite alternate;
  }

  :root[data-dl-vibe="full"][data-dl-theme="sandstone"] body::before {
    animation: dl-v-breathe 10s ease-in-out infinite alternate;
  }

  /* Cybersecurity's scan beam. It exists only where it may move: standing
     still it would be a stripe parked across the top of the screen. */
  :root[data-dl-vibe="full"][data-dl-theme="cybersecurity"]::after {
    content: "";
    position: fixed;
    inset: 0 0 auto;
    height: 26vh;
    z-index: 1090;
    pointer-events: none;
    background: linear-gradient(to bottom, transparent, rgba(var(--dl-t-accent), 0.07) 42%, rgba(var(--dl-t-accent), 0.13) 50%, rgba(var(--dl-t-accent), 0.07) 58%, transparent);
    animation: dl-v-scan 9s linear infinite;
  }

  :root[data-dl-vibe="full"] .card::after {
    animation: dl-v-breathe 6s ease-in-out infinite alternate;
  }

  /* Out of step with each other, so a page of cards shimmers, not blinks. */
  :root[data-dl-vibe="full"] .card:nth-of-type(3n + 2)::after {
    animation-delay: -2s;
  }

  :root[data-dl-vibe="full"] .card:nth-of-type(3n)::after {
    animation-delay: -4s;
  }

  :root[data-dl-vibe="full"] #jazzy-sidebar .nav-link.active::after {
    animation: dl-v-breathe 3s ease-in-out infinite alternate;
  }
}
