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 */
}

Reference skins

Maya Okonjo

Art director, Lagos → Berlin. Available for freelance from October.

Hire me Résumé
studio-edit · default

Maya Okonjo

Art director, Lagos → Berlin. Available for freelance from October.

Hire me Résumé
studio-edit-dark

Maya Okonjo

Art director, Lagos → Berlin. Available for freelance from October.

Hire me Résumé
creative-supplied skin

Maya Okonjo

Art director, Lagos → Berlin. Available for freelance from October.

Hire me Résumé
high-contrast