/* ── CSS Reset ─────────────────────────────────────────────────────────── */

a,
abbr,
acronym,
address,
applet,
big,
blockquote,
body,
caption,
cite,
code,
dd,
del,
dfn,
div,
dl,
dt,
em,
fieldset,
form,
h1,
h2,
h3,
h4,
h5,
h6,
html,
iframe,
img,
ins,
kbd,
label,
legend,
li,
object,
ol,
p,
pre,
q,
s,
samp,
small,
span,
strike,
strong,
table,
tbody,
td,
tfoot,
th,
thead,
tr,
tt,
ul,
var {
	border: 0;
	font-family: inherit;
	font-size: 100%;
	font-style: inherit;
	font-weight: inherit;
	margin: 0;
	padding: 0;
	vertical-align: baseline;
}

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

html,
body,
#root {
	height: 100%;
	width: 100%;
}

/* Frameless Electron: reserve 32px at the top for the TitleBar.
   The class is flipped on/off at runtime by TitleBar.tsx so web
   and Android builds don't reserve any space. We pad #root (not
   body) so children that use `height: 100vh` start below the bar;
   the bottom 32px of such children will overflow the viewport but
   most top-level layouts use `height: 100%` which fits cleanly. */
body.has-window-controls #root {
	padding-top: 32px;
}

/* ── IBM Plex (self-hosted) ──────────────────────────────────────
   WOFF2 files live under `packages/shared/src/assets/font/` and
   are emitted to `dist/assets/` by Vite's asset pipeline on build.
   Using `font-display: swap` so text paints immediately in the
   system fallback, then reflows once Plex finishes downloading —
   standard first-paint tradeoff for self-hosted webfonts.

   Only Latin glyphs are covered. Add a `unicode-range` descriptor
   here if we ever need to load extra scripts. */
@font-face {
	font-family: 'IBM Plex Sans';
	src: url('./assets/font/IBMPlexSans-Regular.woff2') format('woff2');
	font-weight: 400;
	font-style: normal;
	font-display: swap;
}
@font-face {
	font-family: 'IBM Plex Sans';
	src: url('./assets/font/IBMPlexSans-Italic.woff2') format('woff2');
	font-weight: 400;
	font-style: italic;
	font-display: swap;
}
@font-face {
	font-family: 'IBM Plex Sans';
	src: url('./assets/font/IBMPlexSans-Medium.woff2') format('woff2');
	font-weight: 500;
	font-style: normal;
	font-display: swap;
}
@font-face {
	font-family: 'IBM Plex Sans';
	src: url('./assets/font/IBMPlexSans-MediumItalic.woff2') format('woff2');
	font-weight: 500;
	font-style: italic;
	font-display: swap;
}
@font-face {
	font-family: 'IBM Plex Sans';
	src: url('./assets/font/IBMPlexSans-SemiBold.woff2') format('woff2');
	font-weight: 600;
	font-style: normal;
	font-display: swap;
}
@font-face {
	font-family: 'IBM Plex Sans';
	src: url('./assets/font/IBMPlexSans-SemiBoldItalic.woff2') format('woff2');
	font-weight: 600;
	font-style: italic;
	font-display: swap;
}
@font-face {
	font-family: 'IBM Plex Sans';
	src: url('./assets/font/IBMPlexSans-Bold.woff2') format('woff2');
	font-weight: 700;
	font-style: normal;
	font-display: swap;
}
@font-face {
	font-family: 'IBM Plex Sans';
	src: url('./assets/font/IBMPlexSans-BoldItalic.woff2') format('woff2');
	font-weight: 700;
	font-style: italic;
	font-display: swap;
}
@font-face {
	font-family: 'IBM Plex Mono';
	src: url('./assets/font/IBMPlexMono-Regular.woff2') format('woff2');
	font-weight: 400;
	font-style: normal;
	font-display: swap;
}
@font-face {
	font-family: 'IBM Plex Mono';
	src: url('./assets/font/IBMPlexMono-Italic.woff2') format('woff2');
	font-weight: 400;
	font-style: italic;
	font-display: swap;
}
@font-face {
	font-family: 'IBM Plex Mono';
	src: url('./assets/font/IBMPlexMono-Medium.woff2') format('woff2');
	font-weight: 500;
	font-style: normal;
	font-display: swap;
}

/* ── Design Tokens ────────────────────────────────────────────────────── */

