# Floating Embed Forms — Exploration Notes & Lever Recipe

**Goal.** Embeddable "floating" SuiteDash forms: the form *container* is fully transparent (no card
background, border, shadow, padding, or title bar) so the fields float directly over a host website's
own design.

**Deliverables on disk** (`work/forms/`): `embed-A.png`, `embed-B.png` (transparent renders),
`embed-explore-gallery.html` (the demo — open in a browser), `embed-explore-settings.json` (live probe
of the strip-toggle ng-model keys), `embed-A.css` / `embed-B.css` (the exact minified customCSS shipped),
`embed-explore-build.json` (the build/verify log).

**Test forms (throwaway, General `co` type):**
- **EMBED TEST A — Floating Minimal:** string-id `24iZsCYiBcmcq2mBu`
- **EMBED TEST B — Frosted Panel:** string-id `2qapLbVbpds9F9fFE`
- Render URL pattern: `/frmTpl/{id}?embed=1&noSV=1&preview=1`
- Each carries the full field spectrum: short text (Full Name), email, single-select dropdown, radio
  group, a second dropdown (intended multiselect — see limitation #2), textarea, submit button, plus
  one HTML-Content intro line.

---

## 1. Confirmed native chrome-strip levers (probed live on the General kitchen-sink form `2sZsny2a2pJz98nqE`)

All six strip toggles are real `FormSetting.$*` booleans with ng-model bindings in the Style Options
panel. Set them in the same `scope.$apply` as the other tokens, then `FormSetting.save()`. Confirmed
`true` after reload on both test forms.

| ng-model key | set to | What it visually removes |
|---|---|---|
| `FormSetting.$stripTitle` | `true` | The form **title bar** (`.card-header.forms-form-header h6`). |
| `FormSetting.$stripRequiredMessage` | `true` | The "**\* indicates required**" helper line above the fields. |
| `FormSetting.$stripPadding` | `true` | The card's inner **padding** (`.card-block.forms-form-block`) — fields go edge-to-edge. |
| `FormSetting.$stripFormBackground` | `true` | The card **background fill** (`.card#forms-form-wrapper` bg → none). **The core lever.** |
| `FormSetting.$stripBorder` | `true` | The card **border + box-shadow + radius**. |
| `FormSetting.$stripScrollBar` | `true` | The embed-iframe **scrollbar**. |

Also present on the scope (read from the same probe): `FormSetting.$embedWidth`, `$embedHeight`,
`$standaloneWidth`, `$standaloneMaxWidth`, `$backgroundColor`, `$titleColor`, `$buttonBackgroundColor`,
plus all the per-element color tokens.

**Belt-and-suspenders:** even with the toggles on, the shipped customCSS still forces the container
transparent (`.card#forms-form-wrapper{background:transparent!important;border:0;box-shadow:none;
padding:0}` etc.) — see the page-wrapper reset block in §3. This guarantees the float even if a future
platform default re-paints the card.

---

## 2. Platform limitations found

1. **`header.hideWhenEmbedded` / `footer.hideWhenEmbedded` have NO UI control on these forms** — the
   live probe returned `hideWhenEmbedded ng-models: []`. The keys exist on `Form.divBlocks.{header,footer}`
   and we set them to `true` on the Form scope (harmless), but the *effective* way to hide header/footer
   content on an embed is simply to leave `divBlocks.header.content` / `footer.content` empty (which we
   do) and/or `display:none` them in customCSS. Don't rely on `hideWhenEmbedded` doing anything visible
   on a General form — it's a no-op here.
2. **Multi-select (`meta.multiple`) did not take** — the second dropdown ("Topics of interest") rendered
   as a single-select Select2 box despite setting `f.multiple` + `meta.multiple` in the Form scope. The
   `_field-spectrum.js` multiselect CSS is present and correct, but the field itself stayed single. To
   ship a true multiselect, set it via the field's own UI option (or confirm the exact `meta` key for
   "Allow multiple") — the scope shortcut isn't enough. Not blocking for the float exploration (the
   Select2 box styles identically either way).
