/* ═══════════════════════════════════════════════════════════════════
   NORDLYS - MAIN STYLES & FOUNDATION
   ═══════════════════════════════════════════════════════════════════ */

/* Bundled faces. Both are OFL and ship inside the extension — an MV3 page may not
   fetch fonts from a CDN. They cover Latin; Cyrillic, CJK and other scripts fall
   through to the system stacks below, per glyph, which is why every stack still
   names a real system face rather than ending at a generic family. */
@font-face {
  font-family: "Outfit";
  src: url("../fonts/outfit.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
}
@font-face {
  font-family: "Instrument Sans";
  src: url("../fonts/instrument-sans.woff2") format("woff2");
  font-weight: 400 700;
  font-display: swap;
}

:root {
  /* Core Geometry & Scaling */
  --tw: 78px;               /* Tile box dimension */
  --grid-gap: 12px 10px;
  --card-radius: 18px;
  --tile-radius: 20px;
  
  /* Primary Surface Tokens (Overridden by themes.css) */
  --void: #060a14;
  --void-gradient: radial-gradient(130% 100% at 50% -10%, #0c1426 0%, #080d1a 45%, var(--void) 100%);
  --glass: rgba(11, 18, 34, 0.46);
  --glass-border: rgba(255, 255, 255, 0.08);
  --frost: rgba(148, 178, 255, 0.16);
  --card-tint: #141c34;
  --card-tint-deep: #090e1c;

  /* Custom Wallpaper Effects (driven by Background settings) */
  --bg-blur: 0px;
  --bg-blur-px: 0;
  --bg-dim: 0;
  
  /* Typography Tokens */
  --ink: #e9effb;
  --dim: #8ca0c4;
  --faint: #7e93b8;
  --accent: #7c9cff;
  --accent-glow: rgba(124, 156, 255, 0.4);
  
  /* Fonts */
  --font-main: "Instrument Sans", "Segoe UI Variable Text", "Segoe UI", "SF Pro Text", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  --font-display: "Outfit", "Segoe UI Variable Display", "Segoe UI", "SF Pro Display", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "Cascadia Code", "JetBrains Mono", Menlo, Consolas, monospace;
}

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

html {
  height: 100%;
  font-size: var(--nl-text-lg);
}

body {
  min-height: 100vh;
  background-color: var(--void);
  background-image: var(--void-gradient);
  background-attachment: fixed;
  background-size: cover;
  background-position: center;
  color: var(--nl-text-primary, var(--ink));
  font-family: var(--font-main);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  transition: background-color var(--nl-transition-panel), color var(--nl-transition-control);
}

/* Solid means solid. The word says it and the preview card shows it, while the
   page went on painting the theme's own radial wash underneath — a fine thing
   to look at, and exactly what the other three scenes are for. This rule used
   to live in the stylesheet for the still compositions; those are gone and it
   is not, because it was never about them. */
html[data-bg="solid"] body {
  background-image: none;
}

/* ── Background Rendering Layers ──────────────────────────────── */
#bg-container {
  position: fixed;
  inset: 0;
  z-index: var(--nl-z-background);
  pointer-events: none;
  overflow: hidden;
}

#bg-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

#bg-media, #bg-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity var(--nl-transition-panel);
  filter: blur(var(--bg-blur));
  /* Slight overscale hides the blurred edge bleed */
  transform: scale(calc(1 + var(--bg-blur-px) / 500));
}
#bg-media.active, #bg-video.active {
  opacity: 1;
}

/* Soft shades behind the words that sit on a wallpaper, placed by
   measureWallpaper in app.js. Above the picture and the chosen dim. */
/* Last in #bg-container, so above the picture and the dim by order alone. */
#wallpaper-scrims { position: absolute; inset: 0; pointer-events: none; }
.wallpaper-scrim { position: absolute; }

/* User-adjustable darkness overlay above custom wallpapers */
#bg-dimmer {
  position: absolute;
  inset: 0;
  background: #02040a;
  opacity: var(--bg-dim);
  pointer-events: none;
  transition: opacity var(--nl-transition-control);
}

/* Vignette + Organic Grain Film */
#veil {
  position: fixed;
  inset: 0;
  z-index: var(--nl-z-veil);
  pointer-events: none;
  background: radial-gradient(120% 92% at 50% 4%, transparent 50%, rgba(2, 4, 10, 0.55) 100%);
  transition: opacity var(--nl-transition-panel);
}

#veil::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: 0.04;
  background-size: 170px 170px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='170' height='170'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='170' height='170' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
}

/* ── Main Layout Frame ────────────────────────────────────────── */
#page {
  position: relative;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 28px;
  padding: 36px 20px 48px;
}

/* ── Utility Animations ───────────────────────────────────────── */
/* There is deliberately no page-entrance animation. This page is opened dozens
   of times a day and looked at for a second or two; a staged arrival is not a
   flourish at that frequency, it is a toll. Motion here belongs to things the
   user starts. */

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

@keyframes pop {
  0% { transform: scale(1); }
  45% { transform: scale(1.025); }
  100% { transform: scale(1); }
}

@keyframes foldaway {
  to { opacity: 0; transform: scale(0.96) translateY(12px); }
}

/* ── Responsive Viewport Adjustments ──────────────────────────── */
@media (max-height: 940px) {
  :root { --tw: 70px; }
  #page { gap: 22px; padding-top: 24px; padding-bottom: 32px; }
}

@media (max-height: 820px) {
  :root { --tw: 62px; }
  #page { gap: 18px; }
}

@media (max-width: 860px) {
  .card { flex: 1 1 100%; max-width: 100%; }
  .grid[data-cols] { grid-template-columns: repeat(auto-fill, minmax(64px, 1fr)); width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  /* Nothing moves: keyframe animations stop, transforms and filters are
     dropped, and a transition may only fade or recolour, briefly. This used
     to stretch every transition on every element to 80ms, and an element with
     none declared transitions all of its properties, so under "reduce" gaps,
     widths and positions began to glide, and an opening menu stayed hidden
     for those 80ms, too long for focus to go into it. Centring that must
     survive uses `translate`, which `transform: none` leaves alone. */
  *, *::before, *::after {
    animation: none !important;
    animation-delay: 0s !important;
    transition-property: opacity, color, background-color, border-color, outline-color, fill, stroke, box-shadow !important;
    transition-duration: 80ms !important;
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
    transform: none !important;
    filter: none !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
  }
}