:root {
	--saturation-factor: 1;
	--user-select: auto;

	/* ── Voice / video stage tokens ─────────────────────────────── */
	--voice-surface-0: var(--background-primary);
	--voice-surface-1: var(--background-secondary);
	--voice-surface-2: var(--background-secondary-alt, var(--background-secondary));
	--voice-surface-3: var(--background-tertiary);
	--voice-surface-4: var(--background-header-secondary, var(--background-tertiary));
	--voice-surface-5: var(--background-header-primary-hover, var(--background-modifier-hover));

	--voice-overlay-base: color-mix(in srgb, black 72%, var(--background-primary));
	--voice-overlay-strong: color-mix(in srgb, var(--voice-overlay-base) 78%, transparent);
	--voice-overlay: color-mix(in srgb, var(--voice-overlay-base) 62%, transparent);
	--voice-overlay-soft: color-mix(in srgb, var(--voice-overlay-base) 46%, transparent);
	--voice-overlay-subtle: color-mix(in srgb, var(--voice-overlay-base) 32%, transparent);
	--voice-overlay-light: color-mix(in srgb, var(--text-primary) 12%, transparent);
	--voice-overlay-light-strong: color-mix(in srgb, var(--text-primary) 20%, transparent);
	--voice-overlay-light-bold: color-mix(in srgb, var(--text-primary) 48%, transparent);

	--voice-text-strong: var(--text-primary);
	--voice-text-muted: var(--text-secondary);
	--voice-text-subtle: var(--text-tertiary);

	--voice-status-success: var(--status-online, #23a55a);
	--voice-status-success-bg-solid: color-mix(in srgb, var(--voice-status-success) 20%, var(--voice-surface-2));

	--voice-status-warning: var(--status-warning, #f0b232);
	--voice-status-warning-alt: var(--status-idle, #f0b232);

	--voice-status-danger: var(--status-danger, #f23f43);
	--voice-status-danger-bg-solid: color-mix(in srgb, var(--voice-status-danger) 20%, var(--voice-surface-2));
	--voice-status-danger-bg-strong-solid: color-mix(in srgb, var(--voice-status-danger) 30%, var(--voice-surface-2));

	--voice-shadow-base: color-mix(in srgb, var(--background-primary) 12%, black);
	--voice-shadow-strong: color-mix(in srgb, var(--voice-shadow-base) 40%, transparent);
	--voice-shadow-medium: color-mix(in srgb, var(--voice-shadow-base) 30%, transparent);
	--voice-shadow-soft: color-mix(in srgb, var(--voice-shadow-base) 20%, transparent);

	--voice-header-gradient: linear-gradient(
		to bottom,
		var(--voice-overlay-strong) 0%,
		var(--voice-overlay) 46%,
		transparent 100%
	);
	--voice-footer-gradient: linear-gradient(
		to top,
		var(--voice-overlay-strong) 0%,
		var(--voice-overlay-soft) 46%,
		transparent 100%
	);

	/* Z-index layers */
	--z-index-base: 0;
	--z-index-elevated-1: 10;
	--z-index-elevated-2: 20;
	--z-index-elevated-3: 30;
	--z-index-modal: 10000;
	--z-index-popout: 15000;
	--z-index-modal-swap: 25000;
	--z-index-popout-above-swap: 30000;
	--z-index-overlay: 40000;
	--z-index-tooltip: 45000;
	--z-index-toast: 50000;
	--z-index-titlebar: 100000;
	--z-index-contextmenu: 2147483647;
	--native-titlebar-height: 32px;

	/* Border radii */
	--radius-sm: 0.25rem;
	--radius-md: 0.375rem;
	--radius-lg: 0.5rem;
	--radius-xl: 0.75rem;
	--radius-2xl: 1rem;
	--radius-full: 9999px;
	--media-border-radius: 4px;

	/* Spacing scale */
	--spacing-0: 0;
	--spacing-1: 0.25rem;
	--spacing-1-5: 0.375rem;
	--spacing-2: 0.5rem;
	--spacing-3: 0.75rem;
	--spacing-4: 1rem;
	--spacing-5: 1.25rem;
	--spacing-6: 1.5rem;
	--spacing-8: 2rem;
	--spacing-10: 2.5rem;
	--spacing-12: 3rem;
	--spacing-16: 4rem;
	--spacing-20: 5rem;
	--spacing-24: 6rem;

	/* Layout dimensions */
	--layout-guild-list-width: 4.5rem;
	--layout-sidebar-width: 16.875rem;
	--layout-header-height: 3.5rem;
	--layout-user-area-height: var(--input-container-min-height);
	--layout-user-area-reserved-height: 0px;
	--layout-mobile-bottom-nav-reserved-height: 0px;
	--layout-member-list-width: 265px;
	--guild-icon-size: 44px;
	--guild-icon-gap: var(--spacing-2);
	--mobile-bottom-nav-height: 60px;

	--layout-gap: var(--spacing-4);
	--layout-gap-sm: var(--spacing-2);
	--layout-gap-lg: var(--spacing-6);

	--content-padding: var(--spacing-4);
	--content-padding-sm: var(--spacing-3);
	--content-padding-lg: var(--spacing-6);
	--layout-header-popout-width: calc(var(--layout-sidebar-width) - (var(--spacing-4) * 2));

	/* Input / textarea */
	--input-height: 40px;
	--input-container-padding: 0.625rem;
	--footer-row-height: 72px;
	--input-container-min-height: var(--footer-row-height);
	--input-wrapper-padding-x: 0.5rem;
	--input-wrapper-padding-bottom: 0.5rem;
	--textarea-top-bar-height: 40px;
	--textarea-line-height: 1.375rem;
	--textarea-content-offset: calc((var(--user-area-content-height) - var(--textarea-line-height)) / 2);

	/* Typing indicator */
	--typing-indicator-height: 16px;
	--typing-pill-height: 20px;
	--slowmode-indicator-height: var(--typing-pill-height);
	--scroller-spacer-height: 28px;
	--typing-avatar-size: 12px;
	--typing-indicator-animation-size: 20px;
	--typing-indicator-gap: 0px;
	--typing-upload-column-width: calc(
		var(--user-area-content-height) +
		(var(--textarea-side-button-padding, 0.34375rem) * 2)
	);

	/* User area */
	--user-area-content-height: 36px;
	--user-area-padding-y: calc((var(--layout-user-area-height) - var(--user-area-content-height)) / 2);
	--user-area-padding-x: var(--spacing-4);
	--voice-connection-padding-y: var(--spacing-2);
	--footer-row-padding-y: var(--user-area-padding-y);

	/* Message layout */
	--message-avatar-size: 40px;
	--message-gutter: 16px;
	--message-line-height: 1.375rem;

	/* Spoiler */
	--spoiler-border-radius: 6px;

	/* Typography */
	--font-sans: 'IBM Plex Sans', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
	--font-mono: 'IBM Plex Mono', 'Consolas', 'Andale Mono WT', 'Andale Mono', 'Lucida Console', 'Lucida Sans Typewriter', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Liberation Mono', 'Nimbus Mono L', Monaco, 'Courier New', Courier, monospace;
	--font-emoji: 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji', var(--font-sans, system-ui), sans-serif;
	--font-size-xs: 0.75rem;
	--font-size-sm: 0.8125rem;
	--font-size-md: 0.875rem;
	--font-size-lg: 1rem;
	--font-size-xl: 1.25rem;
	--font-size-2xl: 1.5rem;

	/* Emoji */
	--custom-emoji-size-emoji: 1.375em;
	--custom-emoji-size-jumbo-emoji: 3rem;
	--emoji-size: var(--custom-emoji-size-emoji);
	--emoji-jumbo-size: var(--custom-emoji-size-jumbo-emoji);

	/* Focus */
	--focus-primary: #00b0f4;
}

/* ── Dark Theme (default) ─────────────────────────────────────────────── */

:root,
[data-theme='dark'] {
	/* Backgrounds — HSL with saturation factor (neutralDark: hue=220, sat=13%) */
	--background-primary: hsl(220, calc(13% * var(--saturation-factor)), 5%);
	--background-secondary: hsl(220, calc(13% * var(--saturation-factor)), 11.18%);
	--background-secondary-lighter: hsl(220, calc(13% * var(--saturation-factor)), 13.22%);
	--background-secondary-alt: hsl(220, calc(13% * var(--saturation-factor)), 15.08%);
	--background-tertiary: hsl(220, calc(13% * var(--saturation-factor)), 17.78%);
	--background-channel-header: hsl(220, calc(13% * var(--saturation-factor)), 16.46%);
	--background-floating: hsl(220, calc(13% * var(--saturation-factor)), 3%);
	--background-textarea: hsl(220, calc(13% * var(--saturation-factor)), 21.78%);
	--background-header-secondary: hsl(220, calc(13% * var(--saturation-factor)), 20.75%);
	--background-header-primary: hsl(220, calc(13% * var(--saturation-factor)), 19.5%);
	--background-accent: hsl(220, calc(13% * var(--saturation-factor)), 40%);

	--background-modifier-hover: hsla(220, calc(13% * var(--saturation-factor)), 100%, 0.05);
	--background-modifier-active: hsla(220, calc(13% * var(--saturation-factor)), 100%, 0.08);
	--background-modifier-selected: hsla(220, calc(13% * var(--saturation-factor)), 100%, 0.1);
	--background-modifier-accent: hsla(220, calc(13% * var(--saturation-factor)), 80%, 0.15);
	--background-modifier-accent-focus: hsla(220, calc(13% * var(--saturation-factor)), 80%, 0.22);

	/* Code blocks */
	--bg-code: hsla(220, calc(13% * var(--saturation-factor)), 15%, 0.8);
	--bg-code-block: var(--background-secondary-alt);

	/* Text — HSL (neutralDark hue=220, sat=13%, darkText range [52, 96]) */
	--text-primary: hsl(220, calc(13% * var(--saturation-factor)), 96%);
	--text-chat: hsl(220, calc(13% * var(--saturation-factor)), 90.56%);
	--text-secondary: hsl(220, calc(13% * var(--saturation-factor)), 83.68%);
	--text-primary-muted: hsl(220, calc(13% * var(--saturation-factor)), 76.2%);
	--text-tertiary: hsl(220, calc(13% * var(--saturation-factor)), 68.72%);
	--text-tertiary-secondary: hsl(220, calc(13% * var(--saturation-factor)), 52%);
	--text-tertiary-muted: hsl(220, calc(13% * var(--saturation-factor)), 60.8%);
	--text-muted: var(--text-tertiary-muted);

	/* Brand */
	--brand-primary: hsl(242, calc(70% * var(--saturation-factor)), 55%);
	--brand-secondary: hsl(242, calc(60% * var(--saturation-factor)), 49%);
	--brand-primary-light: hsl(242, calc(100% * var(--saturation-factor)), 84%);
	--brand-primary-fill: hsl(0, 0%, 100%);
	--brand-primary-hover: var(--brand-secondary);
	--brand-primary-active: hsl(242, calc(60% * var(--saturation-factor)), 42%);

	/* Links */
	--text-link: hsl(210, calc(100% * var(--saturation-factor)), 70%);
	--text-on-brand-primary: hsl(0, 0%, 98%);

	/* Status */
	--status-online: hsl(142, calc(76% * var(--saturation-factor)), 40%);
	--status-idle: hsl(45, calc(93% * var(--saturation-factor)), 50%);
	--status-dnd: hsl(0, calc(84% * var(--saturation-factor)), 60%);
	--status-offline: hsl(218, calc(11% * var(--saturation-factor)), 65%);
	--status-danger: hsl(1, calc(77% * var(--saturation-factor)), 55%);
	--status-warning: var(--status-idle);
	--status-success: var(--status-online);
	--accent-success: var(--status-online);

	/* Interactive */
	--interactive-normal: var(--text-secondary);
	--interactive-hover: var(--text-primary);
	--interactive-active: color-mix(in oklab, hsl(0, 0%, 100%) 100%, hsl(245, calc(100% * var(--saturation-factor)), 80%) 40%);
	--interactive-muted: color-mix(in oklab, hsl(228, calc(10% * var(--saturation-factor)), 35%) 100%, hsl(245, calc(100% * var(--saturation-factor)), 80%) 40%);

	/* Buttons */
	--button-secondary-fill: hsla(0, 0%, 100%, 0.1);
	--button-secondary-active-fill: hsla(0, 0%, 100%, 0.15);
	--button-secondary-text: hsl(0, 0%, 100%);
	--button-secondary-active-text: var(--button-secondary-text);
	--button-ghost-text: hsl(0, 0%, 100%);
	--button-danger-fill: hsl(359, calc(70% * var(--saturation-factor)), 54%);
	--button-danger-text: hsl(0, 0%, 100%);
	--button-danger-active-fill: hsl(359, calc(65% * var(--saturation-factor)), 45%);
	--button-danger-outline-text: hsl(0, 0%, 100%);
	--button-inverted-fill: hsl(0, 0%, 100%);
	--button-inverted-text: hsl(0, 0%, 0%);

	/* Control buttons */
	--control-button-normal-text: var(--text-primary-muted);
	--control-button-hover-bg: hsl(220, calc(13% * var(--saturation-factor)), 22%);
	--control-button-hover-text: var(--text-primary);
	--control-button-danger-text: hsl(1, calc(77% * var(--saturation-factor)), 60%);

	/* Channel */
	--channel-icon: var(--text-tertiary-muted);

	/* Surfaces */
	--form-surface-background: var(--background-tertiary);
	--surface-interactive-hover-bg: var(--background-modifier-hover);
	--surface-interactive-selected-bg: var(--background-modifier-selected);
	--surface-interactive-selected-color: var(--text-primary);

	/* Scrollbar — matches Fluxer's dark-theme palette so the chat
	   scroller (and any other `.scroller`-styled element) reads the
	   same as Fluxer. The thumb is a muted mix of the textarea
	   surface and the tertiary text colour; hover bumps the mix
	   toward text-secondary for a subtle hi-light. */
	--scrollbar-thumb-bg: color-mix(in srgb, var(--background-textarea) 35%, var(--text-tertiary) 65%);
	--scrollbar-thumb-bg-hover: color-mix(in srgb, var(--background-textarea) 25%, var(--text-secondary) 75%);
	--scrollbar-track-bg: color-mix(in srgb, var(--background-secondary) 80%, transparent);

	/* Panel controls (UserArea, voice panels) */
	--panel-control-bg: color-mix(
		in srgb,
		var(--background-secondary-alt) 80%,
		hsl(220, calc(13% * var(--saturation-factor)), 2%) 20%
	);
	--panel-control-border: hsla(220, calc(30% * var(--saturation-factor)), 65%, 0.45);
	--panel-control-divider: hsla(220, calc(30% * var(--saturation-factor)), 55%, 0.35);
	--panel-control-highlight: hsla(0, 0%, 100%, 0.04);

	/* Guild list */
	--guild-list-foreground: hsl(220, calc(13% * var(--saturation-factor)), 19.5%);

	/* User area */
	--user-area-divider-color: color-mix(in srgb, var(--background-modifier-hover) 70%, transparent);

	/* Shadows */
	--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.1);
	--shadow-md: 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.1);
	--shadow-lg: 0 4px 8px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(0, 0, 0, 0.1);

	/* Transitions */
	--transition-fast: 100ms ease;
	--transition-normal: 200ms ease;
	--transition-slow: 300ms ease;

	/* Border */
	--border-color: hsla(220, calc(13% * var(--saturation-factor)), 50%, 0.2);

	color-scheme: dark;
}

/* ── Light Theme ──────────────────────────────────────────────────────── */

[data-theme='light'] {
	/* Backgrounds — HSL with saturation factor (neutralLight: hue=220, sat=10%) */
	/* lightSurface scale: easeIn curve, range [86, 98.5] */
	--background-primary: hsl(220, calc(10% * var(--saturation-factor)), 98.5%);
	--background-secondary: hsl(220, calc(10% * var(--saturation-factor)), 92.85%);
	--background-secondary-lighter: hsl(220, calc(10% * var(--saturation-factor)), 94.61%);
	--background-secondary-alt: hsl(220, calc(10% * var(--saturation-factor)), 90.96%);
	--background-tertiary: hsl(220, calc(10% * var(--saturation-factor)), 88.21%);
	--background-channel-header: hsl(220, calc(10% * var(--saturation-factor)), 89.13%);
	--background-floating: hsl(220, calc(10% * var(--saturation-factor)), 98.5%);
	--background-accent: hsl(220, calc(10% * var(--saturation-factor)), 88.21%);
	--background-textarea: hsl(220, calc(10% * var(--saturation-factor)), 95.68%);
	--background-header-secondary: hsl(220, calc(10% * var(--saturation-factor)), 86.5%);
	--background-header-primary: hsl(220, calc(10% * var(--saturation-factor)), 86.18%);
	--background-header-primary-hover: hsl(220, calc(10% * var(--saturation-factor)), 86%);
	--guild-list-foreground: hsl(220, calc(10% * var(--saturation-factor)), 87.53%);

	/* Modifiers — light theme uses dark base with alpha */
	--background-modifier-hover: hsla(220, calc(10% * var(--saturation-factor)), 10%, 0.05);
	--background-modifier-active: hsla(220, calc(10% * var(--saturation-factor)), 10%, 0.08);
	--background-modifier-selected: hsla(220, calc(10% * var(--saturation-factor)), 10%, 0.1);
	--background-modifier-accent: hsla(220, calc(10% * var(--saturation-factor)), 40%, 0.22);
	--background-modifier-accent-focus: hsla(220, calc(10% * var(--saturation-factor)), 40%, 0.32);

	/* Code */
	--bg-code: hsla(220, calc(22% * var(--saturation-factor)), 90%, 0.9);
	--bg-code-block: var(--background-primary);

	/* Text — HSL (neutralLight hue=220, sat=10%, lightText range [15, 60]) */
	--text-primary: hsl(220, calc(10% * var(--saturation-factor)), 15%);
	--text-chat: hsl(220, calc(10% * var(--saturation-factor)), 21.91%);
	--text-secondary: hsl(220, calc(10% * var(--saturation-factor)), 36.67%);
	--text-primary-muted: hsl(220, calc(10% * var(--saturation-factor)), 46.39%);
	--text-tertiary: hsl(220, calc(10% * var(--saturation-factor)), 52.8%);
	--text-tertiary-secondary: hsl(220, calc(10% * var(--saturation-factor)), 57.19%);
	--text-tertiary-muted: hsl(220, calc(10% * var(--saturation-factor)), 58.99%);
	--text-muted: var(--text-tertiary-muted);
	--text-link: hsl(210, 100%, 45%);
	--text-code: hsl(340, 50%, 45%);

	/* Brand */
	--brand-primary: hsl(242, calc(70% * var(--saturation-factor)), 55%);
	--brand-secondary: hsl(242, calc(60% * var(--saturation-factor)), 49%);
	--brand-primary-hover: var(--brand-secondary);
	--brand-primary-active: hsl(242, calc(60% * var(--saturation-factor)), 42%);
	--brand-primary-fill: hsl(0, 0%, 100%);
	--text-on-brand-primary: hsl(0, 0%, 98%);

	/* Status */
	--status-online: hsl(142, calc(70% * var(--saturation-factor)), 40%);
	--status-idle: hsl(45, calc(90% * var(--saturation-factor)), 45%);
	--status-dnd: hsl(359, calc(70% * var(--saturation-factor)), 50%);
	--status-offline: hsl(210, calc(10% * var(--saturation-factor)), 55%);
	--status-danger: hsl(359, calc(70% * var(--saturation-factor)), 50%);
	--status-warning: var(--status-idle);
	--status-success: var(--status-online);
	--accent-success: var(--status-online);

	/* Buttons */
	--button-secondary-fill: hsla(220, calc(10% * var(--saturation-factor)), 10%, 0.1);
	--button-secondary-active-fill: hsla(220, calc(10% * var(--saturation-factor)), 10%, 0.15);
	--button-secondary-text: hsl(220, calc(10% * var(--saturation-factor)), 15%);
	--button-secondary-active-text: hsl(220, calc(10% * var(--saturation-factor)), 10%);
	--button-ghost-text: hsl(220, calc(10% * var(--saturation-factor)), 20%);
	--button-inverted-fill: hsl(0, 0%, 100%);
	--button-inverted-text: hsl(0, 0%, 10%);
	--button-danger-fill: hsl(359, calc(70% * var(--saturation-factor)), 54%);
	--button-danger-text: hsl(0, 0%, 100%);
	--button-danger-active-fill: hsl(359, calc(65% * var(--saturation-factor)), 45%);
	--button-danger-outline-text: hsl(359, calc(70% * var(--saturation-factor)), 45%);

	/* Control buttons */
	--control-button-normal-bg: transparent;
	--control-button-normal-text: hsl(220, calc(10% * var(--saturation-factor)), 50%);
	--control-button-hover-bg: hsl(220, calc(10% * var(--saturation-factor)), 88%);
	--control-button-hover-text: hsl(220, calc(10% * var(--saturation-factor)), 20%);
	--control-button-active-bg: hsl(220, calc(10% * var(--saturation-factor)), 85%);
	--control-button-active-text: hsl(220, calc(10% * var(--saturation-factor)), 15%);
	--control-button-danger-text: hsl(359, calc(70% * var(--saturation-factor)), 50%);
	--control-button-danger-hover-bg: hsl(359, calc(70% * var(--saturation-factor)), 95%);

	/* Panel controls */
	--panel-control-bg: color-mix(in srgb, var(--background-secondary) 65%, hsl(0, 0%, 100%) 35%);
	--panel-control-border: hsla(220, calc(25% * var(--saturation-factor)), 45%, 0.25);
	--panel-control-divider: hsla(220, calc(30% * var(--saturation-factor)), 35%, 0.2);
	--panel-control-highlight: hsla(0, 0%, 100%, 0.65);

	/* Guild list */
	--guild-list-foreground: hsl(220, calc(10% * var(--saturation-factor)), 87.53%);

	/* Surfaces */
	--form-surface-background: var(--background-primary);
	--surface-interactive-hover-bg: var(--background-modifier-hover);
	--surface-interactive-selected-bg: var(--background-modifier-selected);
	--surface-interactive-selected-color: var(--text-primary);

	/* Scrollbar */
	--scrollbar-thumb-bg: color-mix(in srgb, var(--background-header-secondary) 40%, var(--text-secondary) 60%);
	--scrollbar-thumb-bg-hover: color-mix(in srgb, var(--background-header-secondary) 30%, var(--text-primary) 70%);
	--scrollbar-track-bg: color-mix(in srgb, var(--background-secondary) 50%, transparent);

	/* Border */
	--border-color: hsla(220, calc(10% * var(--saturation-factor)), 40%, 0.15);
	--border-color-hover: hsla(220, calc(10% * var(--saturation-factor)), 40%, 0.25);
	--border-color-focus: hsla(210, calc(90% * var(--saturation-factor)), 50%, 0.4);

	/* User area */
	--user-area-divider-color: hsla(220, calc(10% * var(--saturation-factor)), 40%, 0.2);

	/* Syntax highlighting (light theme) */
	--hljs-light-text: #24292e;
	--hljs-light-keyword: #d73a49;
	--hljs-light-entity: #6f42c1;
	--hljs-light-constant: #005cc5;
	--hljs-light-string: #032f62;
	--hljs-light-variable: #e36209;
	--hljs-light-comment: #6a737d;
	--hljs-light-tag: #22863a;
	--hljs-light-list: #735c0f;
	--hljs-light-addition: #22863a;
	--hljs-light-addition-bg: #f0fff4;
	--hljs-light-deletion: #b31d28;
	--hljs-light-deletion-bg: #ffeef0;

	color-scheme: light;
}

/* ── macOS native titlebar adjustment ─────────────────────────────────── */

html.platform-native.platform-macos {
	--layout-guild-list-width: 4.75rem;
}

/* ── Base Styles ──────────────────────────────────────────────────────── */

html {
	background-color: var(--background-secondary);
	color: var(--text-primary);
	overflow: hidden;
	overscroll-behavior: none;
	user-select: var(--user-select);
	-webkit-user-select: var(--user-select);
	font-family: var(--font-sans);
	font-size: 16px;
	line-height: 1.5;
	font-optical-sizing: auto;
}

html,
body {
	touch-action: pan-y;
}

body {
	font-family: var(--font-sans), var(--font-emoji);
	font-size: var(--font-size-lg);
	line-height: 1.375;
	color: var(--text-primary);
	background-color: var(--background-tertiary);
	scrollbar-color: var(--scrollbar-thumb-bg) var(--scrollbar-track-bg);
	user-select: var(--user-select);
	overflow: hidden;
	margin: 0;
	padding: 0;
}

button,
input,
select,
textarea,
a {
	touch-action: manipulation;
	outline: none;
}

[role='button'],
[tabindex] {
	outline: none;
}

input,
textarea,
select,
button {
	font-family: inherit;
	font-size: inherit;
}

input {
	color-scheme: dark;
}

[data-theme='light'] input {
	color-scheme: light;
}

b,
strong {
	font-weight: 600;
}

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

@media (hover: hover) {
	a:hover {
		color: var(--text-link);
		text-decoration: underline;
	}
}

@media (hover: none) {
	a,
	a:hover,
	a:active {
		text-decoration: none !important;
	}
}

code {
	font-family: var(--font-mono);
	font-size: 0.9em;
	line-height: 1.5;
	padding: 0.2em 0.4em;
	border-radius: var(--radius-sm);
	background-color: var(--bg-code);
}

pre {
	padding: var(--pre-padding, 1em);
	overflow: auto;
	border-radius: var(--radius-md);
	background-color: var(--bg-code-block);
}

pre code {
	padding: 0;
	background-color: transparent;
}

blockquote {
	margin: 1em 0;
	padding: 0;
	border: none;
	background-color: transparent;
}

table {
	border-collapse: collapse;
	margin: 1em 0;
}

table th {
	text-align: left;
	font-weight: bold;
}

table td {
	padding: 0.5em;
}

img[alt] {
	text-indent: -9999px;
}

/* ── Scrollbar (WebKit) ───────────────────────────────────────────────── */

::-webkit-scrollbar {
	width: 8px;
	height: 8px;
}

::-webkit-scrollbar-track {
	background: var(--scrollbar-track-bg);
	border-radius: 4px;
}

::-webkit-scrollbar-thumb {
	background: var(--scrollbar-thumb-bg);
	border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
	background: var(--scrollbar-thumb-bg-hover);
}

/* ── Syntax Highlighting (light theme) ────────────────────────────────── */

[data-theme='light'] .hljs {
	color: var(--hljs-light-text);
	background: transparent;
}

[data-theme='light'] .hljs-doctag,
[data-theme='light'] .hljs-keyword,
[data-theme='light'] .hljs-meta .hljs-keyword,
[data-theme='light'] .hljs-template-tag,
[data-theme='light'] .hljs-template-variable,
[data-theme='light'] .hljs-type,
[data-theme='light'] .hljs-variable.language_ {
	color: var(--hljs-light-keyword);
}

[data-theme='light'] .hljs-title,
[data-theme='light'] .hljs-title.class_,
[data-theme='light'] .hljs-title.class_.inherited__,
[data-theme='light'] .hljs-title.function_ {
	color: var(--hljs-light-entity);
}

[data-theme='light'] .hljs-attr,
[data-theme='light'] .hljs-attribute,
[data-theme='light'] .hljs-literal,
[data-theme='light'] .hljs-meta,
[data-theme='light'] .hljs-number,
[data-theme='light'] .hljs-operator,
[data-theme='light'] .hljs-variable,
[data-theme='light'] .hljs-selector-attr,
[data-theme='light'] .hljs-selector-class,
[data-theme='light'] .hljs-selector-id {
	color: var(--hljs-light-constant);
}

[data-theme='light'] .hljs-regexp,
[data-theme='light'] .hljs-string,
[data-theme='light'] .hljs-meta .hljs-string {
	color: var(--hljs-light-string);
}

[data-theme='light'] .hljs-built_in,
[data-theme='light'] .hljs-symbol {
	color: var(--hljs-light-variable);
}

[data-theme='light'] .hljs-comment,
[data-theme='light'] .hljs-code,
[data-theme='light'] .hljs-formula {
	color: var(--hljs-light-comment);
}

[data-theme='light'] .hljs-name,
[data-theme='light'] .hljs-quote,
[data-theme='light'] .hljs-selector-tag,
[data-theme='light'] .hljs-selector-pseudo {
	color: var(--hljs-light-tag);
}

[data-theme='light'] .hljs-subst,
[data-theme='light'] .hljs-emphasis,
[data-theme='light'] .hljs-strong {
	color: var(--hljs-light-text);
}

[data-theme='light'] .hljs-section {
	color: var(--hljs-light-constant);
	font-weight: 600;
}

[data-theme='light'] .hljs-bullet {
	color: var(--hljs-light-list);
}

[data-theme='light'] .hljs-emphasis {
	font-style: italic;
}

[data-theme='light'] .hljs-strong {
	font-weight: 600;
}

[data-theme='light'] .hljs-addition {
	color: var(--hljs-light-addition);
	background-color: var(--hljs-light-addition-bg);
}

[data-theme='light'] .hljs-deletion {
	color: var(--hljs-light-deletion);
	background-color: var(--hljs-light-deletion-bg);
}

/* ── Animations ───────────────────────────────────────────────────────── */

@keyframes spin {
	to {
		transform: rotate(360deg);
	}
}

@keyframes fadeIn {
	from { opacity: 0; }
	to { opacity: 1; }
}

@keyframes slideUp {
	from { opacity: 0; transform: translateY(8px); }
	to { opacity: 1; transform: translateY(0); }
}

@keyframes searchFlash {
	0% { background-color: rgba(250, 168, 26, 0.2); }
	100% { background-color: transparent; }
}

.searchHighlight {
	animation: searchFlash 2s ease-out;
}

/* ── Utility Classes ──────────────────────────────────────────────────── */

.text-smol {
	font-size: 14px;
	font-weight: 400;
	line-height: 1.2857142857;
}

.truncate {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	min-width: 0;
}

.clamp {
	--clamp-lines: 3;
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: var(--clamp-lines);
	line-clamp: var(--clamp-lines);
	overflow: hidden;
}

.zalgo-contain {
	--zalgo-line-height: 1.25em;
	line-height: var(--zalgo-line-height);
	max-height: var(--zalgo-line-height);
	overflow: hidden;
	display: block;
}

.zalgo-contain-inline {
	--zalgo-line-height: 1.25em;
	line-height: var(--zalgo-line-height);
	overflow: clip;
	overflow-clip-margin: 0px;
	display: inline-block;
	vertical-align: bottom;
	max-height: var(--zalgo-line-height);
}

.user-text {
	--user-text-line-height: 1.25em;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	min-width: 0;
	line-height: var(--user-text-line-height);
	max-height: var(--user-text-line-height);
	display: block;
}

.user-text-inline {
	--user-text-line-height: 1.25em;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	line-height: var(--user-text-line-height);
	max-height: var(--user-text-line-height);
	display: inline-block;
	vertical-align: bottom;
	max-width: 100%;
}

.user-text-flex {
	--user-text-line-height: 1.25em;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	min-width: 0;
	line-height: var(--user-text-line-height);
	max-height: var(--user-text-line-height);
	flex: 1 1 auto;
}

.emoji {
	font-family: var(--font-emoji);
	display: inline-block;
	width: var(--custom-emoji-size-emoji);
	height: var(--custom-emoji-size-emoji);
	object-fit: contain;
	vertical-align: bottom;
}

.emoji img {
	width: 100%;
	height: 100%;
	object-fit: contain;
}

.emoji.jumboable {
	width: var(--custom-emoji-size-jumbo-emoji);
	height: var(--custom-emoji-size-jumbo-emoji);
	min-height: var(--custom-emoji-size-jumbo-emoji);
}

.emoji:not(img) {
	font-size: var(--custom-emoji-size-emoji);
	line-height: 1;
	width: 1em;
	height: 1em;
}

.emoji.jumboable:not(img) {
	font-size: var(--custom-emoji-size-jumbo-emoji);
	width: 1em;
	height: 1em;
	min-height: 1em;
}

/* Twemoji inside contenteditable input */
.twemoji-inline {
	width: 1.375em;
	height: 1.375em;
	vertical-align: -0.3em;
	display: inline;
	object-fit: contain;
	pointer-events: none;
}

/* Custom MSC2545 server emoji inside the contenteditable input —
   sized to match .twemoji-inline so custom emojis and unicode
   emojis are visually identical in the composer. Without this rule
   the img renders at the source file's natural pixel dimensions
   (e.g. 128×128), making it tower over unicode emojis. */
.customEmojiInline {
	width: auto;
	height: 1.375em;
	max-width: 2.75em;
	vertical-align: -0.3em;
	display: inline;
	object-fit: contain;
	pointer-events: none;
}

/* Inline emoji images inserted into ChannelTextarea's contenteditable
   by the EmojiPicker. Both unicode (twemoji) and custom server emoji
   use these dimensions so they render identically in the composer. */
.customEmoji {
	display: inline-block;
	vertical-align: -0.125em;
	width: 1.375em;
	height: 1.375em;
	margin: 0 0.05em;
	user-select: text;
}

/* ── Focus Visible ────────────────────────────────────────────────────── */

:focus-visible {
	outline: 2px solid var(--focus-primary);
	outline-offset: 2px;
}

textarea:focus-visible,
textarea:focus {
	outline: none;
}

/* ── Selection ────────────────────────────────────────────────────────── */

::selection {
	background-color: var(--brand-primary);
	color: #fff;
}

/* ── Mobile Keyboard Handling ─────────────────────────────────────────── */

body.keyboard-visible {
	--mobile-bottom-nav-height: 0px;
}

body.keyboard-visible .mobile-bottom-nav {
	display: none;
}

/* ── Capacitor Safe Areas ─────────────────────────────────────────────── */

@supports (padding: env(safe-area-inset-top)) {
	:root {
		--safe-area-top: env(safe-area-inset-top, 0px);
		--safe-area-bottom: env(safe-area-inset-bottom, 0px);
		--safe-area-left: env(safe-area-inset-left, 0px);
		--safe-area-right: env(safe-area-inset-right, 0px);
	}
}

/* ── Accessibility: High Contrast ─────────────────────────────────────── */

@media (prefers-contrast: more) {
	:root {
		--text-primary: hsl(0, 0%, 100%);
		--text-secondary: hsl(0, 0%, 90%);
		--text-tertiary: hsl(0, 0%, 80%);
		--text-link: hsl(210, 100%, 70%);
		--border-color: hsl(0, 0%, 50%);
	}
	[data-theme='light'] {
		--text-primary: hsl(0, 0%, 0%);
		--text-secondary: hsl(0, 0%, 10%);
		--text-tertiary: hsl(0, 0%, 20%);
		--text-link: hsl(210, 100%, 40%);
		--border-color: hsl(0, 0%, 40%);
	}
}

/* ── Mobile: Disable Text Selection ───────────────────────────────────── */

@media (max-width: 840px) {
	:root {
		--user-select: none;
	}
	*,
	.select-text {
		user-select: none !important;
		-webkit-user-select: none !important;
		-moz-user-select: none !important;
		-ms-user-select: none !important;
	}
	input,
	textarea {
		user-select: auto !important;
		-webkit-user-select: auto !important;
		-moz-user-select: auto !important;
		-ms-user-select: auto !important;
	}
}

/* ── Reduced Motion ───────────────────────────────────────────────────── */

html.reduced-motion * {
	animation-duration: 0.01ms;
	animation-iteration-count: 1;
	transition-duration: 0.01ms;
	scroll-behavior: auto;
}
