Skip to content

Free shipping on every order to the US and Canada. Free shipping to the US and Canada.

Dist. by Amber & Oil, New Jersey

Design system 2026-10-06

Style guide, measured.

Every token and component of the storefront, rendered from the stylesheet and the snippets that ship. One serif for what is said, one label face for what is named, one mono for what is counted. No rounded corners, no shadows, hairlines instead of boxes. Amber marks commitment only.

01

Colour

Nine tokens, and only the six text pairs that were checked. Amber is never decoration: it is the one commitment button of a view (“Find your formula”, “Make it yours”, add to bag, check out), the tick of the Measure and the progress fill. Links are ink.

paper

--paper #F3F3F0

Page ground. Most surfaces start here.

ink

--ink #17191B

Type, logo, hairlines, the default button.

amber

--amber #A85A17

Commitment only: the one amber button of a view, the tick of the Measure, progress.

glass

--glass #E6D3B8

Tint ground, packaging.

steel

--steel #5F6469

Secondary text.

oil

--oil #D9B46A

Blend bars only (the base oil). Never text.

white

--white #FFFFFF

The chosen size, the label of the bottle.

line

--line #DCDCD6

The quiet hairline between rows.

amber light

--amber-light #D9A45E

Amber on the ink ground only.

Checked text pairs

Ink on paper

15.9:1 · AA

Amber on paper

4.6:1 · AA

Steel on paper

5.4:1 · AA

White on amber

5.1:1 · AA

Ink on glass

12.1:1 · AA

Amber light on ink

7.9:1 · AA

Grounds

.ao-ground .ao-ground--paper | --white | --glass | --ink | --amber set the ground and redefine the contextual colours (--ao-text, --ao-muted, --ao-link, --ao-rule, --ao-focus), so every component stays inside the checked pairs wherever it stands.

paper

Blended by hand, to the gram.

Secondary text, and a link.

Continue

white

Blended by hand, to the gram.

Secondary text, and a link.

Continue

glass

Blended by hand, to the gram.

Secondary text, and a link.

Continue

ink

Blended by hand, to the gram.

Secondary text, and a link.

Continue

amber

Blended by hand, to the gram.

Secondary text, and a link.

Continue

02

Type

Newsreader 300 sets headlines, blend names and oil names (350 for lead text), with italic for emphasis and for every INCI name. Archivo Expanded 500 in capitals names things: navigation, eyebrows, buttons, role labels, never under 12 px. Schibsted Grotesk is body and interface text at 16/26. IBM Plex Mono is every number.

Editorial scale

Fluid between 390 px and 1280 px. .ao-display .ao-display--{xxl|xl|lg|md|sm}; h1 to h4 take xl, lg, md, sm.

--text-display-xxl · 48 at 320, 56 at 390, 97 at 1280 px

Your formula, measured to the gram.

--text-display-xl · 40 to 60 px

What’s your hair type?

--text-display-lg · 32 to 42 px

Three steps. One formula.

--text-display-md · 26 to 32 px

The quiz suggests.

--text-display-sm · 22 to 24 px

Argan, weighed to a tenth of a gram.

.ao-lead · Newsreader 350 · 20 to 24 px

A short quiz suggests a formula. You change any oil. We blend each bottle by hand and print its label with your formula and the name you give it.

body · Schibsted Grotesk 400 · 16/26

Six questions about your hair and scalp, about two minutes. We suggest your base oils and your actives, with the percent of each. Emphasis inside body text is the serif italic, never a slanted sans, and .ao-strong is weight 500.

.ao-serif · 20 px · .ao-inci · italic 17 px

Atlas Cedarwood

Cedrus Atlantica Bark Oil

Simmondsia Chinensis (Jojoba) Seed Oil

.ao-eyebrow · Archivo Expanded 500 · 12 px

Custom hair & scalp oil

Signature blendNº 0142

A number inside a label is set in the mono: wrap it in .ao-data or .ao-num.

.ao-data · IBM Plex Mono · 13, 12, 16 px

Question 2 of 7

4 oz (118 mL) · 108.6 g

78.5%

21.4 g of jojoba: .ao-num is a bare number, .ao-u its unit.

