/*
 * Kagaku design system — the single source of the visual language (ADR 0023).
 * Sections: font · reset · theme inputs, modes and resolved tokens · base elements · utilities.
 * Shared visual roles use tokens; components may retain documented structural and optical constants.
 */

/* ------------------------------------------------------------------ font --- */

/* Inter 4.1, both faces of the release, unmodified (SIL OFL 1.1 — fonts/Inter-LICENSE.txt). The
   italic is its own face, so <em> is drawn, not a slant the browser fakes from the upright. */
@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 100 900; /* variable */
    font-display: swap;
    src: url("../fonts/InterVariable.woff2") format("woff2");
}

@font-face {
    font-family: "Inter";
    font-style: italic;
    font-weight: 100 900; /* variable */
    font-display: swap;
    src: url("../fonts/InterVariable-Italic.woff2") format("woff2");
}

/* ----------------------------------------------------------------- reset --- */

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

* {
    margin: 0;
}

html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;

    /* The viewport never scrolls (ADR 0025): the app shell is exactly one viewport tall and the
       content region inside it is the sole scroll container. scroll-padding-top for anchor jumps
       and the quicklink scroll-spy lives on that region (.app-shell__main), not here. Assumes
       every route renders inside MainLayout (Routes.razor's DefaultLayout enforces this today) —
       a bare @layout-less page would find itself unable to scroll at all. */
    overflow: hidden;
}

