/**
 * polaris.css — Polaris (cosmic) appearance, SHARED design-token layer.
 *
 * The Polaris "Utseende" mode (EngWS-Theme) rides on the dark base: ThemeCustomizer
 * sets body.dark (Mörkt base) AND body.polaris (cosmic skin). Apps that don't carry
 * a Polaris layer degrade to plain dark — which is why Polaris was Verkstad-only at
 * first (the palette lived in apps/eng/styles/app.css against eng's OWN vars).
 *
 * This file lifts the SHARED design-token cosmic palette + the generic flair out of
 * eng/app.css so any app that loads it gets real Polaris instead of plain dark.
 * Adopters: the Studio editor cockpit, Site Builder, and (2026-08-06) the 360 hub
 * surfaces — the Projects app (360 + Karta tab), /engineering, and
 * /core/engineering-map. Portal-wide beyond that still pending. It overrides theme.css's dark
 * shared tokens by specificity (body.polaris.dark = 0,2,1 > theme's 0,1,x). Token
 * values are kept in sync with eng/app.css's `body.polaris.dark` block.
 *
 * Every page links it directly BEFORE theme.css (it used to be an @import at the
 * top of theme.css, which kept it out of the versioned, cached URLs). Keep the
 * two together. Does nothing unless body has BOTH .dark and .polaris.
 */

/* ---------- cosmic palette → shared design tokens ----------
 *
 * Polaris takes a PALETTE (Dennis 2026-09-10). Rather than hand-authoring
 * eleven cosmic token blocks, the whole skin hangs off two hues:
 *
 *   --pol-h        the cosmic base hue, carried by the surfaces, borders and
 *                  body text at Polaris' low saturation
 *   --pol-accent-h the signature accent hue (--primary and the ring glow)
 *
 * Every surface token keeps its ORIGINAL offset from that base, so the
 * default (--pol-h: 205, --pol-accent-h: 355) reproduces the previous values
 * byte for byte: foreground 192 = 205-13, card 218 = 205+13, popover 220 =
 * 205+15, secondary/accent 200 = 205-5, muted 205, border/input 195 = 205-10,
 * ring 192 = 205-13. Saturation and lightness never move, which is what keeps
 * every palette recognisably Polaris rather than "dark mode with a tint".
 *
 * --background stays achromatic (0% saturation), so the deep void is the same
 * in every palette and only the surfaces above it take the hue.
 */
body.polaris {
  --pol-h: 205;
  --pol-accent-h: 355;

  /* Derived cosmic colours, previously hardcoded as rgba(156,222,242) and
   * rgba(53,90,102) in the starfield, rain, scrollbars and the /eng grids.
   * Both were hue 195 = --pol-h - 10, so they now follow the palette instead
   * of staying icy blue under an orange or green sky. */
  --pol-star:   calc(var(--pol-h) - 10) 79% 78%;
  --pol-scroll: calc(var(--pol-h) - 10) 32% 30%;
}

body.polaris.dark {
  --background: 0 0% 7%;                          --foreground: calc(var(--pol-h) - 13) 70% 80%;
  --card: calc(var(--pol-h) + 13) 16% 15%;        --card-foreground: calc(var(--pol-h) - 13) 70% 80%;
  --popover: calc(var(--pol-h) + 15) 17% 12%;     --popover-foreground: calc(var(--pol-h) - 13) 70% 80%;
  --primary: var(--pol-accent-h) 75% 68%;         --primary-foreground: 0 0% 8%;
  --secondary: calc(var(--pol-h) - 5) 18% 18%;    --secondary-foreground: calc(var(--pol-h) - 13) 70% 80%;
  --muted: var(--pol-h) 16% 16%;                  --muted-foreground: calc(var(--pol-h) - 12) 20% 60%;
  --accent: calc(var(--pol-h) - 5) 18% 20%;       --accent-foreground: calc(var(--pol-h) - 13) 70% 80%;
  --destructive: 0 72% 55%;                       --destructive-foreground: 0 0% 98%;
  --border: calc(var(--pol-h) - 10) 30% 30%;
  --input: calc(var(--pol-h) - 10) 30% 26%;
  --ring: calc(var(--pol-h) - 13) 70% 60%;
}