$64.00 .ao-price

$64 .ao-price--lg

.ao-meta · .ao-caption

6 questionsAbout 2 minutesNo account needed

Ratio, percent by weight4 oz · 108.6 g

Rich text

.ao-rte (and Shopify’s own .rte on policy pages): what the editor produces, in the same language.

Refund policy

Every bottle is made to order, so we don't take returns for a change of mind. If yours arrives damaged, leaking or wrong, or you have a reaction, we replace it free or refund you.

What we replace

  • A bottle that arrives damaged or leaking.
  • A bottle that is not the formula on its label.

Made to order, so no returns for a change of mind. Damaged, leaking or wrong bottle, or a reaction: free replacement or refund.

SizeNet quantityClosure
1 oz30 mLDropper
4 oz118 mLTreatment pump
8 oz237 mLTreatment pump

03

Space, layout, motion

Mobile first at 390 px. Breakpoints: 48em, 64em, 80em. The gutter is 20 px, 32 px from 48em and 48 px from 80em. Sections breathe: --section-y runs from 80 to 149 px.

Spacing steps

--space-1 4
--space-2 8
--space-3 12
--space-4 16
--space-5 24
--space-6 32
--space-7 48
--space-8 64
--space-9 96
--space-10 128
--space-11 160

Sizes and motion

Container
.ao-container84rem + gutters
Narrow
.ao-container--narrow42rem
Control
--control-h56 px
Tap target
--tap44 px
Header
--header-h60, 72 px
Radius
--radius-1, -20
Hairline
--ao-rule, --ao-text1 px
Motion
--dur-1, --dur-2150, 250 ms
Easing
--ease.2, 0, 0, 1

Only opacity and a small translate move. .ao-rise fades a block in over 6 px when it first scrolls into view; the Measure may fill once (reveal: true). Reduced motion switches all of it off.

This line rises once.

Layout primitives

.ao-section (section padding), .ao-stack --xs --sm --lg --xl, .ao-cluster --between, .ao-grid (auto-fill, --ao-grid-min), .ao-split --5-7 --7-5 (12 columns from 64em, .ao-split__pin keeps a column in view), .ao-divider --strong, .ao-from-lg / .ao-until-lg, .ao-visually-hidden.

.ao-split--5-7

A head that stays, beside a list that runs.

  1. Base Argan Argania Spinosa Kernel Oil 78.5%
  2. Active Avocado Persea Gratissima (Avocado) Oil 10%
  3. Active Baobab Adansonia Digitata Seed Oil 10%

05

Buttons and links

Wide, quiet, square: the label sits left and a thin arrow sits right, drawn by the stylesheet (the markup is only the label). Ink is the default and every step-advance. Amber is commitment only, at most one per view. Hover moves the arrow 4 px.

.ao-btn.ao-btn--primary

Ink. The default, and every step-advance.

.ao-btn.ao-btn--cta

Amber. Commitment only: at most one per view.

.ao-btn.ao-btn--secondary

Outline. Hover fills it.

.ao-btn.ao-btn--quiet

A label link with no box.

aria-busy="true" with .ao-btn__stack

The label swaps in place, so the button keeps its width; the arrow gives way to a rule that breathes.

.ao-btn--block · .ao-btn--sm

Continue to actives Swap to Jojoba

.ao-btn--quiet.ao-btn--back · a link that is disabled

Back Build from scratch

Action groups

.ao-actions: stacked and full width on a phone with the quiet link centred under the buttons, a row from 48em. --center centres the row; --stack sets two buttons side by side from 64em.

6 questionsAbout 2 minutesNo account needed

Links

A text link is ink with a hairline underline, and hover thickens the rule.

a, .ao-link

Edit blend Back Remove

.ao-link--label · --back · --quiet

Find your formula The oils

.ao-navlink · [aria-current="page"]

06

Fields

A field stands on a rule, like a line in a ledger: the label above in the label face, the value in the serif. Help and error are wired with aria-describedby. The palette has no error hue, so an error is a mark, weight and a doubled rule.

Default, with a placeholder and help.

Give your blend a name.

13 of 28 characters. It’s printed on your label.

.ao-input.ao-input--display

