Rulebook 1.0.0
Every number, and the rule that produced it.
Atmosphere OS is not generative. The same inputs produce the same brief every time, which is what makes a brief safe to send to a florist who is going to quote against it. That is a claim, and a claim nobody can check is a slogan — so here is the whole thing, with the arithmetic and the standards it rests on.
20
computed rules
2
stated positions
5
judgements, kept out
Three kinds of number, kept apart
Calling everything a rule would be the fastest way to lose this argument. The first person to ask why a weight is 0.26 would decide the rest of the book is the same, and they would be wrong — but that is the inference they would draw. So:
- Computed
- Arithmetic, geometry, or a named external standard. Ohm's law, CIEDE2000, WCAG, the critical path method, an M/M/c queue. Check them against a textbook rather than against us. 19 of the 22 rules here name an outside authority.
- Stated positions
- Deterministic in the code, but the constant is a judgement rather than a fact — 0.65 m a cover, 2.5 minutes of service per course per table. Published with the number and the reasoning so you can disagree with them precisely.
- Judgements
- Taste. The energy curve, the fit scores, the readiness rubrics. Deliberately not in this book, and listed at the bottom so you can see exactly what we are keeping out of it.
Power
Amps from declared draw
POWER-AMPS-01Computed
Add the watts of everything that declared a wattage, then divide by the supply voltage.
totalWatts = SUM (wattsEach x qty) · amps = totalWatts / volts- Needs
- Per-line watts · Per-line quantity · Supply voltage
- Where you meet it
- Vendor Pack · Pull list & power · Lighting role sheet
- Basis
- Ohm's law. Nothing here is ours.
- What it does not claim
- Voltage defaults to 120V when undeclared, and the output says so. On a 230V supply an undeclared figure is wrong by roughly half.
src/lib/vendor-pack/equipment.ts
Continuous-load headroom
POWER-DERATE-01Computed
Never plan a circuit above 80% of its rating, so the working figure is the amps divided by 0.8.
ampsWithHeadroom = amps / 0.8- Needs
- Amps from POWER-AMPS-01
- Where you meet it
- Vendor Pack · Pull list & power
- Basis
- NEC 210.19(A) and 210.20(A): a branch circuit serving a continuous load is sized at 125% of that load, which is the same thing as planning to 80% of the rating. IEC practice is equivalent.
src/lib/vendor-pack/equipment.ts
Circuits needed
POWER-CIRCUIT-01Computed
Take the derated amps, divide by the amps on one circuit, round up.
circuits = ceil(ampsWithHeadroom / ampsPerCircuit)- Needs
- Derated amps · Amps per circuit at the venue
- Where you meet it
- Vendor Pack · Pull list & power
- Basis
- Division. Ceiling because a circuit is not divisible.
src/lib/vendor-pack/equipment.ts
Supply verdict
POWER-MARGIN-01Computed
The building's declared capacity minus what you are planning to pull. A negative number blocks the pack from being sent.
supplyAmps = circuits x ampsPerCircuit · margin = supplyAmps - ampsWithHeadroom · over when margin < 0- Needs
- Declared circuits · Amps per circuit · Derated amps
- Where you meet it
- Vendor Pack · Pull list & power · Vendor Pack · Still undeclared
- Basis
- Subtraction. The verdict is the sign of the result.
src/lib/vendor-pack/equipment.ts
A declared total is a floor
POWER-FLOOR-01Computed
Items that declare no draw are counted and named, never guessed at. Where a derived pull list supplies a planning figure before a unit has been chosen, that line is marked assumed, kept out of the declared total, and reported separately.
declaredWatts = SUM over lines with a typed wattage · assumedWatts = SUM over lines carrying a planning figure · working total = declared + assumed- Needs
- Which lines declared a draw · Which lines carry an assumed draw
- Where you meet it
- Vendor Pack · Pull list & power · Every role sheet
- Our position
- A policy rather than a calculation, and the one this whole rulebook rests on: no line is ever silently given a typical wattage.
- What it does not claim
- The working total is still short by whatever the undeclared lines pull. The pack says how many those are.
src/lib/vendor-pack/equipment.ts
Light
Beam coverage at a distance
LIGHT-BEAM-01Computed
How wide the pool of light is by the time it reaches the table.
d = 2 x throw x tan(beamAngle / 2)- Needs
- Throw distance · Beam angle
- Where you meet it
- Vendor Pack · derived lighting · Room elevation
- Basis
- Trigonometry of a cone.
src/lib/spatial/room.ts
Hotspot is not average illuminance
LIGHT-LUX-01Computed
A pin spot is very bright inside its pool and much dimmer averaged across the whole table. Quoting the hotspot as 'light on the table' is how you get a glowing centrepiece and an unreadable menu.
centreLux = lumens / poolArea · averageLux = (lumens / max(poolArea, tableArea)) + (12 x candles / tableArea)- Needs
- Fixture lumens · Beam pool area · Table area · Candle count
- Where you meet it
- Vendor Pack · derived lighting · Room elevation
- Basis
- Illuminance over a lit area. The distinction between the two figures is the rule; the arithmetic is division.
- What it does not claim
- A planning approximation. It ignores reflectance, beam overlap and fixture efficiency, and reads optimistic in a dark room with dark walls.
src/lib/spatial/room.ts
Room
Seats from table perimeter
SEAT-COVER-01Stated position
A 1.8 m round seats eight, not ten. Ten is the banqueting squeeze, and you can declare it - but you have to declare it.
perimeter = pi*d (round) | 4s (square) | 2s (long, ends left for service) · seats = max(2, floor(perimeter / 0.65))- Needs
- Table shape · Table size
- Where you meet it
- Every module that counts tables
- Our position
- Our position: 0.65 m is the elbow-to-elbow width one diner needs to eat without apologising. Below about 0.60 m people knock each other's glasses. Hotel banqueting will plan to 0.55 m and the room feels it all night.
src/lib/spatial/seating.ts
One table count for the whole plan
SEAT-TABLES-01Computed
Linen, covers, centrepieces, pin spots, stem counts and the service pass all count the same tables. They used to disagree.
tables = ceil(guests / seatsPerTable), where seatsPerTable is declared, or SEAT-COVER-01, in that order- Needs
- Guest count · Declared table count or seat count · Table geometry
- Where you meet it
- Floral · Arc Studio · Vendor Pack · Room elevation
- Basis
- Ceiling, because a fractional table does not exist. Precedence, because a declared number always beats a derived one.
src/lib/spatial/seating.ts
The centrepiece dead zone
ROOM-SIGHT-01Computed
On a 0.75 m table, keep a centrepiece under 28 cm or over 92 cm. Between those two numbers it sits exactly where a face should be.
maxLow = seatedEye - tableHeight - 0.06 · minTall = standingEye - tableHeight + 0.05- Needs
- Table height · Seated eye height · Standing eye height
- Where you meet it
- Floral brief · Room elevation · Moodboard proportions
- Basis
- Anthropometry for a mixed adult population: seated eye 1.09-1.29 m, standing eye 1.62 m. The 0.06 m margin allows for slouch, cushions and a raised chair.
- What it does not claim
- Averages. A real room contains people well outside them, which is why the output carries a range rather than one number.
src/lib/spatial/room.ts
Guest flow
Queue wait at a service point
GJP-QUEUE-01Computed
How long the bar queue actually gets, given how many people want a drink and how fast the bar pours.
rho = lambda / (c*mu) · Wq ~= rho^(sqrt(2(c+1)) - 1) / (c*mu*(1 - rho))- Needs
- Arrival rate · Service rate · Number of servers
- Where you meet it
- Guest Journey · capacity
- Basis
- The Sakasegawa approximation for an M/M/c queue. A published, checkable result, named in the source.
- What it does not claim
- Above rho = 1 there is no steady state, so the model stops estimating a wait and reports the backlog accumulating over the declared window instead.
src/lib/gjp/capacity.ts
Clear exit width per person
EGRESS-WIDTH-01Computed
Four hundred guests need at least two metres of clear exit width, and it has to stay clear all night.
egressM = max(1.1, guests x 0.005)- Needs
- Guest count
- Where you meet it
- Moodboard · proportions · Guest Journey
- Basis
- 5 mm of clear exit width per person is the long-standing building-code convention - IBC 1005 in the US, Approved Document B in England and Wales.
- What it does not claim
- An order-of-magnitude check, not a code sign-off. Occupancy classification, travel distance and door swing all change the real answer, and only the authority having jurisdiction can give it.
src/lib/moodboard/tablescape.ts
Timing
Meal service window
SERVICE-PASS-01Stated position
A forty-person dinner and a four-hundred-person gala do not take the same time to serve. This is why.
teams = clamp(round(tables / 3), 1, 12) · passMinutes = round(2.5 x tables / teams) · window = SUM (pass + dwell + clear) per course- Needs
- Guest count · Seats per table · Service style · Course count
- Where you meet it
- Arc Studio · act maths · Run sheet
- Our position
- Our position: roughly 2.5 minutes of service per course per table, and one service team covers about three tables before the pass stops being one pass.
src/lib/arc/acts.ts
Critical path through the build
PROD-CPM-01Computed
Which load-in tasks have no room to slip. If one of these runs late, doors run late.
Forward pass for earliest start and finish; backward pass for latest; slack = LS - ES; a task is critical when slack <= 0- Needs
- Task durations · Declared dependencies · Phase order
- Where you meet it
- Vendor Pack · production schedule · Derived constraints
- Basis
- The critical path method, unmodified. Dependency ordering uses Kahn's algorithm, and a cycle is reported rather than silently dropped.
src/lib/vendor-pack/production.ts
Does the build fit before doors
PROD-WINDOW-01Computed
You have this many minutes between the door being unlocked and the first guest arriving. Here is whether your build fits inside them.
window = (doorsClock - startClock + 1440) mod 1440 · critical when loadInEnd > window- Needs
- Access time · Doors time · Critical path length
- Where you meet it
- Vendor Pack · production schedule
- Basis
- Clock arithmetic, with the shortfall quoted in minutes.
src/lib/vendor-pack/production.ts
Floral
Blocked stems and substitution
FLORAL-GATE-01Computed
If you said no scent, nothing scented reaches the brief, and the substitute offered has been through the same gates rather than picked for looking similar.
A stem passes when it clears every declared gate: season legality, allergy, scent, exposure, foam policy and water. A substitute must clear every gate the original failed.- Needs
- Season · Declared constraints · Water availability · Stem catalogue
- Where you meet it
- Floral Direction · blocked stems
- Basis
- A decision procedure over a declared catalogue. No scoring, no preference, no tie-breaking - a stem is either legal against your constraints or it is not.
src/lib/floral/volume.ts
Money
Diminishing return above a threshold
BUD-EFFECT-01Computed
The first money into a category buys the thing existing at all. After that each extra pound buys less, and how much less depends on how many guests you are covering.
effect = 0 when spend <= fixed; otherwise (spend - fixed) / ((spend - fixed) + perGuest x guests)- Needs
- Spend in a category · That category's fixed cost · Per-guest cost · Guest count
- Where you meet it
- Budget-to-Atmosphere · sensitivity · Decision brief
- Basis
- A saturating curve. Marginal return is strictly decreasing above the threshold, and the curve moves with guest count rather than staying fixed.
- What it does not claim
- The fixed and per-guest figures are indicative planning bands for a mid-market metro, priced as of 2026. They are comparison controls, never quotes.
src/lib/budget/costModel.ts
Distributing the envelope
BUD-ALLOC-01Computed
Money moves to protect the categories that break the event when starved, and if the budget genuinely cannot cover them the plan says so instead of pretending.
1. spread the free envelope by scenario weight · 2. repair any category below its floor by taking proportionally from donors above theirs · 3. rounding residual lands in reserve- Needs
- Total budget · Scenario weights · Category floors · Guest count
- Where you meet it
- Budget-to-Atmosphere · Decision brief
- Basis
- A three-pass procedure. A floor that cannot be met is reported as a shortfall rather than silently guaranteed.
src/lib/budget/evaluate.ts
Paperwork
Certificate gaps
PAPER-COI-01Computed
Every vendor needs a certificate on file, naming a carrier, naming you as additional insured, expiring after your date.
Five tests per vendor: received · names a carrier · names the host as additional insured · declares an expiry · expiry after the event date- Needs
- Certificate records · Event date
- Where you meet it
- Vendor Pack · insurance · Vendor library alerts
- Basis
- Presence checks and one date comparison. No thresholds to argue with.
- What it does not claim
- This tracks what you recorded. It does not verify cover, contact an insurer, or make a statement about anyone's compliance.
src/lib/vendor-pack/paperwork.ts
Colour
Perceptual colour difference
COLOR-DE2000-01Computed
Two swatches under about 2.3 are a just-noticeable difference. Under about 5, a client will not reliably tell them apart across a dim room.
dE2000 over CIELAB, with kL = kC = kH = 1- Needs
- Two colours · Illuminant
- Where you meet it
- Theme Atelier · palette · Floral palette read
- Basis
- CIEDE2000, the CIE standard colour-difference formula. Implemented in full.
src/lib/color/index.ts
Contrast ratio
COLOR-WCAG-01Computed
Whether the menu card can be read by the person holding it, rather than by the designer who made it on a bright screen.
(L1 + 0.05) / (L2 + 0.05), where L is relative luminance- Needs
- Foreground colour · Background colour
- Where you meet it
- Theme Atelier · palette · Stationery notes
- Basis
- WCAG 2.x. AAA at 7:1, AA at 4.5:1, AA Large at 3:1.
src/lib/color/index.ts
Correlated colour temperature
COLOR-CCT-01Computed
What colour the light actually is, so a palette can be judged under candlelight at 2200 K rather than under a studio lamp.
Cubic approximation of the Planckian locus, valid 1667 K to 25000 K- Needs
- Chromaticity coordinates
- Where you meet it
- Theme Atelier · palette under light
- Basis
- The Kim et al. approximation, with its published coefficients and its stated validity range.
src/lib/color/index.ts
What is deliberately not a rule
These are ours, we stand behind them, and they do real work. They are not measurements, and publishing them as rules would make every rule above look like one too.
The energy curve and The Turn
Five intensity weights and around 120 authored role-profile numbers produce the curve, its peak, its flat middles and its faults.
The procedure that finds the sharpest change in the curve is defensible. The curve it runs on is a point of view about how evenings feel. It is ours, we stand behind it, and it is not a measurement.
Scenario fit scores
A weighted blend of goal impact, carrier coverage and band fit, minus risk penalties.
It ranks options usefully and it is legible on screen. As a published rule it would present an editorial ranking as a 0-100 measurement, which it is not.
Guest-journey and readiness rubrics
Criteria scored out of two, weighted by context, banded into ready, caution and not ready.
Professional opinion in numeric costume. Useful for structuring a walkthrough, wrong to cite as a finding.
Stem ranking
A points table that scores season, tier, palette proximity, vase life, hardiness and allergy.
Every number in it is a preference. The gate that blocks a stem is a rule (FLORAL-GATE-01); the order the survivors appear in is taste.
Moodboard confidence
A percentage assembled from brief specificity, context depth, tension load and named limits.
There is no model behind a number like that.
Corrections
A rule that is wrong is wrong the same way every time, at scale — which is the cost of being deterministic, and the reason this page exists rather than a marketing sentence about it. When a number changes, the version changes with it and the reason is published. If something here does not match what you know from a real load-in, tell us: hello@tangledthistle.blog.
Rulebook 1.0.0 · published 2026-09-02 · 22 rules