/* ── Self-hosted Cascadia Mono (OFL 1.1, microsoft/cascadia-code v2407.24) ── */
@font-face {
    font-family: "Cascadia Mono";
    src: url("/fonts/cascadia-mono.woff2") format("woff2");
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
}

/* ── Self-hosted Sarasa Term SC (OFL 1.1, be5invis/Sarasa-Gothic v1.0.40) ──
   Subset to the GB2312 repertoire plus Latin, box drawing and fullwidth forms. Rarer
   hanzi fall through to the system CJK font rather than rendering tofu. Only the CJK
   rule below names this family, so other locales never fetch the 1 MB of glyphs.
   "Term" rather than "Mono": its East-Asian-ambiguous characters — the box-drawing
   runs MUSH tables are framed with — are one cell wide, where Mono renders them two
   and shears every framed row.
   font-display: swap is safe despite the size: terminalMetrics.js re-measures the
   character grid on document.fonts.ready, so the terminal refits when this lands. */
@font-face {
    font-family: "Sarasa Term SC";
    src: url("/fonts/sarasa-term-sc-regular.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Sarasa Term SC";
    src: url("/fonts/sarasa-term-sc-bold.woff2") format("woff2");
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

/* ── Self-hosted Hanken Grotesk (OFL 1.1, google/fonts) ──
   The UI face, previously fetched from fonts.googleapis.com. Variable across the whole
   100-900 range, so one file per subset covers every weight the portal asks for. These
   are Google's own subsets and unicode-ranges unchanged, so coverage is identical to
   what the CDN served — latin-ext is what carries ł, ș, č, ő, å and ß for the European
   locales, and only loads when a page actually uses one.
   Note the family has no basic Cyrillic (its "cyrillic-ext" subset is U+0460-052F, not
   the U+0400-045F that Russian and Bulgarian are written in), so ru and bg chrome falls
   through to system-ui. That was equally true of the CDN version. */
@font-face {
    font-family: "Hanken Grotesk";
    src: url("/fonts/hanken-grotesk-latin.woff2") format("woff2");
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
    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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: "Hanken Grotesk";
    src: url("/fonts/hanken-grotesk-latin-ext.woff2") format("woff2");
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ── Theme display faces (fonts/OFL-Themes.txt; Special Elite: fonts/LICENSE-SpecialElite.txt) ──
   Title faces a theme can name (ThemeStyles.DisplayFaces). Latin subsets only, as Google serves them; other
   scripts fall through to the stack's serif or sans. A face is only fetched when a theme in use sets it. */
@font-face {
    font-family: "Cinzel";
    src: url("/fonts/cinzel-latin.woff2") format("woff2");
    font-weight: 400 900;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Cormorant Garamond";
    src: url("/fonts/cormorant-garamond-latin.woff2") format("woff2");
    font-weight: 400 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Cormorant Garamond";
    src: url("/fonts/cormorant-garamond-italic-latin.woff2") format("woff2");
    font-weight: 400 700;
    font-style: italic;
    font-display: swap;
}
@font-face {
    font-family: "Grenze Gotisch";
    src: url("/fonts/grenze-gotisch-latin.woff2") format("woff2");
    font-weight: 400 900;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "IM Fell English";
    src: url("/fonts/im-fell-english-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Marcellus";
    src: url("/fonts/marcellus-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Orbitron";
    src: url("/fonts/orbitron-latin.woff2") format("woff2");
    font-weight: 400 900;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Playfair Display";
    src: url("/fonts/playfair-display-latin.woff2") format("woff2");
    font-weight: 400 900;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Playfair Display";
    src: url("/fonts/playfair-display-italic-latin.woff2") format("woff2");
    font-weight: 400 900;
    font-style: italic;
    font-display: swap;
}
@font-face {
    font-family: "Space Grotesk";
    src: url("/fonts/space-grotesk-latin.woff2") format("woff2");
    font-weight: 300 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Special Elite";
    src: url("/fonts/special-elite-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Fredoka";
    src: url("/fonts/fredoka-latin.woff2") format("woff2");
    font-weight: 300 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Dancing Script";
    src: url("/fonts/dancing-script-latin.woff2") format("woff2");
    font-weight: 400 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Mochiy Pop One";
    src: url("/fonts/mochiy-pop-one-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Patrick Hand";
    src: url("/fonts/patrick-hand-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Dela Gothic One";
    src: url("/fonts/dela-gothic-one-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Graduate";
    src: url("/fonts/graduate-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Pixelify Sans";
    src: url("/fonts/pixelify-sans-latin.woff2") format("woff2");
    font-weight: 400 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Saira Stencil One";
    src: url("/fonts/saira-stencil-one-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Yuji Syuku";
    src: url("/fonts/yuji-syuku-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Bangers";
    src: url("/fonts/bangers-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Lilita One";
    src: url("/fonts/lilita-one-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Titan One";
    src: url("/fonts/titan-one-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Chakra Petch";
    src: url("/fonts/chakra-petch-latin.woff2") format("woff2");
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Monoton";
    src: url("/fonts/monoton-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Michroma";
    src: url("/fonts/michroma-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Antonio";
    src: url("/fonts/antonio-latin.woff2") format("woff2");
    font-weight: 100 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Oxanium";
    src: url("/fonts/oxanium-latin.woff2") format("woff2");
    font-weight: 800;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Russo One";
    src: url("/fonts/russo-one-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Cinzel Decorative";
    src: url("/fonts/cinzel-decorative-latin.woff2") format("woff2");
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Forum";
    src: url("/fonts/forum-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Press Start 2P";
    src: url("/fonts/press-start-2p-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Anton";
    src: url("/fonts/anton-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "DotGothic16";
    src: url("/fonts/dotgothic16-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Alegreya SC";
    src: url("/fonts/alegreya-sc-latin.woff2") format("woff2");
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Oswald";
    src: url("/fonts/oswald-latin.woff2") format("woff2");
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Pirata One";
    src: url("/fonts/pirata-one-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Uncial Antiqua";
    src: url("/fonts/uncial-antiqua-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Barlow Condensed";
    src: url("/fonts/barlow-condensed-latin.woff2") format("woff2");
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Metamorphous";
    src: url("/fonts/metamorphous-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Krona One";
    src: url("/fonts/krona-one-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Saira Condensed";
    src: url("/fonts/saira-condensed-latin.woff2") format("woff2");
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Bodoni Moda";
    src: url("/fonts/bodoni-moda-latin.woff2") format("woff2");
    font-weight: 400 900;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Eagle Lake";
    src: url("/fonts/eagle-lake-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Federant";
    src: url("/fonts/federant-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Rye";
    src: url("/fonts/rye-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Black Ops One";
    src: url("/fonts/black-ops-one-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Jost";
    src: url("/fonts/jost-latin.woff2") format("woff2");
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Big Shoulders Display";
    src: url("/fonts/big-shoulders-display-latin.woff2") format("woff2");
    font-weight: 800;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "EB Garamond";
    src: url("/fonts/eb-garamond-latin.woff2") format("woff2");
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Tektur";
    src: url("/fonts/tektur-latin.woff2") format("woff2");
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Libre Baskerville";
    src: url("/fonts/libre-baskerville-italic-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: italic;
    font-display: swap;
}
@font-face {
    font-family: "Baloo 2";
    src: url("/fonts/baloo-2-latin.woff2") format("woff2");
    font-weight: 800;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Gloock";
    src: url("/fonts/gloock-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Silkscreen";
    src: url("/fonts/silkscreen-latin.woff2") format("woff2");
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Inknut Antiqua";
    src: url("/fonts/inknut-antiqua-latin.woff2") format("woff2");
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Shippori Mincho B1";
    src: url("/fonts/shippori-mincho-b1-latin.woff2") format("woff2");
    font-weight: 800;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Hina Mincho";
    src: url("/fonts/hina-mincho-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Zen Kaku Gothic New";
    src: url("/fonts/zen-kaku-gothic-new-latin.woff2") format("woff2");
    font-weight: 900;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Audiowide";
    src: url("/fonts/audiowide-latin.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: "Jura";
    src: url("/fonts/jura-latin.woff2") format("woff2");
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}

:root {
	/* ── Phosphor design tokens (BuiltInThemes.Phosphor) ── */
	--bg: #121110;
	--surface: #191716;
	--surface-2: #211e1c;
	--surface-3: #161412;
	--text: #efebe5;
	--text-dim: #aaa298;
	--text-faint: #90887e;
	--border: #322d28;
	--border-soft: #272320;
	--accent: #00f5b7;
	--accent-dim: rgb(0,191,143);
	--accent-on: #03150f;
	--glow: 0,245,183;
	--radius: 9px;
	--radius-lg: 14px;
	/* Type scale. Every font-size in the portal is one of these, or relative to its parent (em, %): body text is
	   --text-base, meta text (dates, counts, captions under a title) --text-sm, and --text-xs is kept for badges,
	   kickers and mono labels. rem, so the reader's browser font size scales all of it. SizeTokenTests fails a
	   stylesheet that writes a size of its own. */
	--text-xs: 0.6875rem;    /* 11px */
	--text-sm: 0.8125rem;    /* 13px */
	--text-base: 0.9375rem;  /* 15px */
	--text-md: 1.0625rem;    /* 17px */
	--text-lg: 1.25rem;      /* 20px */
	--text-xl: 1.5rem;       /* 24px */
	--text-2xl: 2rem;        /* 32px */
	--text-3xl: 2.75rem;     /* 44px */
	/* The terminal's base size. terminalMetrics.js measures the character grid from it and fits the columns
	   around it, so it is the terminal's own and not a step of the scale. */
	--text-terminal: 0.84375rem;
	/* Space scale, for padding and gap: a 4px grid with a 2px step for hairline insets. */
	--space-1: 0.125rem;     /* 2px */
	--space-2: 0.25rem;      /* 4px */
	--space-3: 0.5rem;       /* 8px */
	--space-4: 0.75rem;      /* 12px */
	--space-5: 1rem;         /* 16px */
	--space-6: 1.5rem;       /* 24px */
	--space-7: 2rem;         /* 32px */
	--space-8: 3rem;         /* 48px */
	--cpad: var(--space-7);
	--nav-letterspacing: 0.01em;
	/* Documentation only: the mobile breakpoint. CSS media queries can't read a
	   custom property in their condition, so every @media uses the literal 760px —
	   keep them in sync with this value (and with sharpmushLayout.isNarrow in layout.js). */
	--mobile-bp: 760px;
	/* Container padding to use inside mobile (<=760px) media queries — tighter than the
	   desktop --cpad without depending on the density-compact toggle. Pages
	   should prefer var(--cpad-mobile) over a hardcoded 1rem in their @media blocks.
	   Sizing is rem (16px root) so type + spacing honor the user's browser font size;
	   borders, shadows, fixed dimensions, radii, and breakpoints stay px. */
	--cpad-mobile: var(--space-5);
	/* Documentation only: a @container condition cannot read a custom property. */
	--tier-narrow: 48rem;
	--tier-medium: 64rem;
	--tier-roomy: 90rem;
	/* Zero until shell.css raises it while the fixed touch bottom nav is on screen; a scoped
	   stylesheet reads it instead of repeating that media query. */
	--bottomnav-clearance: 0px;
	/* Motion, after Material 3's easing and duration tokens; the spring has the damping of its Expressive
	   default spatial spring (0.8). A rule names what moves and takes one of the --motion-* pairs:
	   --motion-fade for an effect (colour, background, border, opacity, filter, shadow); for a spatial
	   change (transform, position, size) --motion-enter as it arrives, --motion-move as it changes in
	   place, --motion-exit as it leaves, and --motion-spring for a turn or a switch's thumb.
	   Reduced motion zeroes the spatial durations (globals.css) and keeps the effects, which move nothing. */
	--duration-effect: 0.15s;
	--duration-enter: 0.3s;
	--duration-exit: 0.2s;
	--duration-spring: 0.35s;
	--duration-linger: 2s;
	/* One pass of a loading placeholder's sheen (globals.css), which crosses three times; longer than any change of
	   state. Spatial, so reduced motion zeroes it and the placeholder stands still. */
	--duration-sweep: 1.6s;
	--ease-standard: cubic-bezier(0.2, 0, 0, 1);
	--ease-enter: cubic-bezier(0.05, 0.7, 0.1, 1);
	--ease-exit: cubic-bezier(0.3, 0, 0.8, 0.15);
	/* Sampled from the spring until it settles. Its shape depends only on the damping; the duration sets
	   how stiff it is (0.35s is a stiffness of about 600). It starts from rest, so it suits a turn or a
	   thumb, not something arriving, and overshoots by 1.5%, which a panel pinned to an edge would show. */
	--ease-spring: linear(0, 0.008 1.5%, 0.029 3%, 0.061 4.5%, 0.102 6%, 0.148 7.5%, 0.198 9%, 0.433 15.5%, 0.536 18.5%, 0.644 22%, 0.723 25%, 0.791 28%, 0.848 31%, 0.893 34%, 0.934 37.5%, 0.964 41%, 0.988 45%, 1.004 49.5%, 1.012 54.5%, 1.015 63.5%, 1);
	--motion-fade: var(--duration-effect) var(--ease-standard);
	--motion-enter: var(--duration-enter) var(--ease-enter);
	--motion-move: var(--duration-enter) var(--ease-standard);
	--motion-exit: var(--duration-exit) var(--ease-exit);
	--motion-spring: var(--duration-spring) var(--ease-spring);
	--motion-sweep: var(--duration-sweep) var(--ease-standard);
	/* A loading placeholder (globals.css .kit-skeleton): a tint of the text colour, so it reads on every theme, light or
	   dark, and the sheen that crosses it. */
	--skeleton: color-mix(in srgb, var(--text) 9%, transparent);
	--skeleton-sheen: color-mix(in srgb, var(--text) 8%, transparent);
	/* How long a panel opened by hovering stays after the pointer leaves, so a path that grazes its edge does
	   not close it. A wait, not movement, so reduced motion keeps it. */
	--delay-hover-leave: 0.25s;
	/* How long a loading placeholder stays invisible: a read that answers sooner never flashes one (its space is held
	   all the same). A wait, not movement, so reduced motion keeps it. */
	--delay-skeleton: 0.3s;
	--font-ui: 'Hanken Grotesk', system-ui, sans-serif;
	--font-mono: "Cascadia Mono", "DejaVu Sans Mono", monospace;
	--font-display: 'Hanken Grotesk', system-ui, sans-serif;
	/* Kickers: the small capitals over a tile, a panel or a field. In the body face, so a label reads as a label, not code. */
	--font-kicker: var(--font-ui);
	--kicker-tracking: 0.12em;
	/* ── theme parts: the look with every part at its first choice (ThemeStyles.Defaults). The rules in css/themes/ set these per part (data-texture,
	   data-frame-marks, ...); a Custom theme's stylesheet can set any of them. See docs/guides/portal-themes.md. ── */
	--font-title-weight: 700;
	--texture: none;                /* page texture: gradient layers, then drawn layers (masks) in the theme's colours */
	--texture-size: auto;
	--texture-opacity: 1;           /* the texture's strength */
	--no-drawing: linear-gradient(transparent, transparent);
	/* Drawings filled with each colour: an SVG under /themes/drawings, used as a mask. "Nothing drawn" is a clear
	   gradient, since a mask of none would show the colour everywhere. */
	--texture-mask-text: var(--no-drawing);
	--texture-mask-accent: var(--no-drawing);
	--texture-mask-accent-2: var(--no-drawing);
	--texture-mask-accent-3: var(--no-drawing);
	--texture-mask-border: var(--no-drawing);
	--texture-ink-text: var(--text);
	--texture-ink-accent: var(--accent);
	--texture-ink-accent-2: var(--accent-2);
	--texture-ink-accent-3: var(--accent-3);
	--texture-ink-border: var(--border);
	--ornament-before: none;        /* page and banner titles: a glyph either side, and a rule under */
	--ornament-after: none;
	--title-underline: none;
	--title-underline-pad: 0px;
	--title-transform: none;
	--title-tracking: normal;
	--title-tracking-length: 0em;
	--title-style: normal;
	--title-underline-height: 2px;
	--title-color: var(--text);     /* titles' colour and effect (glow, gilt, letterpress...) */
	--title-shadow: none;
	--image-filter: none;           /* the tone pictures take: banners, covers, avatars, wiki pictures */
	--card-marks: none;             /* the frame's gradient layers over a card's surface */
	--card-mask-text: var(--no-drawing); /* the frame's drawings, filled with each colour, as for the texture */
	--card-mask-accent: var(--no-drawing);
	--card-mask-accent-2: var(--no-drawing);
	--card-mask-accent-3: var(--no-drawing);
	--card-mask-border: var(--no-drawing);
	--card-mask-grain: var(--no-drawing); /* set by a paper texture, so cards share the page's grain */
	--card-ink-text: var(--text);
	--card-ink-accent: var(--accent);
	--card-ink-accent-2: var(--accent-2);
	--card-ink-accent-3: var(--accent-3);
	--card-ink-border: var(--border);
	--card-ink-grain: var(--text);
	--card-border-style: solid;
	--card-border-width: 1px;
	--card-shadow: none;
	--hero-marks: var(--no-drawing); /* the frame's layers over the Home hero, which is a card (frames.css "lifted") */
	/* Elevation: a card standing off the page, its top edge catching the light. Dark here; [data-scheme="light"] below. */
	--elev-1: inset 0 1px 0 rgba(255, 240, 220, 0.05), 0 1px 2px rgba(0, 0, 0, 0.5), 0 10px 28px -8px rgba(0, 0, 0, 0.6);
	/* The SharpMUSH mark: its body in the accent, its two inner strokes in this, so it keeps an edge on any surface. */
	--logo-inner: color-mix(in srgb, var(--accent) 70%, var(--text));
	--accent-2: #ff8a8a;            /* decorative colours for drawings only; a theme without them gets --link-missing and --warn */
	--accent-3: #ffb454;
	--accent-hue: 163;              /* the accent's hue in degrees, for picture tones that tint toward it */
	--shadow: 0 1px 0 rgba(255,255,255,0.03) inset, 0 4px 16px rgba(0,0,0,0.4);
	--mud-palette-background-gradient: radial-gradient(120% 100% at 80% -10%, #181615 0%, #121110 55%);
	--mud-palette-navbar-gradient: linear-gradient(90deg, #161412 0%, #11100e 100%);

	/* ── D1 · Commons Dark additions (docs/design/d1/README.md §2) ── */

	/* ── surfaces ── */
	--rail-bg: #0c0b0a;             /* icon rail, darker than --surface-3 (page sidebar) */
	--rail-ink: #aaa298;            /* rail icons: --text-dim, moved until it reads 4.5:1 on --rail-bg */
	--rail-accent: var(--accent);   /* the accent on the rail; a theme moves it until it reads 3:1 on --rail-bg */

	/* ── text roles ── */
	--text-over-image: #e9edf0;     /* primary lines and glass controls over banner images; not themed, as the scrim under them is always dark */
	--text-on-image: #d2d8dd;       /* secondary lines over banner images (with the scrim below) */
	--link-missing: #ff8a8a;        /* wiki redlinks, 1px dashed underline; 7.84:1 on --surface */

	/* ── status ── */
	--warn: #ffb454;                /* "changed" badge, unsaved bar icon; 10.09:1 on --surface */
	--warn-tint: rgba(255, 180, 84, 0.14);
	--unread-alert: #ff8a8a;        /* rail mail badge fill (text uses --bg) */
	--switch-knob-off: #c3cad0;     /* an off switch's knob carries the 3:1 non-text contrast on its --border track */
	/* Status and kind colours; a theme derives its own, readable on its surfaces (ThemeResolver.StatusColors).
	   A tint is color-mix(in srgb, var(--danger) 12%, transparent), never a second hard-coded colour. */
	--danger: #e57373;              /* deletes, denials, errors */
	--success: #6cde9a;             /* allows, results */
	--info: #5aa9ff;                /* notices, pages */
	--special: #b39cff;             /* roles, forms, other marked kinds */

	/* ── tone() (ToneMarkup; shell.css .tone-*) ── */
	--tone-tertiary: #ffb454;       /* the third decorative colour, readable */
	--highlight: #134c3d;           /* behind marked text: the surface tinted with the accent, text still 4.5:1 on it */
	/* hues (ThemeResolver.HueColors), readable on the surfaces, the same in every colour vision */
	--hue-red: #f07178;
	--hue-green: #c3e88d;
	--hue-yellow: #ffcb6b;
	--hue-blue: #82aaff;
	--hue-purple: #c792ea;
	--hue-cyan: #89ddff;
	--hue-orange: #f78c6c;
	--hue-pink: #ff79c6;
	/* ansi() colours in MarkupString's HTML: red to cyan and their bright forms from the hues; behind text, darkened
	   until the text reads on them. Black, white and the greys keep MarkupString's own values. */
	--ms-ansi-1: #f07178;
	--ms-ansi-2: #c3e88d;
	--ms-ansi-3: #ffcb6b;
	--ms-ansi-4: #82aaff;
	--ms-ansi-5: #c792ea;
	--ms-ansi-6: #89ddff;
	--ms-ansi-9: #f4949a;
	--ms-ansi-10: #d2eeaa;
	--ms-ansi-11: #ffd890;
	--ms-ansi-12: #a1bfff;
	--ms-ansi-13: #d5adef;
	--ms-ansi-14: #a6e6ff;
	--ms-ansi-bg-1: #a24f54;
	--ms-ansi-bg-2: #596742;
	--ms-ansi-bg-3: #7d6539;
	--ms-ansi-bg-4: #506593;
	--ms-ansi-bg-5: #7f5e93;
	--ms-ansi-bg-6: #486d7c;
	--ms-ansi-bg-9: #8e595c;
	--ms-ansi-bg-10: #5f694e;
	--ms-ansi-bg-11: #716143;
	--ms-ansi-bg-12: #5a6888;
	--ms-ansi-bg-13: #745f80;
	--ms-ansi-bg-14: #4d6670;

	/* ── code and syntax (ThemeResolver.SyntaxColors): help, the softcode console, highlighted softcode ── */
	--code-bg: #0c0b0a;
	--code-text: #efebe5;
	--syntax-command: #c792ea;      /* $-command patterns */
	--syntax-function: #82aaff;
	--syntax-substitution: #f78c6c; /* %-substitutions */
	--syntax-dbref: #89ddff;
	--syntax-reference: #c3e88d;    /* attribute references */
	--syntax-at-command: #ffcb6b;
	--syntax-danger: #ff5350;
	--syntax-string: #ce9178;       /* help: inline code */
	--syntax-link: #4ec9b0;         /* help: links to other topics */
	--syntax-heading: #9cdcfe;
	--syntax-emphasis: #dcdcaa;
	/* Monaco paints with its own dark theme (mush-monaco.js 'mush-dark') whatever the portal's, so the
	   editor's frame matches that, not the theme. */
	--editor-bg: #1a1a2e;
	/* Mermaid retains its dark SVG palette after portal theme changes; its canvas must match. */
	--mermaid-bg: #1f2020;
	--mermaid-text: #e6e6e6;

	/* ── depth ── */
	--shadow-pop: 0 12px 32px rgba(0, 0, 0, 0.4);  /* menus, popovers, drawers */
	--overlay: rgba(0, 0, 0, 0.55);                /* behind a drawer or dialog */
	--scrim-ink: 10, 11, 13;                       /* rgba(var(--scrim-ink), a): the dark wash under text over images */

	/* ── OOC band (Play story, scene log): Phosphor's; every theme derives its own from its surface and
	   accent (PortalThemes Derive) ── */
	--ooc-band-bg: #172b24;         /* --text on it: 12.57:1 */
	--ooc-band-border: #1c8768;
	--ooc-icon-bg: #1a4d3e;
	--ooc-icon-fg: #efebe5;         /* 8.13:1 on --ooc-icon-bg */

	/* ── frame ── */
	--topbar-h: 60px;               /* the shell topbar; a sticky box inside .phosphor-main subtracts it */
	--rail-w: 72px;
	--side-w: 232px;                /* same as today's expanded sidebar */
	--side-strip-w: 62px;           /* same as today's collapsed sidebar (boards draw 64) */
	--aside-w: 196px;
	--main-pad: 16px 12px 16px 20px;

	/* ── radii ── */
	--radius-card: 16px;            /* cards, banners, bottom bar */
	--radius-row: 10px;             /* sidebar rows, tiles */
	--radius-tile: 10px;
	--radius-portrait: 12px;        /* story portraits, OOC tile (rail items and the minimised banner use the existing --radius-lg, 14px) */

	/* ── glass banner (README §4.3) ── */
	--glass-bg: rgba(14, 15, 17, 0.30);
	--glass-pill-bg: rgba(14, 15, 17, 0.45);
	--glass-filter: blur(16px) saturate(180%);
	--glass-edge: inset 0 1px 0 rgba(255, 255, 255, 0.22), inset 0 0 0 1px rgba(255, 255, 255, 0.08);
	--on-image-shadow: 0 1px 12px rgba(0, 0, 0, 0.55);
	--scrim: linear-gradient(to top, rgba(10, 11, 13, 0.72) 0%, rgba(10, 11, 13, 0.64) 30%, rgba(10, 11, 13, 0.58) 50%, rgba(10, 11, 13, 0.2) 64%, rgba(10, 11, 13, 0) 74%);
	--scrim-open: linear-gradient(to top, rgba(10, 11, 13, 0.8) 0%, rgba(10, 11, 13, 0.68) 40%, rgba(10, 11, 13, 0.58) 72%, rgba(10, 11, 13, 0.2) 84%, rgba(10, 11, 13, 0) 92%);
	--blur-mask-soft: linear-gradient(to top, black 0%, black 35%, transparent 60%);   /* with blur(2px)  */
	--blur-mask-mid: linear-gradient(to top, black 0%, black 20%, transparent 45%);    /* with blur(6px)  */
	--blur-mask-deep: linear-gradient(to top, black 0%, transparent 30%);              /* with blur(12px) */
	--blur-mask-soft-open: linear-gradient(to top, black 0%, black 45%, transparent 70%);
	--blur-mask-mid-open: linear-gradient(to top, black 0%, black 28%, transparent 52%);
	--blur-mask-deep-open: linear-gradient(to top, black 0%, transparent 36%);

	/* ── name mentions (README §4.8): set --name per mention; the viewer's own name uses --accent ── */
	--mention-offset: 3px;
	--mention-alpha: 50%;
}

/* A light theme's elevation: a shallower shadow, warmed toward the paper, under a white top edge. */
[data-scheme="light"] {
	--elev-1: inset 0 1px 0 rgba(255, 255, 255, 0.8), 0 1px 2px rgba(60, 40, 20, 0.06), 0 8px 24px -10px rgba(60, 40, 20, 0.18);
	--logo-inner: color-mix(in srgb, var(--accent) 70%, #ffffff);
}
/* Where relative colour is understood, a lighter step of the accent itself, which keeps its saturation. */
@supports (color: oklch(from red l c h)) {
	[data-scheme="light"] {
		--logo-inner: oklch(from var(--accent) calc(l + 0.14) c h);
	}
}

/* What a theme's parts start from, and what is worked out from its colours: a card's background (the frame's
   gradient layers over the surface), the colours the texture's and frame's drawings are filled with, the kickers'
   face. Set again wherever a theme's attributes are (<html>, or an element previewing another theme), so a preview
   starts from the defaults rather than the worn theme's parts, and its colours are its own. The parts' rules
   (css/themes/) come in a later layer and set what each part changes. */
:root, [data-scheme] {
	--card-bg: var(--card-marks), var(--card-material);
	--font-kicker: var(--font-ui);
	--font-title-weight: 700;
	--texture: none;
	--texture-size: auto;
	--texture-opacity: 1;
	--no-drawing: linear-gradient(transparent, transparent);
	--texture-mask-text: var(--no-drawing);
	--texture-mask-accent: var(--no-drawing);
	--texture-mask-accent-2: var(--no-drawing);
	--texture-mask-accent-3: var(--no-drawing);
	--texture-mask-border: var(--no-drawing);
	--texture-ink-text: var(--text);
	--texture-ink-accent: var(--accent);
	--texture-ink-accent-2: var(--accent-2);
	--texture-ink-accent-3: var(--accent-3);
	--texture-ink-border: var(--border);
	--ornament-before: none;
	--ornament-after: none;
	--title-underline: none;
	--title-underline-pad: 0px;
	--title-transform: none;
	--title-tracking: normal;
	--title-tracking-length: 0em;
	--title-style: normal;
	--title-underline-height: 2px;
	--title-color: var(--text);
	--title-shadow: none;
	--image-filter: none;
	--card-marks: none;
	--card-mask-text: var(--no-drawing);
	--card-mask-accent: var(--no-drawing);
	--card-mask-accent-2: var(--no-drawing);
	--card-mask-accent-3: var(--no-drawing);
	--card-mask-border: var(--no-drawing);
	--card-mask-grain: var(--no-drawing);
	--card-ink-text: var(--text);
	--card-ink-accent: var(--accent);
	--card-ink-accent-2: var(--accent-2);
	--card-ink-accent-3: var(--accent-3);
	--card-ink-border: var(--border);
	--card-ink-grain: var(--text);
	--card-border-style: solid;
	--card-border-width: 1px;
	--card-shadow: none;
	--hero-marks: var(--no-drawing);
	/* What a card is made of (data-material): the fill under its marks, and what it does to the page behind it. */
	--card-material: var(--surface);
	--card-backdrop: none;
	/* How the current line in a menu is marked (data-selection, css/themes/menus.css) is read with fallbacks where it
	   is drawn (shell.css, Kit/SidebarRow.razor.css), so a theme that leaves it standard keeps each menu's own look.
	   Only the loop it plays is declared here, so data-motion can set it. */
	--select-motion: none;
	/* How things arrive and move (data-motion): a card and a menu line as they appear, the page texture's drift, and
	   whether the atmosphere plays. Reduced motion stops all of them (globals.css). */
	--card-enter: none;
	--nav-enter: none;
	--texture-motion: none;
	--ambient-play: running;
	--ambient-flow: initial;
	--ambient-rest: var(--no-drawing);
	/* What hangs between the texture and the page (data-atmosphere): a still layer, a deep one over it, and a moving
	   one with its tile size, place, repeat and loop, each cut to a drawing when its mask is set. */
	--atmosphere-still: none;
	--atmosphere-still-mask: none;
	--atmosphere-deep: none;
	--atmosphere-deep-mask: none;
	--atmosphere-moving: none;
	--atmosphere-moving-mask: none;
	--atmosphere-size: auto;
	--atmosphere-position: 0 0;
	--atmosphere-repeat: repeat;
	--atmosphere-motion: none;
	/* A loop for the still layer (a glow that breathes or wavers), and the lit layer: light shown only where its mask
	   lets it through, as rain catching a sign's colour or a beam lighting the contacts it passes. */
	--atmosphere-still-motion: none;
	--atmosphere-lit: none;
	--atmosphere-lit-size: auto;
	--atmosphere-lit-mask: none;
	--atmosphere-lit-motion: none;
	/* What a texture offers that light (its drawings that catch it, and the point a turning light turns about), and a
	   loop for its drawn layers (data-texture). */
	--texture-lit-mask: linear-gradient(rgba(0, 0, 0, 0.1) 0 0);
	--texture-lit-at: 50% 50%;
	--texture-layer-motion: none;
	/* Light on the page itself (data-highlight): a still edge on each card, and the page title's loop. */
	--card-highlight: none;
	--title-motion: none;
}

/* CJK locales replace the whole mono stack instead of falling back per glyph. Cascadia's
   Latin advance width is not half of any CJK glyph's, so a mixed line drifts out of the
   character grid the terminal measures and reports to the server over NAWS. Sarasa Term
   is drawn to that 1:2 ratio and supplies the Latin too, so the ratio holds across the
   whole line. :lang() is prefix-matching, so zh-Hans and zh-CN both hit the zh rule;
   Program.cs stamps the tag onto <html> at startup. */
:root:lang(zh),
:root:lang(ja),
:root:lang(ko) {
	--font-mono: "Sarasa Term SC", monospace;
}

/* ── Not Authorized — centered, designed panel ── */
.not-authorized {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 60vh;
	padding: var(--cpad);
}
.not-authorized-card {
	max-width: 420px;
	text-align: center;
}
.not-authorized-icon {
	width: 64px;
	height: 64px;
	margin: 0 auto 1.125rem;
	border-radius: 50%;
	display: grid;
	place-items: center;
	background: rgba(var(--glow), 0.08);
	border: 1px solid rgba(var(--glow), 0.2);
	color: var(--accent);
}
.not-authorized-card h1 {
	margin: 0 0 0.5rem;
	font-family: var(--font-display);
	font-size: var(--text-xl);
	font-weight: 600;
	color: var(--text);
}
.not-authorized-card p {
	margin: 0 0 1.25rem;
	font-family: var(--font-ui);
	font-size: var(--text-base);
	color: var(--text-dim);
}
.not-authorized-home {
	display: inline-flex;
	align-items: center;
	gap: var(--space-3);
	padding: var(--space-3) var(--space-5);
	border-radius: var(--radius);
	background: var(--accent);
	color: var(--accent-on);
	text-decoration: none;
	font-family: var(--font-ui);
	font-size: var(--text-sm);
	font-weight: 600;
	transition: filter var(--motion-fade);
}
.not-authorized-home:hover {
	filter: brightness(1.08);
}

/* ── Section kicker (uppercase labels in --font-kicker — stat tiles, panel headers, meta fields) ── */
.section-kicker {
	font-family: var(--font-kicker);
	font-size: var(--text-xs);
	letter-spacing: var(--kicker-tracking);
	text-transform: uppercase;
	color: var(--text-faint);
}

/* ── Density compact toggle ── */
.density-compact {
	--cpad: var(--space-5);
}

/* Prevent mobile browsers (notably Chrome on Android) from auto-inflating
   text — "font boosting" overrides explicit small font-sizes on wide text
   blocks, which breaks fixed-width terminal layout and any fit-to-width sizing. */
html, body {
	-webkit-text-size-adjust: 100%;
	text-size-adjust: 100%;
}

body {
	background-image: var(--mud-palette-background-gradient);
	background-size: 200% 200%;
}