Several lines need their edges: the textarea is the one boxed field.

.ao-check (checkbox)

.ao-check (radio)

.ao-busy · .ao-note

Loading…

Refunds

Every bottle is made to order, so we don't take returns for a change of mind. If yours arrives damaged, leaking or wrong, or you have a reaction, we replace it free or refund you.

07

Option rows

Quiz answers and builder oils are rows on hairlines, never cards. The native radio or checkbox covers the row, so the whole row is the tap area and the keyboard works as the platform defines it. Selected is a filled mark, ink rules and an italic title, never colour alone. One answer has a round mark, several a square one.

One answer, with a leading glyph (.ao-option__lead)

Question 1 of 6Hair & Scalp Oil

What’s your hair type?

Several answers, with a maximum (.ao-options__note)

Question 4 of 6

What should your oil do?

Pick up to two, the most important first.

You’ve picked 2. Remove one to pick another.

Oils on a scale (.ao-scale): plate, italic INCI name, weight meter, “Suited to you”, a note

Choose your base

Light

Rich

States: hover, focus, off with a reason, selected and off

Product line

.ao-options--2: side by side from 48em

.ao-weight: the four-step meter, always beside its words

Weight 1 of 4 Weight 2 of 4 Weight 3 of 4 Weight 4 of 4

08

Steps

A step has a header (a mono count over a serif question), progress or navigation standing on a ruler, and a sticky bar at the foot of the screen. The step title takes focus on every step change.

.ao-step (h1, h2 or h3 for the title)

Step 2 of 5

Choose your base

The base is about 80% of your blend. Bases run from light to rich: 1 is the lightest, 4 the richest.

Quiz progress: {% render 'measure', variant: 'progress', steps: 7, step: 2 %}

Plain progress: value: 43

.ao-stepnav: steps standing on a ruler; the current one carries the amber tick. Only it shows its name until the navigation is 64rem wide.

.ao-actionbar: Back, then the one main action (sticky in a flow)

.ao-actionbar__note: the main action is never switched off. Pressed too early, it says why on the bar's top edge (the strip lies over the page and moves nothing)

Pick an answer to continue.

.ao-actionbar__summary: the summary bar (the blend at a glance, on a phone)

Your blend4 oz · $64

09

Notices

Guardrail messages come from the rules engine, word for word. The palette has no warning hue, so the three levels differ by their label, their mark and the rule they stand under. A notice may carry one action: the engine’s nearest safe option, one tap.

Needs a change

Argan is out of stock right now, so this blend can’t be ordered as it is.

Worth knowing

That size is sold out right now.

Good to know

Added to your bag.

.ao-notice__title: where the notice is the main thing in its place · .ao-notice__more: a second, quieter sentence · the action may be a link with the same classes, and there may be several · a line and a quiet way round follow the actions

Can’t be reordered as is

We can’t reorder this one as it is.

Castor is out of stock right now. Your quiz answers on this device leave this oil out.

It opens in the builder with the swap already made.

Extra oils (app/ui: <ExtrasNote>): what the price includes and what one more oil adds, as a fact under the quiet rule. No badge, no nudge. It is silent on a price it was not given, and the store’s own wording for a tier is never printed.

Within what is included

Extra oils

3 base oils are included in the price.

The next one is an extra oil, no size chosen yet

Extra oils

3 base oils are included in the price. One more adds $5.00 at 4 oz and $8.00 at 8 oz. A 1 oz bottle holds no extra oils.

The blend holds extra oils, 4 oz chosen

Extra oils

4 active oils are included in the price. This blend has 3 extra oils, which add $15.00 at 4 oz.

Sample prices. A real one is the difference between two variants of the store, never a number in the code.

A size that cannot hold a blend (app/ui: <SizeNotice>): the engine’s sentence and its one tap on. A block, because the blend cannot be added in that size.

Bottle size

Your blend has 3 extra oils. A 1 oz bottle holds no extra oils, so this blend starts at 4 oz.

Bottle size

Your blend has 3 extra oils, and no bottle holds that many yet. Remove an oil to continue.

10

The Measure

