﻿/*
 * tokens.css
 * mnemosia — global design tokens, keyframes, base reset
 *
 * Usage:
 *   Referenced from mnemosia.Web/wwwroot/css/tokens.css
 *   Linked before app.css in index.html
 *
 * Theme switching:
 *   Default (no attribute) = dark mode (deep navy)
 *   [data-theme="light"]   = light mode (Ice)
 *   ThemeService.cs sets document.documentElement.setAttribute("data-theme", ...)
 *   via JS interop. Persisted in localStorage under key "mnemosia.theme".
 *
 * Localisation note:
 *   No user-facing strings live here. All text is in SharedResources.resx.
 *
 * Copyright (c) 2026 iBorkedIt. Licensed under the ISC License.
 */


/* ================================================================
   SELF-HOSTED FONTS
   Files live in: mnemosia.Web/wwwroot/fonts/
   See download instructions in the project README or the
   companion note produced alongside this file.

   OFL-licensed fonts — self-hosting explicitly permitted.
   No external requests made. GDPR-compliant.
================================================================ */

/* DM Sans — 300 Light */
@font-face {
    font-family: 'DM Sans';
    font-style: normal;
    font-weight: 300;
    font-display: swap;
    src: url('/fonts/dm-sans-300.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* DM Sans — 400 Regular */
@font-face {
    font-family: 'DM Sans';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('/fonts/dm-sans-400.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* DM Sans — 400 Italic */
@font-face {
    font-family: 'DM Sans';
    font-style: italic;
    font-weight: 400;
    font-display: swap;
    src: url('/fonts/dm-sans-400-italic.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* DM Sans — 500 Medium */
@font-face {
    font-family: 'DM Sans';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('/fonts/dm-sans-500.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* DM Sans — 600 SemiBold */
@font-face {
    font-family: 'DM Sans';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('/fonts/dm-sans-600.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Syne — 600 SemiBold */
@font-face {
    font-family: 'Syne';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('/fonts/syne-600.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Syne — 700 Bold */
@font-face {
    font-family: 'Syne';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('/fonts/syne-700.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}




/* ================================================================
   DARK MODE TOKENS  (default — no attribute required)
   Palette: deep navy
================================================================ */
:root {
    /* Surface layers */
    --color-base: #090D14; /* page background */
    --color-s0: #0F1520; /* sidebar, nav, elevated panels */
    --color-s1: #161E2C; /* cards, inputs, popovers */
    --color-s2: #1E2840; /* disabled buttons, deepest inset */
    /* Text */
    --color-text: #A8B8D0; /* primary readable text */
    --color-text-2: #506080; /* secondary text, labels, placeholders */
    --color-text-3: #2E3E58; /* decorative only — SVG strokes, subtle dividers */
    /* Borders & overlays */
    --color-border: rgba(255, 255, 255, 0.06);
    --color-highlight: rgba(255, 255, 255, 0.03); /* card top-edge inner glow */
    --color-shadow: rgba(0, 0, 0, 0.60);
    /* Accent — amber/rust, identical in both modes */
    --color-accent: #E8820C;
    --color-accent-dim: #C06A08;
    --color-accent-glow: rgba(232, 130, 12, 0.18);
    --color-rust: #B84E28;
    /* Semantic */
    --color-error: #D04040;
    --color-error-glow: rgba(208, 64, 64, 0.15);
    --color-ok: #4A9E6A;
    /* Content-type accent stripes */
    --color-stripe-bookmark-top: #E8820C;
    --color-stripe-bookmark-bottom: #B84E28;
    --color-stripe-note-top: #5A9E6A;
    --color-stripe-note-bottom: #3A7E50;
    --color-stripe-snippet-top: #5A78C0;
    --color-stripe-snippet-bottom: #3A58A8;
    --color-stripe-image-top: #8A60C0;
    --color-stripe-image-bottom: #6A40A8;
    /* Typography */
    --font-body: 'DM Sans', sans-serif;
    --font-display: 'Syne', sans-serif;
    /* Spacing scale */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.25rem;
    --space-6: 1.5rem;
    --space-8: 2rem;
    --space-10: 2.5rem;
    --space-12: 3rem;
    /* Radii */
    --radius-sm: 0.375rem;
    --radius-md: 0.625rem;
    --radius-lg: 1rem;
    --radius-xl: 1.25rem;
    --radius-pill: 9999px;
    /* Transitions */
    --transition-fast: 0.15s ease;
    --transition-base: 0.2s ease;
    --transition-slow: 0.35s ease;
    --transition-theme: 0.4s ease; /* used on background/color when theme switches */
    /* Z-index scale */
    --z-base: 0;
    --z-raised: 10;
    --z-overlay: 100;
    --z-modal: 200;
    --z-toast: 300;
    /* ── Vault surfaces ──────────────────────────────────────── */
    --color-surface-base: var(--color-base);
    --color-surface-card: var(--color-s1);
    --color-surface-header: rgba(15, 21, 32, 0.85); /* --color-s0 at 85% */
    --color-surface-hover: var(--color-s2);
    --color-surface-toggle-track: var(--color-s2);
    --color-surface-toggle-active: var(--color-s0);
    --color-surface-image-placeholder: var(--color-s2);
    /* ── Semantic text additions ─────────────────────────────── */
    --color-text-primary: var(--color-text);
    --color-text-secondary: var(--color-text-2);
    --color-text-tertiary: var(--color-text-3);
    --color-text-error: var(--color-error);
    /* ── Border alias ────────────────────────────────────────── */
    --color-border-subtle: var(--color-border);
    /* ── Focus ring alias ────────────────────────────────────── */
    --color-focus-ring: var(--color-accent);
    /* ── Content-type accent stripes (single colour per type) ── */
    --color-accent-default: var(--color-accent);
    --color-accent-bookmark: var(--color-stripe-bookmark-top);
    --color-accent-snippet: var(--color-stripe-snippet-top);
    --color-accent-note: var(--color-stripe-note-top);
    --color-accent-image: var(--color-stripe-image-top);
    /* ── Tag chips ───────────────────────────────────────────── */
    --color-tag-bg: var(--color-s2);
    --color-tag-text: var(--color-text-2);
    --color-tag-overflow-bg: var(--color-accent-glow);
    --color-tag-overflow-text: var(--color-accent);
    /* ── Shadows ─────────────────────────────────────────────── */
    --shadow-card-raised: 0 4px 16px var(--color-shadow);
    --shadow-toggle-active: 0 1px 3px rgba(0, 0, 0, 0.40);
    /* ── Card radius alias ───────────────────────────────────── */
    --radius-card: var(--radius-md);
    /* ── Z-index: header ─────────────────────────────────────── */
    --z-header: var(--z-overlay); /* 100 — sits above cards on scroll */
    /* ── Spacing additions ───────────────────────────────────── */
    --space-0-5: 0.125rem; /*  2px */
    --space-1-5: 0.375rem; /*  6px */
    --space-16: 4rem; /* 64px */
    /* ── Typography additions ────────────────────────────────── */
    --text-2xs: 1rem; /* floored to 16px minimum */
    --text-xs: 1rem;
    --text-sm: 1rem;
    --text-base: 1rem;
    --text-lg: 1.125rem;
    --text-2xl: 1.5rem; /* image placeholder icon */
    /* ── Font weight aliases ─────────────────────────────────── */
    --weight-medium: 500;
    --weight-semibold: 600;
    /* ── Line height aliases ─────────────────────────────────── */
    --leading-snug: 1.3;
    --leading-normal: 1.5;
    /* ── Transition aliases ──────────────────────────────────── */
    --duration-fast: 0.15s;
    --easing-standard: ease;
}

/* ================================================================
   LIGHT MODE TOKENS
   Palette: Ice
   Applied when ThemeService sets data-theme="light" on <html>
================================================================ */
[data-theme="light"] {
    --color-base: #EBF0FA;
    --color-s0: #DCE4F4;
    --color-s1: #F5F8FF;
    --color-s2: #FFFFFF;
    --color-text: #141E3A;
    --color-text-2: #3A4E72;
    --color-text-3: #6878A0; /* decorative only in light mode too */

    --color-border: rgba(20, 40, 100, 0.10);
    --color-highlight: rgba(255, 255, 255, 0.70);
    --color-shadow: rgba(10, 20, 60, 0.14);
    /* Accent unchanged */
    --color-accent: #E8820C;
    --color-accent-dim: #C06A08;
    --color-accent-glow: rgba(232, 130, 12, 0.18);
    --color-rust: #B84E28;
    /* Semantic unchanged */
    --color-error: #D04040;
    --color-error-glow: rgba(208, 64, 64, 0.15);
    --color-ok: #4A9E6A;
    /* Content-type stripes unchanged */
    --color-stripe-bookmark-top: #E8820C;
    --color-stripe-bookmark-bottom: #B84E28;
    --color-stripe-note-top: #5A9E6A;
    --color-stripe-note-bottom: #3A7E50;
    --color-stripe-snippet-top: #5A78C0;
    --color-stripe-snippet-bottom: #3A58A8;
    --color-stripe-image-top: #8A60C0;
    --color-stripe-image-bottom: #6A40A8;
    --color-surface-base: var(--color-base);
    --color-surface-card: var(--color-s2);
    --color-surface-header: rgba(235, 240, 250, 0.85); /* --color-base at 85% */
    --color-surface-hover: var(--color-s0);
    --color-surface-toggle-track: var(--color-s0);
    --color-surface-toggle-active: var(--color-s2);
    --color-surface-image-placeholder: var(--color-s1);
    /* ── Tag chips (light mode has more contrast on white cards) */
    --color-tag-bg: var(--color-s1);
    --color-tag-text: var(--color-text-2);
    --color-tag-overflow-bg: var(--color-accent-glow);
    --color-tag-overflow-text: var(--color-accent-dim);
    /* ── Shadows (softer in light mode) ─────────────────────── */
    --shadow-card-raised: 0 4px 16px var(--color-shadow);
    --shadow-toggle-active: 0 1px 3px rgba(10, 20, 60, 0.18);
}

/* ================================================================
   BASE RESET
================================================================ */
*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html {
    font-size: 16px;
    -webkit-text-size-adjust: 100%;
    /* theme transition applied to html so all descendants inherit it */
    transition: background-color var(--transition-theme), color var(--transition-theme);
}

/* Suppress all transitions while the viewport is being resized.
 * JS in ui.js adds/removes this class around every resize event so that
 * CSS breakpoint changes (e.g. nav layout at 640 px) snap instead of
 * animating. The class is removed 200 ms after the last resize event. */
.mnemosia-resizing *,
.mnemosia-resizing *::before,
.mnemosia-resizing *::after {
    transition: none !important;
    animation-duration: 0s !important;
}

body {
    font-family: var(--font-body);
    font-size: 1rem;
    font-weight: 400;
    line-height: 1.5;
    color: var(--color-text);
    background-color: var(--color-base);
    min-height: 100vh;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* Headings default to display font */
h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-display);
    font-weight: 700;
    line-height: 1.2;
    color: var(--color-text);
}

/* Inputs and buttons inherit font */
input, button, select, textarea {
    font-family: inherit;
    font-size: inherit;
}

/* Remove default button styles */
button {
    background: none;
    border: none;
    cursor: pointer;
    padding: 0;
}

/* Remove default list styles */
ul, ol {
    list-style: none;
}

/* ================================================================
   KEYFRAME ANIMATIONS
================================================================ */

/* Entrance — used on page load and modal open */
@keyframes fadeUp {
    from {
        opacity: 0;
        transform: translateY(18px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Staggered variant with less travel — cards, list items */
@keyframes fadeIn {
    from {
        opacity: 0;
        transform: translateY(8px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Validation failure feedback */
@keyframes shake {
    0%, 100% {
        transform: translateX(0);
    }

    15% {
        transform: translateX(-6px);
    }

    30% {
        transform: translateX(6px);
    }

    45% {
        transform: translateX(-4px);
    }

    60% {
        transform: translateX(4px);
    }

    75% {
        transform: translateX(-2px);
    }

    90% {
        transform: translateX(2px);
    }
}

/* Spinner — async operations */
@keyframes spin {
    from {
        transform: rotate(0deg);
    }

    to {
        transform: rotate(360deg);
    }
}

/* Vault glyph ambient pulse */
@keyframes pulseRing {
    0% {
        transform: scale(1);
        opacity: 0.4;
    }

    50% {
        transform: scale(1.12);
        opacity: 0.15;
    }

    100% {
        transform: scale(1);
        opacity: 0.4;
    }
}

/* Toast slide-in from bottom */
@keyframes slideUp {
    from {
        opacity: 0;
        transform: translateY(12px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Toast slide-out */
@keyframes slideDown {
    from {
        opacity: 1;
        transform: translateY(0);
    }

    to {
        opacity: 0;
        transform: translateY(12px);
    }
}

/* Skeleton shimmer */
@keyframes shimmer {
    0% {
        background-position: -400px 0;
    }

    100% {
        background-position: 400px 0;
    }
}

/* ================================================================
   UTILITY CLASSES
   Kept minimal — components use scoped CSS for specifics.
================================================================ */

/* Animation helpers */
.anim-fade-up {
    animation: fadeUp 0.55s cubic-bezier(0.2, 0, 0, 1) both;
}

.anim-shake {
    animation: shake 0.5s ease both;
}

.anim-spin {
    animation: spin 0.7s linear infinite;
}

/* Delay helpers for staggered entrance */
.delay-1 {
    animation-delay: 0.1s;
}

.delay-2 {
    animation-delay: 0.2s;
}

.delay-3 {
    animation-delay: 0.3s;
}

.delay-4 {
    animation-delay: 0.4s;
}

.delay-5 {
    animation-delay: 0.5s;
}

.delay-6 {
    animation-delay: 0.6s;
}

/* Screen-reader only */
.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;
}

/* Focus ring — keyboard navigation */
:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

/* Skeleton shimmer base */
.skeleton {
    background: linear-gradient( 90deg, var(--color-s1) 25%, var(--color-s2) 50%, var(--color-s1) 75% );
    background-size: 400px 100%;
    animation: shimmer 1.4s ease infinite;
    border-radius: var(--radius-sm);
}