3. **`backdrop-filter: blur()` (Variant B) only frosts over textured/photographic backgrounds.** Over
   flat white there's nothing to blur, so the frosted fill reads as a plain translucent panel. This is
   expected CSS behavior, not a bug — the frost is most valuable over photo/brand heros (see the gallery
   photo + brand rows).
4. **Transparency renders correctly.** At the embed URL, `getComputedStyle` returns
   `body / html / .card#forms-form-wrapper = rgba(0,0,0,0)`. Screenshot with
   `screenshot({ omitBackground: true })` produces a true alpha PNG (A = 95.8% transparent area,
   B = 67.4%; both corners alpha 0). No platform background bleed once the page-wrapper reset is in the
   customCSS.

---

## 3. The exact recipe

### 3a. Tokens (both variants share these; set in one `$apply`, then `FormSetting.save()`)
```js
FormSetting.$theme               = 'no_theme';   // call FormSetting.changeTheme('no_theme') FIRST (avoids save() throw)
FormSetting.$enableCustomCSS     = true;
FormSetting.$enableAnimatedLabels= false;
FormSetting.$stripTitle          = true;
FormSetting.$stripRequiredMessage= true;
FormSetting.$stripPadding        = true;
FormSetting.$stripFormBackground = true;
FormSetting.$stripBorder         = true;
FormSetting.$stripScrollBar      = true;
FormSetting.$backgroundColor     = 'rgba(0,0,0,0)';      // transparent page bg
FormSetting.$customCSS           = <minified CSS, below>;
// + the per-element color tokens to match the variant ($titleColor/$labelColor/$subtextColor/
//   $buttonBackgroundColor/$buttonTextColor/$accentColorOne/$accentColorTwo)
```
**CSS rule (applies to ALL form CSS):** double-quotes only, minified (no newlines) except the `:root`
accent vars which must each stay on their own line (the platform's greedy `replaceAccentColors` regex).

### 3b. Shared transparent-container reset (in both variants' customCSS)
```css
html.intake-form, html.intake-form body, html.intake-form .main-wrapper, html.intake-form .public-page-layout { background: transparent !important; }
html.intake-form body::before, html.intake-form .main-wrapper::before, html.intake-form .public-page-layout::before { display:none !important; background:none !important; content:"" !important; }
.app-form-embed#FormSetting-scope .card, .app-form-embed .card#forms-form-wrapper { background: transparent !important; border: 0 !important; box-shadow: none !important; border-radius: 0 !important; max-width: 560px !important; margin: 0 auto !important; }
.app-form-embed .card-block.forms-form-block { padding: 0 !important; background: transparent !important; }
.app-form-embed .card-header.forms-form-header { display: none !important; }
```

### 3c. Variant A — Floating Minimal (DARK-TEXT, for LIGHT hosts)
Underline-only inputs, uppercase micro-labels, generous spacing, ink submit pill. Color tokens:
```
INK   #16181d   (text / input value)
LABEL #33363d   (uppercase labels)
MUTED #6b7078   (placeholder / subtext / intro)
LINE  #c9cdd4   (input underline)
ACCENT#16181d   (focus underline + submit fill)
```
Key rules (full CSS in `embed-A.css`):
```css
.app-form-embed#FormSetting-scope label { font-size:11px; font-weight:600; letter-spacing:.12em; text-transform:uppercase; color:#33363d; }
.app-form-embed .form-control { background:transparent; border:0; border-bottom:1.5px solid #c9cdd4; border-radius:0; padding:8px 0; color:#16181d; font-size:16px; }
.app-form-embed .form-control:focus { border-bottom:2px solid #16181d; outline:none; }
.app-form-embed .btn.btn-primary { background:#16181d; color:#fff; border:0; border-radius:999px; padding:14px 34px; }
.app-form-embed #formFields > div.form-group { margin-bottom:26px; }   /* airy */
```
+ the `fieldSpectrum({ underline:true, radius:0, inputBg:'transparent', inputBorder:'#c9cdd4',
text:'#16181d', muted:'#6b7078', surface:'#ffffff' })` block for radio/select2/checkbox/file/date.

**Flip to WHITE-TEXT (for DARK hosts) — change ONLY the color tokens, nothing structural:**
```
INK   #f4f5f7   LABEL #e4e6ea   MUTED #aab0ba   LINE rgba(255,255,255,.34)   ACCENT #ffffff
submit: background:#ffffff; color:#16181d;   (dark text on white pill)
fieldSpectrum: text:#f4f5f7, muted:#aab0ba, inputBorder:'rgba(255,255,255,.34)', surface:'#1b1d22'
```
Everything else (underline structure, spacing, label casing) is identical. The dark cells in the
gallery show the dark-text version with a note that this flip is required.

### 3d. Variant B — Frosted Panel (works over ANY background, dark-text labels)
Transparent container; each field/intro sits on a translucent frosted fill. Color tokens:
```
INK    #13151b   LABEL #2b2e36   MUTED #5a5f69   ACCENT #2563EB / #1D4ED8
FILL   rgba(255,255,255,.66)     BORDER rgba(15,20,30,.10)
```
Key rules (full CSS in `embed-B.css`):
```css
.app-form-embed .form-control { background:rgba(255,255,255,.66); backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px); border:1px solid rgba(15,20,30,.10); border-radius:12px; padding:12px 14px; color:#13151b; box-shadow:0 1px 2px rgba(15,20,30,.04); }
.app-form-embed .form-control:focus { border-color:#2563EB; box-shadow:0 0 0 3px rgba(37,99,235,.16); outline:none; }
.app-form-embed#FormSetting-scope .div-block { background:rgba(255,255,255,.66); backdrop-filter:blur(8px); border:1px solid rgba(15,20,30,.10); border-radius:12px; padding:14px 16px; }  /* intro chip frosts too */
.app-form-embed .btn.btn-primary { background:#2563EB; color:#fff; border-radius:12px; padding:14px 30px; }
.app-form-embed #formFields > div.form-group { margin-bottom:14px; }  /* tighter — fields are chips */
```
+ the `fieldSpectrum({ underline:false, radius:12, inputBg:'rgba(255,255,255,.66)',
inputBorder:'rgba(15,20,30,.10)', text:'#13151b', muted:'#5a5f69', surface:'rgba(255,255,255,.92)' })`
block. For a **dark frosted** variant (white-on-dark hosts), swap FILL→`rgba(20,22,30,.55)`,
BORDER→`rgba(255,255,255,.14)`, INK→`#f4f5f7`, LABEL→`#dfe2e8`, MUTED→`#aab0ba`.

### 3e. Embed width behavior
`$embedWidth` / `$embedHeight` (and `$standaloneWidth` / `$standaloneMaxWidth`) exist on the scope and
control the iframe sizing. We left them at defaults and instead constrained the form with
`.card#forms-form-wrapper{max-width:560px;margin:0 auto}` in customCSS, which is the more portable lever
(the host iframe can be any width; the form self-centers up to 560px). For an edge-to-edge float in a
narrow host column, set `max-width:100%` instead. Set `$embedWidth` only if you want the platform to
hard-pin the iframe width.

---

## 4. Recommendation

**Ship Variant B (Frosted Panel) as the primary "floating" template**, with Variant A (Floating
Minimal) offered as the light-host minimalist option. B is the broadly-useful default because its
translucent frosted fills stay legible over *any* host background — flat, dark, saturated brand color,
or a photographic hero — without the embedder having to know their background tone, whereas A's
underline-only fields demand a known light (or, after the one-line token flip, known dark) background
and become invisible on the wrong one. For maximum coverage, package B as the universal float and A as
the "light-minimal" variant with the documented `#fff` color-token flip for dark hosts; the transparent
container, all six strip toggles, and the field-spectrum CSS are identical across all of them, so it's
one engine with three palette presets.

---

# v2 — 3 new art directions + 2 optical-polish rules (2026-06-14)

Second pass: kept + re-polished A/B, added **C Glass / D Bold Outline / E Floating Label**, and applied
two optical-polish rules to ALL five. Same engine (transparent container + 6 strip toggles + field
spectrum). Demo: `embed-explore-gallery.html` (now 5 variants × 4 backgrounds: white / dark / saturated
brand / photo hero). Build script: `embed-explore2.js` (`--create` then `--style`; `--style-ce` for the
C/E fixes). Render: `embed-render2.js` + `embed-render-ce.js`.

**New throwaway General (`co`) test forms:**
- **C — Glass:** `25po14RyWs6gJTcCG`
- **D — Bold Outline:** `wwH6ScWzNfQpLXWX`
- **E — Floating Label:** `z8FEBsvqk9cBajKE`
- (A `24iZsCYiBcmcq2mBu`, B `2qapLbVbpds9F9fFE` re-styled in place.)

All five: `save()` → `saveErr: null`, customCSS persists after reload (cssLen A 12367 / B 12707 /
C 13097 / D 12491 / E 13764), all six strip toggles `true`, all render true-alpha (`rgba(0,0,0,0)` on
body + card; `screenshot({ omitBackground:true })`).

---

## THE TWO POLISH RULES (applied to all variants)

Implemented as a single parameterized block `polishRules(inset)` appended to every variant's CSS.
`inset` = the chosen label left-inset px, tuned per variant so the label text-start nests just INSIDE
the field's rounded corner (never overhanging the radius):

| Variant | radius | label inset (`inset`) |
|---|---|---|
| A Floating Minimal | 0 (underline) | **3px** |
| B Frosted Panel | 12px | **6px** |
| C Glass | 16px | **7px** |
| D Bold Outline | 12px | **6px** |
| E Floating Label | 12px | **6px** |

**Rule 1 — single left content line (labels/inputs/selects nest inside the radius):**
```css
.app-form-embed#FormSetting-scope label { padding-left: ${inset}px !important; }
.app-form-embed#FormSetting-scope .label-subtext, .app-form-embed#FormSetting-scope .form-group .label-subtext { padding-left: ${inset}px !important; }
```
Inputs keep their OWN horizontal padding (A pad 8px 2px; B/E pad 12-13px 14px; C 13px 16px; D 0 16px).
The small label inset makes the label text-start sit a hair right of the rounded corner's visual edge —
optically aligned with (or just left of) the input's text-start, but never overhanging the radius.

**Rule 2 — inset radio/checkbox groups + multi-select to the same line:**
```css
.app-form-embed#FormSetting-scope .radiobox, .app-form-embed#FormSetting-scope .checkbox { padding-left: ${inset}px !important; }
.app-form-embed#FormSetting-scope .radiobox label, .app-form-embed#FormSetting-scope .checkbox label { padding-left: 0 !important; }
.app-form-embed#FormSetting-scope .radiobox span.label-text, .app-form-embed#FormSetting-scope .checkbox span.label-text { padding-left: 28px !important; }   /* fixed ring->label gap */
.app-form-embed#FormSetting-scope .radiobox span.label-text:before, .app-form-embed#FormSetting-scope .radiobox span.label-text:after, .app-form-embed#FormSetting-scope .checkbox span.label-text:after { left: 0 !important; }
```
The ring (`span.label-text:before/:after`) is pinned to `left: 0` of the group, which now starts at the
content line via the group's `padding-left: ${inset}`. The label text keeps a consistent 28px gap from
the ring. Multi-select placeholder/chips already begin on the line (the Select2 box has its own
radius+padding, nothing overhangs).

**VERIFIED:** `embed-polish-check.png` (crop of B over a flat surface) — every label, the select
prompt, and the radio rings begin on one left content line that sits inside the rounded corners; the
rings do not overhang. Looks intentional, not jagged. D's bold rings make this especially clear
(`embed-D.png`).

---

## C — Glass (premium glassmorphism). customCSS in `embed-C.css`. Tokens:
```
INK #10121a  LABEL #252834  MUTED #5b606e  ACCENT #4f46e5 / #4338ca
FILL rgba(255,255,255,0.55)   FIELD-BORDER rgba(255,255,255,0.6)  (bright glass edge highlight)
RING/CONTROL-BORDER rgba(80,70,120,0.30)  (faint neutral so radio rings / Select2 box survive over WHITE too)
GLASS SHADOW = inset 0 1px 0 rgba(255,255,255,.6), 0 10px 34px rgba(0,0,0,.14)
```
Key rules:
```css
.app-form-embed .form-control { background: rgba(255,255,255,0.55) !important; -webkit-backdrop-filter: blur(16px) saturate(1.25) !important; backdrop-filter: blur(16px) saturate(1.25) !important; border: 1px solid rgba(255,255,255,0.6) !important; border-radius: 16px !important; padding: 13px 16px !important; color: #10121a !important; box-shadow: inset 0 1px 0 rgba(255,255,255,.6), 0 10px 34px rgba(0,0,0,.14) !important; }
.app-form-embed .form-control:focus { border-color: rgba(255,255,255,.85) !important; box-shadow: inset 0 1px 0 rgba(255,255,255,.7), 0 0 0 4px color-mix(in srgb, #4f46e5 22%, transparent), 0 12px 36px rgba(0,0,0,.16) !important; outline: none !important; }
.app-form-embed .btn.btn-primary { background: #4f46e5 !important; border-radius: 14px !important; box-shadow: inset 0 1px 0 rgba(255,255,255,.28), 0 12px 30px -10px color-mix(in srgb, #4f46e5 60%, transparent) !important; }
```
The intro `.div-block` ALSO gets the glass treatment. Field-spectrum passes `inputBorder = RING/CONTROL-BORDER`
(the tinted neutral) so radio rings + Select2 box stay visible over white; the bright `rgba(255,255,255,.6)`
edge highlight is reserved for the main `.form-control` fills. Best over photo/saturated color (where the
blur+saturate actually engages); fully usable over white too after the ring-border fix.

**Dark-glass flip (for dark hosts) — change only the tokens, not the structure:**
```
FILL rgba(18,18,24,0.45)   INK #f4f5f7   LABEL #e7e9ef   MUTED #aab0ba
FIELD-BORDER rgba(255,255,255,0.16)   RING/CONTROL-BORDER rgba(255,255,255,0.28)
GLASS SHADOW = inset 0 1px 0 rgba(255,255,255,.18), 0 10px 34px rgba(0,0,0,.4)
```
Keep blur(16px) saturate(1.25), the 16px radius, and the indigo accent.

---

## D — Bold Outline (Linear/Figma crisp). customCSS in `embed-D.css`. Tokens:
```
INK #0e1116  LABEL #3a3f4a  MUTED #737a86  ACCENT #4338ca / #3730a3  LINE #1d2128 (1.5px ink border)
```
Key rules:
```css
.app-form-embed .form-control { background: transparent !important; border: 1.5px solid #1d2128 !important; border-radius: 12px !important; padding: 0 16px !important; height: 50px !important; color: #0e1116 !important; }
.app-form-embed textarea.form-control { height: auto !important; min-height: 110px !important; padding: 14px 16px !important; }
.app-form-embed .form-control:focus { border-color: #4338ca !important; box-shadow: 0 0 0 4px color-mix(in srgb, #4338ca 18%, transparent) !important; outline: none !important; }
.app-form-embed#FormSetting-scope label { font-size: 11px !important; font-weight: 600 !important; letter-spacing: .08em !important; text-transform: uppercase !important; color: #3a3f4a !important; }
.select2-container--default .select2-selection--single { min-height: 50px !important; border-width: 1.5px !important; border-color: #1d2128 !important; }
```
Big soft focus ring + 50px field height + uppercase letter-spaced labels = the most modern, confident
read. Bold ink rings make the radio inset crystal clear. **Dark-host flip:** border → rgba(255,255,255,.22),
INK #f1f2f5, labels light; accent stays indigo.

---

## E — Floating Label (CSS-only). customCSS in `embed-E.css`. Tokens:
```
INK #14151b  REST-LABEL #a2a8b2 (faux placeholder)  FLOATED-LABEL #0c8b8a  MUTED #a2a8b2
ACCENT #0ea5a4 / #0c8b8a  FILL rgba(255,255,255,.78)  BORDER rgba(20,24,32,.16)
```

### `$enableAnimatedLabels` did NOT work natively — CSS-only fallback shipped.
Setting `FormSetting.$enableAnimatedLabels = true` **persists** in form settings (verified `true` after
reload) BUT the public embed render never wraps fields in `.form-group.animated-form-label` — a live DOM
probe returned `hasAnimatedWrapper: false` and focusing+typing added no `.active` class. So native
animated labels are a **no-op on these General `co` embed forms**. We keep the token on (harmless, future-
proof) and ship a **CSS-only floating label** instead.

Rendered structure (probed): `.form-group.embed-group > label > .label-subtext > input.form-control`
(label is a sibling BEFORE the input, input has a `placeholder` attr). The CSS-only float (uses `:has()`,
which works in the Chromium embed):
```css
/* float ONLY on single-line text/email groups (those with a direct .form-control input) */
.app-form-embed#FormSetting-scope .form-group.embed-group:has(> input.form-control) { position: relative !important; }
/* REST: label overlays the field like a placeholder; hide the native placeholder so it does not double up */
.app-form-embed#FormSetting-scope .form-group.embed-group:has(> input.form-control) > label { position: absolute !important; top: 14px !important; left: 16px !important; padding: 0 5px !important; pointer-events: none !important; font-size: 15px !important; font-weight: 400 !important; color: #a2a8b2 !important; z-index: 2 !important; }
.app-form-embed#FormSetting-scope .form-group.embed-group:has(> input.form-control) > input.form-control::placeholder { color: transparent !important; }
/* FLOAT UP on focus OR when filled */
.app-form-embed#FormSetting-scope .form-group.embed-group:has(> input.form-control:focus) > label,
.app-form-embed#FormSetting-scope .form-group.embed-group:has(> input.form-control:not(:placeholder-shown)) > label { top: -8px !important; left: 12px !important; font-size: 11px !important; font-weight: 600 !important; letter-spacing: .04em !important; color: #0c8b8a !important; background: #ffffff !important; }
/* reveal the real placeholder only while focused */
.app-form-embed#FormSetting-scope .form-group.embed-group:has(> input.form-control:focus) > input.form-control::placeholder { color: #a2a8b2 !important; opacity: .65 !important; }
.app-form-embed .label-subtext { display: none !important; }
```
Select2 / radio / textarea fall back to a normal small static label (the float targets only groups that
directly contain `input.form-control`). **PROVEN:** `embed-E-label-rest.png` (labels inside fields) vs
`embed-E-label-active.png` (labels floated to top border on filled "Jane Cooper" + focused empty field);
computed `label top` goes 14px → -8px and font 15px → 11px. Gallery has both shots.

---

## A & B re-polish (color tokens unchanged; only the polish rules + a 2px input pad added)
- **A:** added the polish block (inset 3); input padding `8px 0` → `8px 2px` so the value/placeholder
  clears the label's content line. White-text flip for dark hosts unchanged (INK #f4f5f7, underline
  rgba(255,255,255,.34), white submit pill w/ dark text).