A ruler (a tick every 1%, a long tick every 10%) under a ratio bar of a blend’s exact proportions. Segments always come from a real recipe, one per oil with its true share: several bases in the one oil colour, up to five actives, the essential oil, vitamin E. The markup contract is at the top of snippets/measure.liquid; app/ui/Measure.tsx emits the same markup and a parity test holds the two together.

size: 'lg', scale: true, reveal: true · the bar of the result, numbered 0 to 100, filling once

Ratio, percent by weight4 oz · 108.6 g

Default (md)

size: 'sm'

legend: true

  • Argan 78.5%
  • Avocado 10%
  • Baobab 10%
  • Atlas Cedarwood 1%
  • Vitamin E 0.5%

Three actives, scale: true

Every role: five bases, five actives, the essential oil, vitamin E · size: 'lg', scale: true, legend: true. The bases are one colour, parted by the paper gap; the fourth and fifth actives are the first two colours cut by hairlines. The legend is the text of the bar and the place to find a segment of 1% or 0.5%.

  • Jojoba 22.8%
  • Grapeseed 18.3%
  • Squalane 13.7%
  • Argan 9.1%
  • Fractionated Coconut 4.6%
  • Hemp Seed 9.2%
  • Pumpkin Seed 6.9%
  • Rosehip 5.8%
  • Evening Primrose 4.6%
  • Prickly Pear Seed 3.5%
  • Rosemary 1%
  • Vitamin E 0.5%

Two bases · legend: true

  • Grapeseed 52.3%
  • Jojoba 26.2%
  • Baobab 10%
  • Pumpkin Seed 10%
  • Sweet Orange 1%
  • Vitamin E 0.5%

Two bases and three actives at 24%

Every role, size: 'sm' (the bag line)

The balance

How much of the bottle the actives take, set on a ruler (app/ui: <Balance>; snippets/balance.liquid prints the same markup for one set of figures). The ruler runs over what the rules allow, a tick per step. The marker is the thumb of a real range input laid over what the chosen actives can reach, so arrows, Home and End, a screen reader and a finger move the same thing, and it says both figures: “Actives 24%, base oils 74.5%”. The base oils take what the actives leave. Every figure here is the engine’s answer for a real blend; on this page the marker moves but nothing answers it.

Three actives, at the least, with what else the bottle holds (sample words; the builder writes them from the engine’s figures)

Actives20%

Base oils78.5%

Plus 1% essential oils and 0.5% Vitamin E.

Whole percents. Your base oils take what your actives leave.

Moved up, focus on the marker

Actives24%

Base oils74.5%

Whole percents. Your base oils take what your actives leave.

Two actives reach one share only: the ruler stands still and says why

Actives20%

Base oils78.5%

The actives you picked can make up 20% of the bottle. Add another to go higher.

No share yet (one active, the blend is blocked): rules, never numbers

Actives

Base oils

Actives24%

Base oils74.5%

Whole percents. Your base oils take what your actives leave.

variant: 'rule', tick: 80 · the ruler alone. Outside a container it runs from edge to edge, as an architectural line.

variant: 'beaker', bottle: '1oz'

variant: 'beaker', bottle: '4oz'

variant: 'beaker', bottle: '8oz'

Segment roles

  • Base oils, every one --oil
  • First active --amber
  • Second active --steel
  • Third active --glass
  • Fourth active --amber, cut
  • Fifth active --steel, cut
  • Essential oil --ink
  • In every blend --white

On white

On glass

On ink

On amber

11

Rows on hairlines

The recipe is set like a printed formulary, a few true counts as a ledger, the oils as a numbered index. An ink rule opens and closes a table; the quiet rule separates its rows. A bottle has four parts (base oils, actives, essential oils, vitamin E): the formulary shows them as heads over its rows, each with its share.

