import { globalStyle, style } from "@vanilla-extract/css"; import { vars } from "./theme.css.ts"; globalStyle("html, body", { backgroundColor: vars.color.surface, margin: 0, }); // Mobile-first breakpoints (min-width) const bp = { sm: "screen and (min-width: 480px)", md: "screen and (min-width: 768px)", }; // ---- Root ---- export const themeRoot = style({ minHeight: "100vh", display: "flex", flexDirection: "column", fontFamily: vars.font.body, lineHeight: 1.6, color: vars.color.text, backgroundColor: vars.color.bg, transition: "background-color 0.2s, color 0.2s", }); // ---- Layout ---- export const container = style({ maxWidth: "640px", marginInline: "auto", paddingInline: vars.space.md, paddingBlockEnd: vars.space.xl, }); export const stack = style({ display: "flex", flexDirection: "column", gap: vars.space.md, }); export const stackSm = style({ display: "flex", flexDirection: "column", gap: vars.space.sm, }); export const stackLg = style({ display: "flex", flexDirection: "column", gap: vars.space.lg, }); export const cluster = style({ display: "flex", flexWrap: "wrap", gap: vars.space.sm, }); export const row = style({ display: "flex", alignItems: "center", justifyContent: "space-between", }); export const section = style({ marginBlockStart: vars.space.lg, display: "flex", flexDirection: "column", gap: vars.space.md, }); // ---- Header ---- export const header = style({ borderBlockEnd: `1px solid ${vars.color.border}`, backgroundColor: vars.color.surface, paddingBlock: vars.space.sm, marginBlockEnd: vars.space.lg, boxShadow: `0 1px 3px ${vars.color.shadow}, 0 1px 2px ${vars.color.shadow}`, transition: "background-color 0.2s, border-color 0.2s, box-shadow 0.2s", "@media": { [bp.sm]: { paddingBlock: vars.space.md, marginBlockEnd: vars.space.xl, }, }, }); export const headerInner = style({ marginInline: "auto", paddingInline: vars.space.lg, display: "flex", alignItems: "center", justifyContent: "space-between", }); export const headerTitle = style({ fontFamily: vars.font.heading, fontWeight: 700, fontSize: "1rem", color: vars.color.text, letterSpacing: "-0.01em", ":hover": { textDecoration: "none" }, "@media": { [bp.sm]: { fontSize: "1.125rem", }, }, }); export const headerNav = style({ display: "flex", alignItems: "center", gap: vars.space.sm, "@media": { [bp.sm]: { gap: vars.space.md, }, }, }); // ---- Cards ---- export const card = style({ backgroundColor: vars.color.surface, border: `1px solid ${vars.color.border}`, borderRadius: vars.radius.lg, paddingBlock: vars.space.md, paddingInline: vars.space.lg, boxShadow: `0 1px 3px ${vars.color.shadow}, 0 1px 2px ${vars.color.shadow}`, transition: "background-color 0.2s, border-color 0.2s, box-shadow 0.2s", ":hover": { backgroundColor: vars.color.surfaceHover, }, "@media": { [bp.sm]: { paddingBlock: vars.space.lg, paddingInline: vars.space.xl, }, }, }); export const cardLink = style({ display: "flex", flexDirection: "column", gap: vars.space.xs, textDecoration: "none", color: "inherit", backgroundColor: vars.color.surface, border: `1px solid ${vars.color.border}`, borderRadius: vars.radius.lg, paddingBlock: vars.space.md, paddingInline: vars.space.lg, boxShadow: `0 1px 3px ${vars.color.shadow}, 0 1px 2px ${vars.color.shadow}`, transition: "border-color 0.15s, box-shadow 0.2s, background-color 0.2s, transform 0.15s", ":hover": { backgroundColor: vars.color.surfaceHover, borderColor: vars.color.primary, boxShadow: `0 4px 12px ${vars.color.shadowStrong}, 0 2px 4px ${vars.color.shadow}`, transform: "translateY(-1px)", textDecoration: "none", }, "@media": { [bp.sm]: { paddingBlock: vars.space.lg, paddingInline: vars.space.xl, }, }, }); export const cardNarrow = style({ backgroundColor: vars.color.surface, border: `1px solid ${vars.color.border}`, borderRadius: vars.radius.lg, paddingBlock: vars.space.lg, paddingInline: vars.space.xl, maxWidth: "400px", marginInline: "auto", boxShadow: `0 1px 3px ${vars.color.shadow}, 0 1px 2px ${vars.color.shadow}`, transition: "background-color 0.2s, border-color 0.2s, box-shadow 0.2s", "@media": { [bp.sm]: { paddingBlock: vars.space.xl, paddingInline: vars.space.xxl, }, }, }); export const cardFlat = style({ borderBlockStart: `1px solid ${vars.color.border}`, paddingBlock: vars.space.sm, "@media": { [bp.sm]: { paddingBlock: vars.space.md, }, }, }); // ---- Buttons ---- const btnBase = { boxSizing: "border-box" as const, display: "inline-flex" as const, alignItems: "center" as const, justifyContent: "center" as const, borderRadius: vars.radius.sm, fontWeight: 500, lineHeight: 1.5, cursor: "pointer", fontFamily: vars.font.body, minBlockSize: "44px", whiteSpace: "nowrap" as const, transition: "background-color 0.15s, opacity 0.15s, box-shadow 0.15s, transform 0.1s", }; export const button = style({ ...btnBase, paddingBlock: vars.space.sm, paddingInline: vars.space.lg, border: "none", fontSize: "0.875rem", backgroundColor: vars.color.primary, color: "#fff", boxShadow: `0 1px 2px ${vars.color.shadow}`, ":hover": { backgroundColor: vars.color.primaryHover, textDecoration: "none", boxShadow: `0 2px 6px ${vars.color.shadowStrong}`, }, ":disabled": { opacity: 0.5, cursor: "not-allowed" }, ":active": { transform: "scale(0.98)" }, }); export const buttonSecondary = style({ ...btnBase, paddingBlock: vars.space.sm, paddingInline: vars.space.lg, border: `1px solid ${vars.color.border}`, fontSize: "0.875rem", backgroundColor: vars.color.surface, color: vars.color.text, ":hover": { backgroundColor: vars.color.bg, textDecoration: "none", borderColor: vars.color.primary, }, ":active": { transform: "scale(0.98)" }, }); export const buttonDanger = style({ ...btnBase, paddingBlock: "6px", paddingInline: vars.space.md, border: "none", fontSize: "0.75rem", minBlockSize: "36px", backgroundColor: vars.color.danger, color: "#fff", ":hover": { opacity: 0.9 }, ":active": { transform: "scale(0.98)" }, }); // ---- Forms ---- export const formStack = style({ display: "flex", flexDirection: "column", gap: vars.space.lg, }); export const label = style({ display: "block", fontSize: "0.875rem", fontWeight: 500, marginBlockEnd: vars.space.xs, }); export const labelHint = style({ fontWeight: 400, color: vars.color.textMuted, }); const inputBase = { boxSizing: "border-box" as const, width: "100%" as const, paddingBlock: "10px", paddingInline: vars.space.md, borderRadius: vars.radius.sm, border: `1px solid ${vars.color.border}`, fontSize: "1rem", lineHeight: 1.5, color: vars.color.text, backgroundColor: vars.color.surface, outline: "none" as const, fontFamily: vars.font.body, transition: "border-color 0.15s, box-shadow 0.15s", }; const inputFocus = { borderColor: vars.color.primary, boxShadow: `0 0 0 3px ${vars.color.focusRing}`, }; export const input = style({ ...inputBase, ":focus": inputFocus, }); export const select = style({ ...inputBase, ":focus": inputFocus, }); export const textarea = style({ ...inputBase, resize: "vertical" as const, minHeight: "80px", fontFamily: vars.font.body, ":focus": inputFocus, }); // ---- Typography ---- export const pageTitle = style({ fontFamily: vars.font.heading, fontSize: "1.25rem", fontWeight: 700, letterSpacing: "-0.02em", "@media": { [bp.sm]: { fontSize: "1.5rem", }, }, }); export const sectionTitle = style({ fontFamily: vars.font.heading, fontSize: "1rem", fontWeight: 600, letterSpacing: "-0.01em", "@media": { [bp.sm]: { fontSize: "1.125rem", }, }, }); export const cardTitle = style({ fontFamily: vars.font.heading, fontSize: "1rem", fontWeight: 600, letterSpacing: "-0.01em", "@media": { [bp.sm]: { fontSize: "1.0625rem", }, }, }); export const cardHeading = style({ fontFamily: vars.font.heading, fontSize: "1.125rem", fontWeight: 600, marginBlockEnd: vars.space.sm, letterSpacing: "-0.01em", "@media": { [bp.sm]: { fontSize: "1.25rem", }, }, }); export const muted = style({ color: vars.color.textMuted, fontSize: "0.8125rem", }); export const description = style({ color: vars.color.textMuted, fontSize: "0.875rem", lineHeight: 1.5, display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical", overflow: "hidden", }); export const subsectionTitle = style({ fontSize: "0.875rem", fontWeight: 500, color: vars.color.textMuted, }); export const collapsibleHeading = style({ display: "flex", alignItems: "center", gap: vars.space.sm, cursor: "pointer", userSelect: "none", background: "none", border: "none", padding: 0, fontFamily: vars.font.heading, fontSize: "1rem", fontWeight: 600, color: vars.color.text, ":hover": { color: vars.color.primary, }, }); export const chevron = style({ display: "inline-block", fontSize: "0.75rem", transition: "transform 0.15s", }); export const chevronExpanded = style({ transform: "rotate(180deg)", }); export const introText = style({ color: vars.color.textMuted, fontSize: "0.875rem", lineHeight: 1.6, marginBlockEnd: vars.space.lg, }); export const badge = style({ display: "inline-block", paddingBlock: "2px", paddingInline: vars.space.sm, borderRadius: vars.radius.sm, fontSize: "0.75rem", fontWeight: 500, backgroundColor: vars.color.primaryLight, color: vars.color.primary, }); globalStyle(`${badge}[data-status="not-planned"]`, { backgroundColor: vars.color.dangerLight, color: vars.color.danger, }); globalStyle(`${badge}[data-status="approved"]`, { backgroundColor: vars.color.primaryLight, color: vars.color.primary, }); globalStyle(`${badge}[data-status="in-progress"]`, { backgroundColor: vars.color.warningLight, color: vars.color.warning, }); globalStyle(`${badge}[data-status="done"]`, { backgroundColor: vars.color.successLight, color: vars.color.success, }); export const errorText = style({ color: vars.color.danger, fontSize: "0.875rem", }); // ---- Misc ---- export const metaRow = style({ display: "flex", flexWrap: "wrap", alignItems: "center", gap: vars.space.md, fontSize: "0.875rem", }); export const buttonInline = style({ background: "none", border: "none", color: vars.color.primary, fontSize: "0.875rem", fontWeight: 500, fontFamily: vars.font.body, cursor: "pointer", paddingBlock: 0, paddingInline: vars.space.sm, ":hover": { textDecoration: "underline" }, }); export const buttonDangerInline = style({ background: "none", border: "none", color: vars.color.danger, fontSize: "0.875rem", fontWeight: 500, fontFamily: vars.font.body, cursor: "pointer", paddingBlock: 0, paddingInline: vars.space.sm, ":hover": { textDecoration: "underline" }, }); export const inlineTag = style({ marginInlineStart: vars.space.sm, }); // ---- Responsive utilities ---- export const hiddenMobile = style({ display: "none", "@media": { [bp.md]: { display: "initial", }, }, }); // ---- Theme toggle ---- // ---- Tab navigation ---- export const tabNav = style({ display: "flex", gap: vars.space.xs, borderBlockEnd: `1px solid ${vars.color.border}`, paddingBlockEnd: vars.space.xs, }); export const tabNavLink = style({ paddingBlock: vars.space.xs, paddingInline: vars.space.md, borderRadius: vars.radius.sm, fontSize: "0.875rem", fontWeight: 500, color: vars.color.textMuted, textDecoration: "none", transition: "color 0.15s, background-color 0.15s", ":hover": { color: vars.color.text, backgroundColor: vars.color.surfaceHover, textDecoration: "none", }, }); export const tabNavActive = style({ paddingBlock: vars.space.xs, paddingInline: vars.space.md, borderRadius: vars.radius.sm, fontSize: "0.875rem", fontWeight: 500, color: vars.color.primary, backgroundColor: vars.color.primaryLight, }); // ---- Theme toggle ---- export const themeToggle = style({ display: "inline-flex", alignItems: "center", border: `1px solid ${vars.color.border}`, borderRadius: vars.radius.sm, overflow: "hidden", padding: "2px", gap: "2px", backgroundColor: vars.color.bg, transition: "background-color 0.2s, border-color 0.2s", }); export const themeToggleBtn = style({ display: "inline-flex", alignItems: "center", justifyContent: "center", inlineSize: "28px", blockSize: "28px", border: "none", borderRadius: "6px", cursor: "pointer", backgroundColor: "transparent", color: vars.color.textMuted, padding: 0, transition: "background-color 0.15s, color 0.15s", ":hover": { color: vars.color.text }, }); export const themeToggleBtnActive = style({ backgroundColor: vars.color.surface, color: vars.color.text, boxShadow: `0 1px 2px ${vars.color.shadow}`, }); // ---- Footer ---- export const mainContent = style({ flex: 1, }); export const footer = style({ borderBlockStart: `1px solid ${vars.color.border}`, paddingBlock: vars.space.lg, marginBlockStart: vars.space.xxl, transition: "background-color 0.2s, border-color 0.2s", }); export const footerInner = style({ maxWidth: "640px", marginInline: "auto", paddingInline: vars.space.md, display: "flex", flexWrap: "wrap", alignItems: "center", justifyContent: "center", gap: vars.space.sm, fontSize: "0.8125rem", color: vars.color.textMuted, }); export const footerSep = style({ color: vars.color.border, }); export const footerLink = style({ color: vars.color.textMuted, textDecoration: "none", transition: "color 0.15s", ":hover": { color: vars.color.primary, }, });