/* ---------- per-palette cosmic hues ----------
 * body.polaris[data-theme="x"] = 0,3,1 beats the base block's 0,2,1.
 *
 * RULE (Dennis 2026-09-10, after the first pass got this wrong): the ACCENT
 * hue is the palette's OWN --primary hue, so what Polaris renders matches the
 * swatch the user clicked. The first attempt picked "contrasting" accents,
 * which is why Yellow, Code, Orange and Red looked unrelated to their names.
 * The surface hue sits within ~10deg of the accent so the skin reads as one
 * family; Polaris' low saturation keeps even Orange a warm charcoal rather
 * than an orange screen.
 *
 * Source hues, read from each palette's own .dark block in theme.css:
 *   blue 217 · darkblue 217 · green 142 · orange 20.5 · red 0 · rose 347
 *   violet 263 · yellow 48 · code 207 · warm 40 · default(Stone) achromatic
 *
 * Stone keeps the classic 205/355 because its --primary is achromatic white:
 * there is no hue to borrow, and 205/355 IS the Polaris that shipped. That
 * also makes Stone and Darkblue distinct, which they were not before.
 */
body.polaris[data-theme="darkblue"] { --pol-h: 217; --pol-accent-h: 217; }
body.polaris[data-theme="blue"]     { --pol-h: 212; --pol-accent-h: 217; }
body.polaris[data-theme="green"]    { --pol-h: 152; --pol-accent-h: 142; }
body.polaris[data-theme="violet"]   { --pol-h: 258; --pol-accent-h: 263; }
body.polaris[data-theme="rose"]     { --pol-h: 338; --pol-accent-h: 347; }
body.polaris[data-theme="red"]      { --pol-h: 353; --pol-accent-h: 0;   }
body.polaris[data-theme="orange"]   { --pol-h: 28;  --pol-accent-h: 21;  }
body.polaris[data-theme="yellow"]   { --pol-h: 42;  --pol-accent-h: 48;  }
body.polaris[data-theme="code"]     { --pol-h: 200; --pol-accent-h: 207; }
body.polaris[data-theme="warm"]     { --pol-h: 33;  --pol-accent-h: 40;  }
body.polaris[data-theme="stegvis"]  { --pol-h: 166; --pol-accent-h: 161; }

/* ---------- signature flair (purely cosmetic) ---------- */
/* No font-family: the user's TYPSNITT applies under Polaris too (a forced
   Fira Code, never loaded, hid it; 2026-09-27). Mono gives the old feel. */
body.polaris {
  font-variant-ligatures: none;
}

/* teal scrollbars on the cosmic surface */
body.polaris ::-webkit-scrollbar-thumb {
  background: hsl(var(--pol-scroll) / 0.85);
  border: 3px solid hsl(var(--card));
}
body.polaris ::-webkit-scrollbar-thumb:hover { background: hsl(var(--pol-star) / 0.55); }

/* ---------- subtle starfield (Dennis 2026-08-06) ---------- */
/* Two fixed, pointer-transparent pseudo-layers on body. An overlay (not a
 * body background) on purpose: every adopter paints opaque
 * hsl(var(--background)) shells over the body, so a background-image there
 * would never show. The dot alphas are tuned to read as atmosphere over the
 * dark cosmic surfaces and disappear over text at 1-2px size; per-layer
 * background-sizes are co-prime-ish so the tiling never lines up into a
 * visible grid. No JS, no per-app CSS — anything loading this file gets the
 * sky. Inert without body.polaris.dark, like everything above. */