The parts of the bottle · snippets/formulary.liquid, app/ui: <Formulary groups={formularyGroups(formula)}> · the one way a recipe’s structure is shown. A quiet head per part with its share in the mono; under it each oil once, with its percent. The shares sum to 100, and so do the rows.

  1. Base oils

    1. 01ArganArgania Spinosa Kernel Oil78.5%85.4 gYour base: a medium-light oil.
  2. Actives

    1. 01AvocadoPersea Gratissima (Avocado) Oil10%10.8 gYour lead active, tagged for moisture and softness.
    2. 02BaobabAdansonia Digitata Seed Oil10%10.8 gAn active tagged for moisture, softness and less frizz.
  3. Essential oils

    1. Essential oilAtlas CedarwoodCedrus Atlantica Bark Oil1%1 gAn essential oil you picked, at 1%.
  4. In every blend

    1. AdditiveVitamin ETocopherol0.5%0.6 gIn every blend at 0.5% to slow oxidation.

Total 100% 108.6 g

Two bases · act_label: 'Change' (the way back to a whole part, beside its name; the share keeps the far end)

  1. Base oils

    1. 01GrapeseedVitis Vinifera (Grape) Seed Oil52.3%56.9 g
    2. 02JojobaSimmondsia Chinensis (Jojoba) Seed Oil26.2%28.5 g
  2. Actives

    1. 01BaobabAdansonia Digitata Seed Oil10%10.8 g
    2. 02Pumpkin SeedCucurbita Pepo (Pumpkin) Seed Oil10%10.8 g
  3. Essential oils

    1. Essential oilSweet OrangeCitrus Aurantium Dulcis (Orange) Peel Oil1%1 g
  4. In every blend

    1. AdditiveVitamin ETocopherol0.5%0.6 g

Every role: five bases, five actives, in grams for 8 oz. A role under a head is the oil’s place in its part. From 64em a formulary sets its figures in two columns beside the names, so it wants a column of 36rem or more there.

  1. Base oils

    1. 01JojobaSimmondsia Chinensis (Jojoba) Seed Oil22.8%49.7 g
    2. 02GrapeseedVitis Vinifera (Grape) Seed Oil18.3%39.9 g
    3. 03SqualaneSqualane13.7%29.9 g
    4. 04ArganArgania Spinosa Kernel Oil9.1%19.8 g
    5. 05Fractionated CoconutCaprylic/Capric Triglyceride4.6%10 g
  2. Actives

    1. 01Hemp SeedCannabis Sativa Seed Oil9.2%20.1 g
    2. 02Pumpkin SeedCucurbita Pepo (Pumpkin) Seed Oil6.9%15.1 g
    3. 03RosehipRosa Canina Fruit Oil5.8%12.7 g
    4. 04Evening PrimroseOenothera Biennis (Evening Primrose) Oil4.6%10 g
    5. 05Prickly Pear SeedOpuntia Ficus-Indica Seed Oil3.5%7.6 g
  3. Essential oils

    1. Essential oilRosemaryRosmarinus Officinalis (Rosemary) Leaf Oil1%2.1 g
  4. In every blend

    1. AdditiveVitamin ETocopherol0.5%1.1 g

.ao-formulary.ao-formulary--plates as one list: role, plate, oil, italic INCI name, percent, grams, one line of reason · .ao-formulary__act: the quiet way back to where an oil was chosen (what is in every blend has none, and takes the single drop as its plate)

  1. Base Argan Argania Spinosa Kernel Oil 78.5% 85.4 g Your base: a medium-light oil.
  2. Active Avocado Persea Gratissima (Avocado) Oil 10% 10.8 g Your lead active, tagged for moisture and softness.
  3. Active Baobab Adansonia Digitata Seed Oil 10% 10.8 g An active tagged for moisture, softness and less frizz.
  4. Essential oil Atlas Cedarwood Cedrus Atlantica Bark Oil 1% 1 g An essential oil you picked, at 1%.
  5. In every blend Vitamin E Tocopherol 0.5% 0.6 g In every blend at 0.5% to slow oxidation.

.ao-total: the two sums that close a formulary · .ao-inci-list: the ingredient list, highest to lowest · .ao-specs: a label and a figure per hairline, for what a bottle is (never for facts a line above already said) · .ao-disclosure: a serif line between two hairlines, plus when closed, minus when open. Where it opens a fuller form of a list, it stands over that list, so nothing above it moves

Total 100% 108.6 g

Argania Spinosa Kernel Oil, Persea Gratissima (Avocado) Oil, Adansonia Digitata Seed Oil, Cedrus Atlantica Bark Oil, Tocopherol

