05 / Skins
Writing a new one
A skin is a single file that assigns the contract. It cannot add selectors for component internals — if a skin needs a hook the anatomy does not expose, that is a gap in the anatomy and it gets fixed there. This is the discipline that keeps the system agnostic over time.
[data-se-skin="studio-edit"] {
/* type */
--se-font-sans: Archivo, system-ui, sans-serif;
--se-font-code: "Fragment Mono", ui-monospace, monospace;
--se-font-meta: "Archivo Narrow", system-ui, sans-serif;
--se-text-xs: 0.75rem;
--se-text-sm: 0.8125rem;
--se-text-md: clamp(1rem, 0.97rem + 0.13vi, 1.0625rem);
--se-text-lg: clamp(1.125rem, 1.05rem + 0.36vi, 1.25rem);
--se-text-xl: clamp(1.25rem, 1.09rem + 0.71vi, 1.5rem);
--se-text-2xl: clamp(1.5rem, 1.11rem + 1.79vi, 2rem);
--se-text-3xl: clamp(2.125rem, 1.27rem + 3.93vi, 3rem);
--se-text-4xl: clamp(2.5rem, 0.93rem + 7.14vi, 5rem);
--se-weight-regular: 400;
--se-weight-medium: 500;
--se-weight-semibold: 600;
--se-weight-bold: 700;
--se-leading-display: 0.98;
--se-leading-heading: 1.12;
--se-leading-lead: 1.45;
--se-leading-body: 1.6;
--se-leading-ui: 1.2;
--se-leading-code: 1.8;
--se-tracking-display: -0.035em;
--se-tracking-heading: -0.02em;
--se-tracking-body: 0;
--se-tracking-label: 0.1em;
/* colour — surfaces */
--se-bg: #FBFAF8;
--se-surface: #FFFFFF;
--se-surface-sunk: #F2EFE9; /* wells, inputs, disabled fills */
--se-surface-raised: #FFFFFF; /* same as surface here; a dark skin lifts it */
--se-border: #E8E4DE;
--se-border-strong: #D6D1C9; /* control edges */
--se-border-hover: #A9A29A;
/* colour — text. Two tiers on a light surface, because the AA floor
leaves no room for a third. Hierarchy below muted comes from size,
tracking and caps, never from a lighter grey. */
--se-text: #262934; /* Sky Captain — 13.9:1 */
--se-text-muted: #6E6862; /* 5.3:1 */
--se-text-placeholder: var(--se-text-muted);
--se-text-disabled: #B5AFA6; /* 2.1:1 — the WCAG exemption for inactive controls */
--se-text-on-intent: #FFFFFF; /* label on a solid fill; a pale-fill skin flips this */
--se-text-inverse: #D9D4CC; /* body on a dark surface */
--se-text-muted-inverse: #9C978E;
/* colour — accent and status. Each is one value used as text OR fill;
every softer tone is derived with color-mix, never added here. */
--se-accent: #2F5BE8;
--se-accent-soft: #EEF2FE;
--se-accent-line: #DBE3FC;
--se-positive: #1F6B4A;
--se-negative: #B8402A;
--se-warning: #8A5A0F;
/* space */
--se-space-1: 0.25rem;
--se-space-2: 0.5rem;
--se-space-3: 0.75rem;
--se-space-4: 1rem;
--se-space-5: 1.5rem;
--se-space-6: 2rem;
--se-space-7: 3rem;
--se-space-8: 4.5rem;
--se-section-y: clamp(3.5rem, 8vi, 5.5rem);
--se-page-gutter: clamp(1.25rem, 4vi, 2rem);
--se-stack-gap: clamp(1rem, 2.5vi, 1.5rem);
/* form */
--se-radius-none: 0;
--se-radius-sm: 0.3125rem;
--se-radius-md: 0.4375rem;
--se-radius-lg: 0.75rem;
--se-radius-pill: 999px;
--se-radius-nested: calc(var(--se-radius-lg) - var(--se-space-3));
--se-border-width: 1px;
--se-shadow-none: none;
--se-shadow-raised: 0 1px 2px rgba(38, 41, 52, 0.06), 0 1px 1px rgba(38, 41, 52, 0.04);
--se-shadow-floating: 0 4px 12px -2px rgba(38, 41, 52, 0.10), 0 2px 4px -1px rgba(38, 41, 52, 0.06);
--se-shadow-overlay: 0 16px 40px -8px rgba(38, 41, 52, 0.18), 0 4px 12px -4px rgba(38, 41, 52, 0.10);
--se-shadow-dragging: 0 24px 48px -12px rgba(38, 41, 52, 0.24), 0 8px 16px -8px rgba(38, 41, 52, 0.12);
--se-focus-width: 2px;
--se-focus-offset: 2px;
--se-focus-color: var(--se-accent);
/* icons */
--se-icon-sm: 1rem;
--se-icon-md: 1.25rem;
--se-icon-lg: 1.5rem;
--se-icon-weight: regular;
/* motion */
--se-duration-instant: 80ms;
--se-duration-fast: 160ms;
--se-duration-medium: 240ms;
--se-duration-slow: 400ms;
--se-ease-standard: cubic-bezier(0.2, 0, 0, 1);
--se-ease-decelerate: cubic-bezier(0, 0, 0, 1);
--se-ease-accelerate: cubic-bezier(0.3, 0, 1, 1);
/* layout */
--se-container-max: 72.5rem;
--se-bp-md: 40rem;
--se-bp-lg: 64rem;
--se-grid-columns: 4;
--se-grid-gutter: var(--se-space-4);
--se-grid-margin: var(--se-page-gutter);
--se-col-min: 14rem; /* auto-fit floor for tile grids */
--se-sidebar-min: 14rem; /* panel floor before main gives way */
--se-switch-at: 38rem; /* Switcher stacks below this */
/* dials */
--se-density: 1;
--se-font-scale: 1;
--se-target-min: 2.75rem; /* 44px touch floor */
/* control height — one source for every single-line control.
Set as block-size, not min-block-size, so no state can change it. */
--se-control-h-sm: 2rem;
--se-control-h: 2.5rem;
--se-control-h-lg: 3rem;
/* interaction mixes — a component sets --se-intent, every state derives */
--se-mix-soft: 8%; /* intent over surface: hover on outline and label */
--se-mix-press: 18%; /* intent over surface: pressed outline and label */
--se-mix-hover: 88%; /* intent over black: hover on solid */
--se-mix-down: 78%; /* intent over black: pressed solid */
--se-mix-line: 60%; /* intent over surface: the outline border */
--se-mix-shade: #262934; /* Sky Captain — what hover and press mix toward */
}