body {
    min-height: 100dvh;
    line-height: var(--leading-normal);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

img,
svg,
video,
canvas {
    display: block;
    max-width: 100%;
}

button,
input,
textarea,
select {
    font: inherit;
    font-family: var(--font-sans);
    font-size: var(--text-base);
    font-weight: var(--font-weight-normal);
    line-height: var(--leading-normal);
    color: inherit;
}

:where(a) {
    color: var(--accent-text);
    text-decoration: none;
}

:where(a:hover) {
    text-decoration: underline;
}

/* ---------------------------------------------------------------- tokens --- */

/* Mode-independent values and palette INPUT defaults live at the document root. Consumers
   override --<role>-light / --<role>-dark, or --<role>-override for a value shared by both
   modes. Components consume the resolved --<role> OUTPUTS below. All selectors have zero
   specificity so consumer input declarations retain the ordinary CSS cascade. */

:where(:root) {
    /* Typography */
    --font-sans: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    --font-mono: ui-monospace, "Cascadia Code", "SF Mono", Menlo, Consolas, monospace;

    /* Independent UI size roles. Change the complete scale deliberately; changing base alone
       does not derive a different heading or metadata size. */
    --text-xs: 0.6875rem;  /* 11px */
    --text-sm: 0.8125rem;  /* 13px */
    --text-base: 0.875rem; /* 14px — dense, information-first */
    --text-lg: 1rem;       /* 16px */
    --text-xl: 1.25rem;    /* 20px */
    --text-2xl: 1.5rem;    /* 24px */

    --font-weight-normal: 400;
    --font-weight-medium: 500;
    --font-weight-semibold: 600;
    --font-weight-bold: 700;

    --leading-tight: 1.25;
    --leading-normal: 1.5;
    --leading-compact: 1.4;
    --leading-control: 1;
    --code-size: 0.9em;
    /* --leading-code is optional: code blocks and Diff resolve their local fallback at use. */

    /* Spacing — 4px base */
    --space-1: 0.25rem;  /* 4 */
    --space-2: 0.5rem;   /* 8 */
    --space-3: 0.75rem;  /* 12 */
    --space-4: 1rem;     /* 16 */
    --space-5: 1.5rem;   /* 24 */
    --space-6: 2rem;     /* 32 */
    --space-7: 3rem;     /* 48 */
    --space-8: 4rem;     /* 64 */

    /* Radii */
    --radius-sm: 4px;
    --radius-md: 7px;
    --radius-lg: 11px;
    --radius-full: 999px;

    /* Control sizing — the shared height for inputs and buttons so they line up in a row */
    --control-height: 2.25rem;
    --control-height-sm: 1.75rem;

    /* Chrome — the app header's height; page shells subtract it to fill exactly one viewport */
    --app-header-height: 3.25rem;

    /* Layout — the shared maximum width for every page shell (projects list, workspace, settings),
       so navigation between pages never causes a width jump (ADR 0023). */
    --shell-max-width: 90rem;

    /* Z-index layers */
    --z-base: 0;
    --z-dropdown: 1000;
    --z-sticky: 1100;
    --z-drawer: 1200;
    --z-modal: 1300;
    --z-toast: 1400;

    /* Motion */
    --dur-fast: 100ms;
    --dur-base: 180ms;
    --dur-slow: 300ms;
    --ease: cubic-bezier(0.2, 0, 0, 1);

    /* Color — light theme (semantic roles, not raw hues) */
    --bg-light: #f6f6f8;
    --surface-light: #ffffff;
    --surface-raised-light: #ffffff;
    --surface-sunken-light: #f0f0f3;
    --surface-hover-light: #f4f4f6;

    --text-light: #1b1b20;
    --text-muted-light: #6a6a75;
    --text-subtle-light: #9b9ba4;

    --border-light: #e5e5ea;
    --border-strong-light: #d3d3da;

    /* Strong tones are graphical marks and supported solid fills. Text and subtle surfaces
       are independent authored roles; changing a strong color never generates its peers. */
    --neutral-light: #71717a;
    --neutral-text-light: #6a6a75;
    --neutral-subtle-light: #f0f0f3;

    --accent-light: #5850ec;
    --accent-text-light: #5850ec;
    --accent-hover-light: #453ddb;
    --accent-contrast-light: #ffffff;
    --accent-subtle-light: #edecfd;

    --success-light: #15803d;
    --success-text-light: #137437;
    --success-subtle-light: #e6f4ea;
    --warning-light: #b45309;
    --warning-text-light: #9a4708;
    --warning-subtle-light: #fbefe0;
    --danger-light: #c62828;
    --danger-text-light: #c62828;
    --danger-subtle-light: #fbe9e9;
    --danger-hover-light: #a91f1f;
    --danger-contrast-light: #ffffff;
    --info-light: #1d4ed8;
    --info-text-light: #1d4ed8;
    --info-subtle-light: #e7edfc;

    /* Categorical palette — a qualitative scale for domain categories (e.g. lore). Unlike the
       semantic tones above, a swatch carries no meaning: it is picked by identity, to tell one
       category from another. Each pairs a foreground with a subtle background tint, like the tones. */
    --swatch-1-light: #7c3aed; --swatch-1-subtle-light: #f0ebfe;
    --swatch-2-light: #1d4ed8; --swatch-2-subtle-light: #e7effe;
    --swatch-3-light: #be185d; --swatch-3-subtle-light: #fce8f1;
    --swatch-4-light: #9a4708; --swatch-4-subtle-light: #fbefdd;
    --swatch-5-light: #0c6d65; --swatch-5-subtle-light: #e0f5f2;
    --swatch-6-light: #be123c; --swatch-6-subtle-light: #fde8ec;
    --swatch-7-light: #137437; --swatch-7-subtle-light: #e6f6ec;
    --swatch-8-light: #53637b; --swatch-8-subtle-light: #eef1f5;

    /* Elevation */
    --shadow-1-light: 0 1px 2px rgba(20, 20, 30, 0.06), 0 1px 1px rgba(20, 20, 30, 0.04);
    --shadow-2-light: 0 2px 8px rgba(20, 20, 30, 0.08);
    --shadow-3-light: 0 12px 32px rgba(20, 20, 30, 0.14);


    /* Dark palette inputs (including complete, mode-dependent shadow geometries). */
    --bg-dark: #101013;
    --surface-dark: #1a1a1f;
    --surface-raised-dark: #232329;
    --surface-sunken-dark: #141417;
    --surface-hover-dark: #26262d;

    --text-dark: #ececf0;
    --text-muted-dark: #9c9ca6;
    --text-subtle-dark: #6c6c76;

    --border-dark: #2c2c34;
    --border-strong-dark: #3b3b45;

    --neutral-dark: #9c9ca6;
    --neutral-text-dark: #9c9ca6;
    --neutral-subtle-dark: #141417;

    --accent-dark: #837bf5;
    --accent-text-dark: #8b83f8;
    --accent-hover-dark: #948df7;
    --accent-contrast-dark: #14121f;
    --accent-subtle-dark: #24223a;

    --success-dark: #4ade80;
    --success-text-dark: #4ade80;
    --success-subtle-dark: #16261c;
    --warning-dark: #fbbf5a;
    --warning-text-dark: #fbbf5a;
    --warning-subtle-dark: #2a2013;
    --danger-dark: #f87171;
    --danger-text-dark: #f87171;
    --danger-subtle-dark: #2a1717;
    --danger-hover-dark: #fa8f8f;
    --danger-contrast-dark: #14121f;
    --info-dark: #7aa2f7;
    --info-text-dark: #7aa2f7;
    --info-subtle-dark: #161e2e;

    --swatch-1-dark: #a78bfa; --swatch-1-subtle-dark: #241f38;
    --swatch-2-dark: #60a5fa; --swatch-2-subtle-dark: #16213a;
    --swatch-3-dark: #f472b6; --swatch-3-subtle-dark: #2e1723;
    --swatch-4-dark: #fbbf5a; --swatch-4-subtle-dark: #2a2013;
    --swatch-5-dark: #2dd4bf; --swatch-5-subtle-dark: #0f2a27;
    --swatch-6-dark: #fb7185; --swatch-6-subtle-dark: #2c1720;
    --swatch-7-dark: #4ade80; --swatch-7-subtle-dark: #16261c;
    --swatch-8-dark: #94a3b8; --swatch-8-subtle-dark: #1e242c;

    --shadow-1-dark: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-2-dark: 0 2px 10px rgba(0, 0, 0, 0.45);
    --shadow-3-dark: 0 14px 36px rgba(0, 0, 0, 0.55);

}

/* Mode state is inherited separately from palette inputs. A missing root choice follows the
   OS. A local Inherit scope declares no state; System chooses locally, even under a forced
   parent. These unregistered private properties intentionally distinguish guaranteed-invalid
   initial from a valid empty token list: the active branch uses its var() fallback, while the
   inactive branch contributes no tokens. This also supports arbitrary shadow grammars. */
:where(:root, [data-kg-theme-scope][data-theme="system"], [data-kg-theme-scope][data-theme="light"]) {
    --_kg-light: initial;
    --_kg-dark: ;
    color-scheme: light;
}

@media (prefers-color-scheme: dark) {
    :where(:root:not([data-theme]), :root[data-theme="system"], [data-kg-theme-scope][data-theme="system"]) {
        --_kg-light: ;
        --_kg-dark: initial;
        color-scheme: dark;
    }
}

:where(:root[data-theme="dark"], [data-kg-theme-scope][data-theme="dark"]) {
    --_kg-light: ;
    --_kg-dark: initial;
    color-scheme: dark;
}

/* OUTPUTS resolve again at every boundary, including Inherit scopes. Repeating defaults
   here would erase a consumer's inherited brand; inheriting resolved outputs would freeze
   the parent's selected mode and prevent local input changes. */
:where(:root, [data-kg-theme-scope]) {
    --bg: var(--bg-override, var(--_kg-light, var(--bg-light)) var(--_kg-dark, var(--bg-dark)));
    --surface: var(--surface-override, var(--_kg-light, var(--surface-light)) var(--_kg-dark, var(--surface-dark)));
    --surface-raised: var(--surface-raised-override, var(--_kg-light, var(--surface-raised-light)) var(--_kg-dark, var(--surface-raised-dark)));
    --surface-sunken: var(--surface-sunken-override, var(--_kg-light, var(--surface-sunken-light)) var(--_kg-dark, var(--surface-sunken-dark)));
    --surface-hover: var(--surface-hover-override, var(--_kg-light, var(--surface-hover-light)) var(--_kg-dark, var(--surface-hover-dark)));
    --text: var(--text-override, var(--_kg-light, var(--text-light)) var(--_kg-dark, var(--text-dark)));
    --text-muted: var(--text-muted-override, var(--_kg-light, var(--text-muted-light)) var(--_kg-dark, var(--text-muted-dark)));
    --text-subtle: var(--text-subtle-override, var(--_kg-light, var(--text-subtle-light)) var(--_kg-dark, var(--text-subtle-dark)));
    --border: var(--border-override, var(--_kg-light, var(--border-light)) var(--_kg-dark, var(--border-dark)));
    --border-strong: var(--border-strong-override, var(--_kg-light, var(--border-strong-light)) var(--_kg-dark, var(--border-strong-dark)));
    --neutral: var(--neutral-override, var(--_kg-light, var(--neutral-light)) var(--_kg-dark, var(--neutral-dark)));
    --neutral-text: var(--neutral-text-override, var(--_kg-light, var(--neutral-text-light)) var(--_kg-dark, var(--neutral-text-dark)));
    --neutral-subtle: var(--neutral-subtle-override, var(--_kg-light, var(--neutral-subtle-light)) var(--_kg-dark, var(--neutral-subtle-dark)));
    --accent: var(--accent-override, var(--_kg-light, var(--accent-light)) var(--_kg-dark, var(--accent-dark)));
    --accent-text: var(--accent-text-override, var(--_kg-light, var(--accent-text-light)) var(--_kg-dark, var(--accent-text-dark)));
    --accent-hover: var(--accent-hover-override, var(--_kg-light, var(--accent-hover-light)) var(--_kg-dark, var(--accent-hover-dark)));
    --accent-contrast: var(--accent-contrast-override, var(--_kg-light, var(--accent-contrast-light)) var(--_kg-dark, var(--accent-contrast-dark)));
    --accent-subtle: var(--accent-subtle-override, var(--_kg-light, var(--accent-subtle-light)) var(--_kg-dark, var(--accent-subtle-dark)));
    --success: var(--success-override, var(--_kg-light, var(--success-light)) var(--_kg-dark, var(--success-dark)));
    --success-text: var(--success-text-override, var(--_kg-light, var(--success-text-light)) var(--_kg-dark, var(--success-text-dark)));
    --success-subtle: var(--success-subtle-override, var(--_kg-light, var(--success-subtle-light)) var(--_kg-dark, var(--success-subtle-dark)));
    --warning: var(--warning-override, var(--_kg-light, var(--warning-light)) var(--_kg-dark, var(--warning-dark)));
    --warning-text: var(--warning-text-override, var(--_kg-light, var(--warning-text-light)) var(--_kg-dark, var(--warning-text-dark)));
    --warning-subtle: var(--warning-subtle-override, var(--_kg-light, var(--warning-subtle-light)) var(--_kg-dark, var(--warning-subtle-dark)));
    --danger: var(--danger-override, var(--_kg-light, var(--danger-light)) var(--_kg-dark, var(--danger-dark)));
    --danger-text: var(--danger-text-override, var(--_kg-light, var(--danger-text-light)) var(--_kg-dark, var(--danger-text-dark)));
    --danger-subtle: var(--danger-subtle-override, var(--_kg-light, var(--danger-subtle-light)) var(--_kg-dark, var(--danger-subtle-dark)));
    --danger-hover: var(--danger-hover-override, var(--_kg-light, var(--danger-hover-light)) var(--_kg-dark, var(--danger-hover-dark)));
    --danger-contrast: var(--danger-contrast-override, var(--_kg-light, var(--danger-contrast-light)) var(--_kg-dark, var(--danger-contrast-dark)));
    --info: var(--info-override, var(--_kg-light, var(--info-light)) var(--_kg-dark, var(--info-dark)));
    --info-text: var(--info-text-override, var(--_kg-light, var(--info-text-light)) var(--_kg-dark, var(--info-text-dark)));
    --info-subtle: var(--info-subtle-override, var(--_kg-light, var(--info-subtle-light)) var(--_kg-dark, var(--info-subtle-dark)));
    --swatch-1: var(--swatch-1-override, var(--_kg-light, var(--swatch-1-light)) var(--_kg-dark, var(--swatch-1-dark)));
    --swatch-1-subtle: var(--swatch-1-subtle-override, var(--_kg-light, var(--swatch-1-subtle-light)) var(--_kg-dark, var(--swatch-1-subtle-dark)));
    --swatch-2: var(--swatch-2-override, var(--_kg-light, var(--swatch-2-light)) var(--_kg-dark, var(--swatch-2-dark)));
    --swatch-2-subtle: var(--swatch-2-subtle-override, var(--_kg-light, var(--swatch-2-subtle-light)) var(--_kg-dark, var(--swatch-2-subtle-dark)));
    --swatch-3: var(--swatch-3-override, var(--_kg-light, var(--swatch-3-light)) var(--_kg-dark, var(--swatch-3-dark)));
    --swatch-3-subtle: var(--swatch-3-subtle-override, var(--_kg-light, var(--swatch-3-subtle-light)) var(--_kg-dark, var(--swatch-3-subtle-dark)));
    --swatch-4: var(--swatch-4-override, var(--_kg-light, var(--swatch-4-light)) var(--_kg-dark, var(--swatch-4-dark)));
    --swatch-4-subtle: var(--swatch-4-subtle-override, var(--_kg-light, var(--swatch-4-subtle-light)) var(--_kg-dark, var(--swatch-4-subtle-dark)));
    --swatch-5: var(--swatch-5-override, var(--_kg-light, var(--swatch-5-light)) var(--_kg-dark, var(--swatch-5-dark)));
    --swatch-5-subtle: var(--swatch-5-subtle-override, var(--_kg-light, var(--swatch-5-subtle-light)) var(--_kg-dark, var(--swatch-5-subtle-dark)));
    --swatch-6: var(--swatch-6-override, var(--_kg-light, var(--swatch-6-light)) var(--_kg-dark, var(--swatch-6-dark)));
    --swatch-6-subtle: var(--swatch-6-subtle-override, var(--_kg-light, var(--swatch-6-subtle-light)) var(--_kg-dark, var(--swatch-6-subtle-dark)));
    --swatch-7: var(--swatch-7-override, var(--_kg-light, var(--swatch-7-light)) var(--_kg-dark, var(--swatch-7-dark)));
    --swatch-7-subtle: var(--swatch-7-subtle-override, var(--_kg-light, var(--swatch-7-subtle-light)) var(--_kg-dark, var(--swatch-7-subtle-dark)));
    --swatch-8: var(--swatch-8-override, var(--_kg-light, var(--swatch-8-light)) var(--_kg-dark, var(--swatch-8-dark)));
    --swatch-8-subtle: var(--swatch-8-subtle-override, var(--_kg-light, var(--swatch-8-subtle-light)) var(--_kg-dark, var(--swatch-8-subtle-dark)));
    --shadow-1: var(--shadow-1-override, var(--_kg-light, var(--shadow-1-light)) var(--_kg-dark, var(--shadow-1-dark)));
    --shadow-2: var(--shadow-2-override, var(--_kg-light, var(--shadow-2-light)) var(--_kg-dark, var(--shadow-2-dark)));
    --shadow-3: var(--shadow-3-override, var(--_kg-light, var(--shadow-3-light)) var(--_kg-dark, var(--shadow-3-dark)));
}

/* --------------------------------------------------------- base elements --- */

body {
    font-family: var(--font-sans);
    font-size: var(--text-base);
    font-weight: var(--font-weight-normal);
    color: var(--text);
    background-color: var(--bg);
}

h1,
h2,
h3,
h4,
h5,
h6 {
    line-height: var(--leading-tight);
    font-weight: var(--font-weight-semibold);
    color: var(--text);
}

h1 { font-size: var(--text-2xl); }
h2 { font-size: var(--text-xl); }
h3 { font-size: var(--text-lg); }
h4, h5, h6 { font-size: var(--text-base); }

strong,
b {
    font-weight: var(--font-weight-bold);
}

small {
    font-size: var(--text-sm);
    color: var(--text-muted);
}

code,
kbd,
samp {
    font-family: var(--font-mono);
    font-size: var(--code-size);
}

hr {
    border: none;
    border-top: 1px solid var(--border);
}

:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring, 0 0 0 3px color-mix(in srgb, var(--accent) 35%, transparent));
    border-radius: var(--radius-sm);
}