- **B:** added the polish block (inset 6). Dark-frosted flip unchanged (FILL rgba(20,22,30,.55),
  BORDER rgba(255,255,255,.14), INK #f4f5f7).

---

## v2 recommendation
**D (Bold Outline) is the most modern, broadly-useful default** — crisp, confident, legible on any
light/medium host without depending on a blurred backdrop, and the big soft focus ring reads as
genuinely contemporary (Linear/Figma). **C (Glass) is the standout over photography or saturated brand
color**, where blur(16px) saturate(1.25) actually engages and the inset highlight gives real depth. A is
the minimalist/typographic pick, B the universal frosted fallback, E the compact floating-label novelty.
All share one engine; each is a token/CSS preset.

**Platform limitations carried/found in v2:**
- `$enableAnimatedLabels` is a no-op on General `co` embed forms (persists, never renders the wrapper) →
  use the CSS-only `:has()` floating label (E).
- `backdrop-filter` only frosts over textured/photo backgrounds (B, C, E) — over flat white the
  translucent fill is just a plain panel (expected CSS behavior; most valuable over photo/brand heros).
- The intro HTML `.div-block` for B/C carries the frosted/glass chip; over flat white it reads as a plain
  tint (same blur caveat).

---

# NO-THEME CONTRACT — customCSS = STRUCTURE / native = COLOR (2026-06-14)

**Why.** The A–E embed variants hardcoded every color in customCSS with `!important`, which would
override a customer's native color controls. New contract: build on `no_theme` so the **native
granular FormSetting color tokens own all customer-facing color**, and **customCSS owns only
structure/effect** (transparent container, fill geometry/opacity, blur, radius, border thickness,
label/radio insets, focus-ring shape, type scale). Proven on D (Bold Outline), form `wwH6ScWzNfQpLXWX`.

## Precedence probe — VERDICT (the crux)
Set native tokens to unmistakable test colors ($labelColor #fff, $buttonBackgroundColor #ff0000,
$buttonTextColor #fff, $titleColor #00ff00, $subtextColor #ff00ff, $accentColorOne #00e5ff) on
`no_theme`, applied a customCSS that declared **zero color** on label/.form-control(text)/button,
saved, rendered the embed, read `getComputedStyle`. Result file: `embed-noTheme-precedence.json`;
the platform-generated style block dumped to `notheme-generated-style.css`.

- **(a) Do native granular tokens RENDER on the no_theme embed? YES.** The platform emits a generated
  `<style>` block (the one carrying our test colors) with low-specificity, **non-`!important`** rules:
  - `$labelColor`  → `.app-form-embed#FormSetting-scope label { color: <v>; }` (also `.success-message`)
  - `$subtextColor`→ `.app-form-embed#FormSetting-scope .label-subtext { color: <v>; }` (+ ` *`)
  - `$buttonBackgroundColor`/`$buttonTextColor` → `.app-form-embed#FormSetting-scope .btn.btn-primary { background-color: <bg>; color: <txt>; }` (hover auto-derives a tint)
  - `$titleColor` → drives the form `h6` title (computed green when title not stripped)
  - probe computed: label=white, submit bg=red, submit text=white, subtext=magenta, title=green. ✅
- **(b) Do they WIN when customCSS omits that color? YES.** Two reasons: the native rules render at all
  (above), AND our customCSS simply doesn't compete (it declares no color on those selectors). Note the
  native rules are NOT `!important` and specificity is `(0,2,0)` — so if customCSS *did* declare a color
  with `!important` it would WIN. The contract therefore is strictly "omit color in CSS for any element
  whose color you want native-controlled."
- **(c) Is the accent ($accentColorOne) referenceable from customCSS? NO.** `#00e5ff` appears NOWHERE
  in the rendered embed — not as a rule, not as a CSS custom property (`allRootVars` matching the test
  accent = `{}`; no `--frm-*`/`--accent*` carries it). The accent tokens only feed Booking/Checkout
  "choice-step" + book-me chrome via inline interpolation (often emitted empty on a field form).
  **=> accent MUST stay a hardcoded CSS line.**

## Native token ng-model keys (confirmed live on the FormSetting scope, no_theme)
| ng-model key | controls | native-controllable? |
|---|---|---|
| `$titleColor` | form title (h6) | ✅ (when not stripped) |
| `$labelColor` | every field **label** | ✅ |
| `$subtextColor` | the **.label-subtext** helper line | ✅ |
| `$buttonBackgroundColor` | **submit** button fill | ✅ |
| `$buttonTextColor` | **submit** button text | ✅ |
| `$accentColorOne` / `$accentColorTwo` | book-me/choice-step chrome only | ⚠️ present but **NOT emitted as form CSS / no CSS var** → keep accent in CSS |
| `$backgroundColor` | page bg (we set `rgba(0,0,0,0)`) | ✅ |
| `$inputTextColor` / `$textColor` / `$generalTextColor` / `$placeholderColor` | — | ❌ **ABSENT** (no token) |

## The rule
- **customCSS declares NO color** on: title / label / subtext / submit-bg / submit-text → native wins.
- **customCSS owns ONLY** (D's `embed-D-contract.css`): transparent-container reset, input geometry
  (transparent fill, 1.5px border, 12px radius, 50px height, padding), label+radio INSET polish
  (inset 6 — content line inside the radius), type scale/weight/letter-spacing/spacing, focus-ring
  SHAPE — plus exactly **three documented color vars at the top of `:root`** for the colors the
  platform has no native token for:
  - `--embed-accent` — focus-ring tint + resting-border-on-focus + required asterisk + radio/checkbox/
    Select2 accent + file-drop/datepicker accent + outline button. (accent is NOT referenceable → CSS.)
  - `--embed-border` — resting input border color.
  - `--embed-ink` — input **value** text + placeholder + Select2 rendered text (no `$inputTextColor`).
  Keep the `:root` block's `--frm-color-primary/secondary` too (the field-spectrum + select2/radio
  rules reference them; the platform's greedy `replaceAccentColors` matches that single `:root`).

## Accent handling
Accent stays a single CSS line via `--embed-accent` (default = brand indigo `#4338ca`). It cannot be
native-driven because the platform neither emits accent CSS nor exposes it as a custom property on the
embed. A customer who wants a different accent edits that ONE documented var (or we ship per-brand var
presets); it does not block the light↔dark color flip, which is fully native.

## What MUST remain in CSS (platform limitation to flag)
- **accent** (border-focus, focus ring, asterisk, control accents) — no native token, not referenceable.
- **resting input border** — no native token (`--embed-border`).
- **input value text + placeholder** — no native `$inputTextColor`/`$textColor`. So for a *true dark
  host*, the one CSS line `--embed-ink` must flip dark→light or typed text is unreadable. Everything
  else (title/label/subtext/button) flips purely via native fields.

## Proof — D recolored light↔dark via NATIVE FIELDS ONLY (no CSS edit)
Script `embed-D-contract.js` applied D's contract customCSS once, then saved LIGHT native tokens →
render, then changed **only** native tokens to DARK and saved (customCSS byte-identical, cssLen 12,441
both saves — `embed-D-contract-result.json` `cssIdenticalAcrossFlips: true`) → render.
- LIGHT computed: label `rgb(58,63,74)`, submit bg `rgb(29,33,40)`, submit text white. (`embed-D-light.png`, alpha 560×837)
- DARK computed: label `rgb(255,255,255)`, submit bg white, submit text `rgb(17,17,17)`. (`embed-D-dark.png`, alpha 560×837)
- input text stayed `rgb(14,17,22)` in both → confirms the input-text gap above (it's `--embed-ink` in CSS).
Gallery: `embed-notheme-proof.html` (D-light over a light host bg, D-dark over a dark host bg, side by
side; geometry + insets identical in both). Files: `embed-D-contract.css` (the structure-only CSS),
`embed-D-contract.js` (builder), `embed-notheme-probe.js` + `dump-notheme-style.js` (the probes).

## Recommendation
**"customCSS = structure / native = color" is VIABLE and should be the shipping contract.** Five of the
six customer-facing colors (title, label, subtext, button bg, button text) are fully native-controllable
on `no_theme` embeds and a customer flips a host light↔dark by editing those native color fields with
zero CSS knowledge. The remainder — accent, resting border, and input-value text — have no native token
and stay as three clearly-commented `--embed-*` vars at the top of customCSS (one-line edits, documented).
Apply the same rebuild to A/B/C/E (strip their hardcoded title/label/subtext/button colors; keep
geometry + the three `--embed-*` vars).