Bottle
4 fl oz (118 mL)
Closure
Treatment pump
Fill
108.6 g
Full formula In grams for 4 oz, with label names

The formulary, its total and the ingredient list stand here.

.ao-ledger: counts from the oil library

Base oils
05
Actives
05
Scents
07
Sizes, in oz
1 · 4 · 8

.ao-index: the numbered oil index, with plates and the weight meter

Base oils05

  1. 01 Grapeseed Vitis Vinifera (Grape) Seed Oil Weight 1 of 4
  2. 02 Jojoba Simmondsia Chinensis (Jojoba) Seed Oil Weight 1 of 4
  3. 03 Argan Argania Spinosa Kernel Oil Weight 2 of 4
  4. 04 Fractionated Coconut Caprylic/Capric Triglyceride Weight 2 of 4
  5. 05 Sweet Almond Prunus Amygdalus Dulcis (Sweet Almond) Oil Weight 3 of 4

12

Size and quantity

The size picker is three joined cells on hairlines, one native radio each; the chosen one turns white with an ink edge and an italic label. The quantity stepper is three 44 px cells in one ink frame.

.ao-sizes · .ao-size

Size

Sample prices. Real prices always come from the Shopify variant.

.ao-stepper: minus is off at one bottle

13

The bottle

The drawn bottle is the customer’s own: an amber Boston round with the label of docs/labels.md, their blend name on it and their recipe in the beaker. It stays for the personal moments (result, builder summary, name step, bag). A photograph of a bottle is never captioned as the customer’s. Snippet bottle.liquid and app/ui/Bottle.tsx are generated from one geometry.

{% render 'bottle', size: '1oz' | '4oz' | '8oz', name: …, recipe: … %} · drawn here to one scale

102030mL1 FL OZ (30 mL)ZoHAIR & SCALP OIL
1 oz · dropper · “Zo”
306090mL4 FL OZ (118 mL)SundayRitualHAIR & SCALP OILNº 0142
4 oz · pump · Nº 0142
60120180240mL8 FL OZ (237 mL)The longway home atnightHAIR & SCALP OIL
8 oz · pump · 26 characters

The beaker of a blend with two bases: one oil colour, the second base standing on a hairline as heavy as the gauge

306090mL4 FL OZ (118 mL)Light TouchHAIR & SCALP OIL

Every role: five bases, five actives. The fourth and fifth actives are the first two colours cut by hairlines of the label’s white, drawn by the bottle itself.

60120180240mL8 FL OZ (237 mL)Every RoleHAIR & SCALP OIL

The name on the label: blank, short, wrapped, and one word wider than the label (squeezed, never broken)

306090mL4 FL OZ (118 mL)HAIR & SCALP OIL
No name yet
306090mL4 FL OZ (118 mL)ZoHAIR & SCALP OIL
2 characters
306090mL4 FL OZ (118 mL)SundayRitualHAIR & SCALP OIL
13 characters
306090mL4 FL OZ (118 mL)The longway home atnightHAIR & SCALP OIL
26 characters
306090mL4 FL OZ (118 mL)SupercalifragilisticexpialidHAIR & SCALP OIL
28 characters
306090mL4 FL OZ (118 mL)Root NoteHAIR & SCALP OIL
Before the formula

.ao-blendname: the blend-name moment (app/ui: <BlendName> keeps the label in step with every keystroke)

13 of 28 characters. It’s printed on your label.

.ao-summary: the summary column of a step flow (ao-app.css)

Your blend

Base oils
Argan78.5%
Actives
Avocado, Baobab20%
Essential oils
Atlas Cedarwood1%
In every blend
Vitamin E0.5%

Price, 4 oz$64

.ao-bottle-stage--label: the label close up, wherever a name is typed beside it or the column is narrow (the name is drawn at 13 px or more)

shadow: true · .ao-bottle-stage: the pale ground it stands on

306090mL4 FL OZ (118 mL)SundayRitualHAIR & SCALP OIL

14

Photographs

Fifty-five frames, listed with their size, alt text and intended use in data/shoot.json. The shot snippet (and app/ui/Shot.tsx) turns a frame id into a responsive image: srcset through asset_img_url, width and height so nothing shifts, alt text from the manifest, lazy unless it is the one eager image of the page. Generated bottles are unlabelled stand-ins: never caption one as the customer’s bottle.