::selection {
    background: color-mix(in srgb, var(--accent) 25%, transparent);
}

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

/* -------------------------------------------------------------- utilities --- */

.kg-stack {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.kg-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
}

.kg-cluster {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}

.kg-spacer {
    flex: 1 1 auto;
}

/* An image preview that opens the Lightbox: an unstyled button around the thumbnail, announced by
   the zoom cursor. Shared by every generated-image preview (sprites, backgrounds, asset cards). */
.kg-view {
    display: block;
    width: 100%;
    padding: 0;
    border: none;
    background: none;
    cursor: zoom-in;
    border-radius: var(--radius-sm);
}

.kg-view:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Centered content filling what the app header leaves — host message pages (error, not-found).
   Sized by the layout's flex column rather than 100dvh, so it never overflows past the header. */
.kg-fill {
    flex: 1 1 auto;
    min-height: 0;
    display: grid;
    place-items: center;
    padding: var(--space-5);
}

/* Locks background scroll while a modal overlay is open (overlay.js sets the class on <body>).
   The lock lands on the content region — the app's only scroll container (ADR 0025); its reserved
   scrollbar gutter keeps the lock itself from shifting anything. The body element in the selector
   is load-bearing: it out-specifies the region's own scoped overflow-y: auto, which ties otherwise
   and wins on order. */