body.polaris.dark::before,
body.polaris.dark::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 2147483647;
  pointer-events: none;
}
/* dense faint layer — slow breathe so more of the sky moves */
body.polaris.dark::before {
  animation: polarisBreathe 9s ease-in-out infinite alternate;
  background-image:
    radial-gradient(2.2px 2.2px at 25px 35px,   rgba(199, 235, 255, 0.42) 0, rgba(199, 235, 255, 0.10) 50%, transparent 100%),
    radial-gradient(2px 2px at 190px 90px,       hsl(var(--pol-star) / 0.38) 0, hsl(var(--pol-star) / 0.09) 50%, transparent 100%),
    radial-gradient(2.6px 2.6px at 110px 200px,  rgba(255, 255, 255, 0.40) 0, rgba(255, 255, 255, 0.10) 50%, transparent 100%),
    radial-gradient(2px 2px at 240px 160px,      hsl(var(--pol-star) / 0.30) 0, hsl(var(--pol-star) / 0.08) 50%, transparent 100%),
    radial-gradient(2px 2px at 60px 250px,       rgba(199, 235, 255, 0.34) 0, rgba(199, 235, 255, 0.08) 50%, transparent 100%),
    radial-gradient(2px 2px at 150px 20px,       rgba(255, 255, 255, 0.28) 0, rgba(255, 255, 255, 0.07) 50%, transparent 100%);
  background-size: 277px 277px, 341px 341px, 307px 307px, 263px 263px, 331px 331px, 293px 293px;
}
/* sparse brighter layer — slow twinkle */
body.polaris.dark::after {
  background-image:
    radial-gradient(3.4px 3.4px at 80px 120px,  rgba(255, 255, 255, 0.70) 0, rgba(255, 255, 255, 0.16) 45%, transparent 100%),
    radial-gradient(3px 3px at 320px 280px,     hsl(var(--pol-star) / 0.62) 0, hsl(var(--pol-star) / 0.14) 45%, transparent 100%),
    radial-gradient(3.6px 3.6px at 210px 40px,  rgba(199, 235, 255, 0.55) 0, rgba(199, 235, 255, 0.13) 45%, transparent 100%);
  background-size: 421px 421px, 463px 463px, 521px 521px;
  /* 14 s was too slow to read as a twinkle (Dennis 2026-09-05). */
  animation: polarisTwinkle 4.5s ease-in-out infinite alternate;
}
@keyframes polarisTwinkle {
  from { opacity: 0.35; }
  to   { opacity: 1; }
}
@keyframes polarisBreathe {
  from { opacity: 0.55; }
  to   { opacity: 1; }
}

/* ---------- background effect picker (body.polaris-fx-*) ---------- */
/* theme-customizer.js sets polaris-fx-rain / polaris-fx-none from the
   Installningar picker; the default (stars) needs no class. */
body.polaris.dark.polaris-fx-none::before,
body.polaris.dark.polaris-fx-none::after {
  display: none;
}
/* rain: short drops (thin ellipses on co-prime tiles so no grid shows),
   two layers falling at different speeds, the whole sheet skewed a few
   degrees so the drops lean. Each loop moves exactly one tile height. */
body.polaris.dark.polaris-fx-rain::before,
body.polaris.dark.polaris-fx-rain::after {
  inset: -15%;
  transform: skewX(-8deg);
}
body.polaris.dark.polaris-fx-rain::before {
  background-image:
    radial-gradient(1.2px 26px at 19px 60px,  hsl(var(--pol-star) / 0.05) 0 88%, transparent 100%),
    radial-gradient(1px   20px at 61px 170px, hsl(var(--pol-star) / 0.06) 0 88%, transparent 100%),
    radial-gradient(1px   18px at 103px 110px, rgba(199, 235, 255, 0.045) 0 88%, transparent 100%),
    radial-gradient(1px   22px at 140px 230px, hsl(var(--pol-star) / 0.05) 0 88%, transparent 100%);
  background-size: 173px 271px, 173px 271px, 173px 271px, 173px 271px;
  animation: polarisRainA 1.15s linear infinite;
  opacity: 1;
}
body.polaris.dark.polaris-fx-rain::after {
  background-image:
    radial-gradient(1.6px 34px at 40px 90px,  rgba(199, 235, 255, 0.10) 0 88%, transparent 100%),
    radial-gradient(1.4px 30px at 150px 250px, rgba(199, 235, 255, 0.085) 0 88%, transparent 100%),
    radial-gradient(1.4px 28px at 230px 40px, hsl(var(--pol-star) / 0.07) 0 88%, transparent 100%);
  background-size: 263px 359px, 263px 359px, 263px 359px;
  animation: polarisRainB 0.8s linear infinite;
  opacity: 1;
}
@keyframes polarisRainA {
  from { background-position: 0 0; }
  to   { background-position: 0 271px; }
}
@keyframes polarisRainB {
  from { background-position: 0 0; }
  to   { background-position: 0 359px; }
}
@media (prefers-reduced-motion: reduce) {
  body.polaris.dark::before,
  body.polaris.dark::after { animation: none; }
}
/* Animationer off in the user settings stops the sky and the rain too. */
body.polaris.dark.no-animations::before,
body.polaris.dark.no-animations::after { animation: none; }