{% render 'shot', id: 'ruler', sizes: '(min-width: 64em) 50vw, 100vw' %}
{% render 'shot', id: 'pour', ratio: '4 / 5', sizes: '(min-width: 64em) 33vw, 100vw' %}
{% render 'shot', id: 'plate-argan', sizes: '72px', class: 'ao-plate', decorative: true %}
{% render 'shot', id: 'hero-portrait', wide_id: 'hero-wide', sizes: '100vw', loading: 'eager' %}
Five glass dishes of oil, pale gold to deep amber, standing along a steel rule.
id: 'ruler'2048 × 1360 · its own ratio
Golden oil pouring in a thin stream into a glass beaker standing on a small black scale.
id: 'pour', ratio: '4 / 5'Cropped
Three amber glass bottles in a row in ascending size: one with a dropper, two with pumps.
id: 'sizes', ratio: '1'Square
An amber glass dropper bottle on pale paper, backlit, casting one long amber shadow.
id: 'hero-portrait', wide_id: 'hero-wide' Art-directed: portrait below 64em, wide from 64em. The paper is left empty for the headline.

Ingredient plates: plate-<oil id>, wherever an oil is chosen or listed (.ao-plate, .ao-plate--sm)

Argan: argan nuts, two cracked open to show the kernels, beside a small glass dish of the oil.
Argan
Jojoba: whole jojoba seeds with two split seed capsules, beside a small glass dish of the oil.
Jojoba
Grapeseed: a sprig of dark grapes with a small heap of grape seeds, beside a small glass dish of the oil.
Grapeseed
Avocado: a halved avocado with its stone, beside a small glass dish of the oil.
Avocado
Baobab: a cracked baobab pod showing white pulp and seeds, beside a small glass dish of the oil.
Baobab
Castor: castor beans with a dried seed capsule, beside a small glass dish of the oil.
Castor
Rosemary: two rosemary sprigs, beside a small glass dish of the oil.
Rosemary
Lavender: a small bundle of lavender stems, beside a small glass dish of the oil.
Lavender
Atlas Cedarwood: pieces of cedar wood with shavings and a cedar twig, beside a small glass dish of the oil.
Atlas Cedarwood
Sweet Orange: a halved orange with a spiral of peel, beside a small glass dish of the oil.
Sweet Orange

15

Header and footer

The header at the top of this page and the footer at its end are the real sections. Text only: navigation left, the logo in the centre, “Bag (0)” right. Below 80em the navigation is a full-screen menu, a modal dialog in the language of the oil index; a menu of more than three links takes a centred row of its own under the logo. The quiz and the builder have the same header, so the menu stays in reach mid-flow.

The rows of the full-screen menu (.ao-menu__list)

  1. Find your formula
  2. Build from scratch
  3. Account

16

Bag

The bag drawer and the bag page share their lines and their totals (snippets cart-line and cart-content, styles in ao-cart.css). A line is drawn from a real bag item, so there is no static copy here: add a blend and open the bag from the header. The quantity stepper is under “Size and quantity”, the drawn bottle under “The bottle”.

Bag line

  • .ao-cart-line · the drawn bottle at the size chosen, with the blend name on its label; the product as eyebrow, the name in the serif italic, size and prices in the mono.
  • The small Measure and the Formula line are the recipe as the order carries it. Then the stepper, “Edit blend” and a quiet “Remove”: all ink, no amber.
  • The one amber button of the bag is “Check out”, with the refund note directly above it.

Drawer

  • dialog.ao-drawer · a sheet from the bottom below 48em, a 31rem panel on the right above. It does not move under reduced motion.
  • .ao-drawer__head · title, item count and Close, set like the header's Menu and Bag.
  • .ao-drawer__body · scrolls; the refund note always sits directly above Check out.
  • .ao-cart__error · one line at the top when a change could not be saved.

Open it from the bag link in the header to see it with the bag as it is now.

Your bag

Welcome

15% off your first blend.

Join the list for formula notes and new oils. We email rarely.