body.kg-scroll-lock .app-shell__main {
    overflow-y: hidden;
}

body.kg-navigation-modal .app-shell__main {
    overflow: hidden;
}

/* The AI assistant dock (ai-assistant story) is part of the shell, not an overlay: while it is open
   (assistant.js sets the class on <body>) the shell reserves the panel's width so the whole page —
   header, side menu, content, status bar — reflows left of it and stays usable. The width scales
   with the viewport but is bounded; when the room runs out the content region scrolls horizontally
   rather than crushing, held above a usable minimum. The body element out-specifies the scoped
   .app-shell / .ws rules, as with the scroll lock above. */
body.kg-asst-open {
    --kg-asst-width: clamp(20rem, 26vw, 32rem);
}

.app-shell {
    transition: padding-right var(--dur-base) var(--ease);
}

body.kg-asst-open .app-shell {
    padding-right: var(--kg-asst-width);
}

body.kg-asst-open .app-shell__main {
    overflow-x: auto;
}

body.kg-asst-open .ws {
    min-width: 40rem;
}

@media (prefers-reduced-motion: reduce) {
    .app-shell {
        transition: none;
    }
}

/* Shared input chrome — one look for every text-like control (TextField, TextArea, …). */
.kg-input {
    padding-inline: var(--space-3);
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-md);
    font-size: var(--text-base);
    transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}

.kg-input::placeholder {
    color: var(--text-subtle);
}

.kg-input:hover:not(:disabled) {
    border-color: var(--text-subtle);
}

.kg-input:focus-visible {
    border-color: var(--accent);
    box-shadow: var(--focus-ring, 0 0 0 3px color-mix(in srgb, var(--accent) 35%, transparent));
    outline: none;
}

.kg-input:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.kg-input--invalid {
    border-color: var(--danger);
}
