You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/src/uix/eidos/components/dialog/dialog.css

449 lines
15 KiB

sema/morfo/eidos: typed selector builder + dialog wrapper + emerge color sema architecture - sema-map: 5-channel registry (motion / sound / color / presence / haptic) via SemaChannelSignatures declaration merging; engine stamps data-event-* tokens; flat CSS-style cascade replaces the eventLabel-overrides middle layer. - sema-map: emerge family gains base.color so intent deltas can shift hue / saturation / intensity. Without a base, the resolver was skipping the channel and Dialog open with intent='threat' rendered as neutral blue in the Sema tab visualisation. - types: SEMA_FAMILY_POLICY const drives compile-time + runtime intent requirements per family. Object shape so future per-family policy fields fit alongside. Emerge events MAY now declare intent (canon update — a Dialog confirming threat carries it in its very appearance). - chans: rename vibra→haptic, add HapticChannel V1 (Vibration API); SoundChannel eager-init on first user gesture (autoplay race fix). morfo selector discipline - morfo/selectors.ts (new): semaSelector(morfo, partKebab, matchers?) — type-checked against morfo.parts and morfo.events. Sema cascade rules MUST use it; hand-written strings are an architecture violation that breaks silently when morfo renames a part. - dialog morfo: open carries intent via fromProp; close-cancel / close-dismiss / close-dismiss-outside drop intent (cancellation has no evaluative load); close-save stays hardcoded fulfill (commit fulfils the user's decision regardless of dialog context). eidos dialog migration (4th pilot) - eidos/components/dialog/: full subdirectory wrapper — flat <Dialog> + compound Provider/Trigger/Overlay/Content/Title/Description/Close/Header/ Footer; size + position responsive props; sheet auto-form on narrow viewports; closePosition for the auto-X. - sema/components/dialog.ts: cascade rules use semaSelector(dialogMorfo, 'content', matchers?). Intent block adds character (haptic kind / pattern) but never overrides pitch / gain / contour — those are intent.deltas signature ownership and overriding flattens per-intent perceptual difference. demo controls + dialog page - src/lib/_demo (DemoSwitch / DemoEnum / DemoText / DemoRange) — unified controls reused across all component demos. - web/routes/dialog: live preview always rendered above tabs; per-event Sema tab with independent intent probe; signature visualisation + Play buttons with fallback target chain. documentation - CLAUDE.md: intent.deltas signature ownership rule; eidos drift defense doctrine (types over lint); 2026-05-09 hand-off entry. - morfo/README: Typed selector builder section. - eidos/README: linter section reframed as opt-in safety net for plain CSS recipes; the architectural mechanism is compile-time typing. - sema/README: open channel registry + flat cascade docs + override semantics + intent policy const + selector builder discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
/**
* Eidos — Dialog component recipe.
*
* Eidos applies universally to the data-attrs the dialog morfo emits. Tokens
* follow the bare-prefixed convention (`--dialog-*` public, `--_dialog-*`
* internal — see `eidos/components/README.md`). No `air-` / `eidos-`
* keyframe prefixes either.
*
* The morfo declares `data-last-action` as a prewrite on every close-* event,
* written BEFORE the `data-state` flips to 'closed'. The exit border-top is
* tinted by causa during the closing animation. See the data-last-action
* block at the bottom of this file.
*/
/* ── Trigger ───────────────────────────────────────────────────────────────
* Air's dialog relied on the Button recipe (`.air-button` class on the
* trigger). Eidos has no class composition — the trigger needs its own
* envelope here. Consumes Capa 2 tokens (color/space/radius/control-height)
* directly because the trigger is not a separate component with its own
* Capa 3, just a part of Dialog using the system surface.
*/
[data-dialog-trigger] {
display: inline-flex;
align-items: center;
justify-content: center;
height: var(--control-height-md);
padding-inline: var(--space-3);
border: 1px solid var(--color-border-default);
border-radius: var(--radius-md);
background: var(--color-surface-raised);
color: var(--color-content-primary);
font: inherit;
font-size: var(--dialog-trigger-font-size);
sema/morfo/eidos: typed selector builder + dialog wrapper + emerge color sema architecture - sema-map: 5-channel registry (motion / sound / color / presence / haptic) via SemaChannelSignatures declaration merging; engine stamps data-event-* tokens; flat CSS-style cascade replaces the eventLabel-overrides middle layer. - sema-map: emerge family gains base.color so intent deltas can shift hue / saturation / intensity. Without a base, the resolver was skipping the channel and Dialog open with intent='threat' rendered as neutral blue in the Sema tab visualisation. - types: SEMA_FAMILY_POLICY const drives compile-time + runtime intent requirements per family. Object shape so future per-family policy fields fit alongside. Emerge events MAY now declare intent (canon update — a Dialog confirming threat carries it in its very appearance). - chans: rename vibra→haptic, add HapticChannel V1 (Vibration API); SoundChannel eager-init on first user gesture (autoplay race fix). morfo selector discipline - morfo/selectors.ts (new): semaSelector(morfo, partKebab, matchers?) — type-checked against morfo.parts and morfo.events. Sema cascade rules MUST use it; hand-written strings are an architecture violation that breaks silently when morfo renames a part. - dialog morfo: open carries intent via fromProp; close-cancel / close-dismiss / close-dismiss-outside drop intent (cancellation has no evaluative load); close-save stays hardcoded fulfill (commit fulfils the user's decision regardless of dialog context). eidos dialog migration (4th pilot) - eidos/components/dialog/: full subdirectory wrapper — flat <Dialog> + compound Provider/Trigger/Overlay/Content/Title/Description/Close/Header/ Footer; size + position responsive props; sheet auto-form on narrow viewports; closePosition for the auto-X. - sema/components/dialog.ts: cascade rules use semaSelector(dialogMorfo, 'content', matchers?). Intent block adds character (haptic kind / pattern) but never overrides pitch / gain / contour — those are intent.deltas signature ownership and overriding flattens per-intent perceptual difference. demo controls + dialog page - src/lib/_demo (DemoSwitch / DemoEnum / DemoText / DemoRange) — unified controls reused across all component demos. - web/routes/dialog: live preview always rendered above tabs; per-event Sema tab with independent intent probe; signature visualisation + Play buttons with fallback target chain. documentation - CLAUDE.md: intent.deltas signature ownership rule; eidos drift defense doctrine (types over lint); 2026-05-09 hand-off entry. - morfo/README: Typed selector builder section. - eidos/README: linter section reframed as opt-in safety net for plain CSS recipes; the architectural mechanism is compile-time typing. - sema/README: open channel registry + flat cascade docs + override semantics + intent policy const + selector builder discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
cursor: pointer;
transition:
background var(--duration-fast) var(--ease-default),
border-color var(--duration-fast) var(--ease-default);
}
[data-dialog-trigger]:hover:not([disabled]):not([data-disabled]) {
background: var(--color-surface-overlay);
border-color: var(--color-border-strong);
}
[data-dialog-trigger][data-state='open'] {
background: var(--color-surface-overlay);
border-color: var(--color-border-strong);
}
[data-dialog-trigger]:disabled,
[data-dialog-trigger][data-disabled] {
cursor: default;
opacity: 0.5;
}
/* ── Overlay ───────────────────────────────────────────────────────────── */
[data-dialog-overlay] {
position: fixed;
inset: 0;
background: color-mix(
in srgb,
var(--dialog-overlay-bg) var(--dialog-overlay-opacity),
transparent
);
backdrop-filter: blur(var(--dialog-overlay-blur));
z-index: var(--dialog-overlay-z);
}
[data-dialog-overlay][data-state='open'] {
animation: dialog-overlay-in var(--dialog-overlay-in-duration) ease both;
}
[data-dialog-overlay][data-state='closed'] {
animation: dialog-overlay-out var(--dialog-overlay-out-duration) ease both;
}
@keyframes dialog-overlay-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes dialog-overlay-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
/* ── Content ───────────────────────────────────────────────────────────── */
[data-dialog-content] {
--_dialog-size-width: var(--dialog-content-width-md);
sema/morfo/eidos: typed selector builder + dialog wrapper + emerge color sema architecture - sema-map: 5-channel registry (motion / sound / color / presence / haptic) via SemaChannelSignatures declaration merging; engine stamps data-event-* tokens; flat CSS-style cascade replaces the eventLabel-overrides middle layer. - sema-map: emerge family gains base.color so intent deltas can shift hue / saturation / intensity. Without a base, the resolver was skipping the channel and Dialog open with intent='threat' rendered as neutral blue in the Sema tab visualisation. - types: SEMA_FAMILY_POLICY const drives compile-time + runtime intent requirements per family. Object shape so future per-family policy fields fit alongside. Emerge events MAY now declare intent (canon update — a Dialog confirming threat carries it in its very appearance). - chans: rename vibra→haptic, add HapticChannel V1 (Vibration API); SoundChannel eager-init on first user gesture (autoplay race fix). morfo selector discipline - morfo/selectors.ts (new): semaSelector(morfo, partKebab, matchers?) — type-checked against morfo.parts and morfo.events. Sema cascade rules MUST use it; hand-written strings are an architecture violation that breaks silently when morfo renames a part. - dialog morfo: open carries intent via fromProp; close-cancel / close-dismiss / close-dismiss-outside drop intent (cancellation has no evaluative load); close-save stays hardcoded fulfill (commit fulfils the user's decision regardless of dialog context). eidos dialog migration (4th pilot) - eidos/components/dialog/: full subdirectory wrapper — flat <Dialog> + compound Provider/Trigger/Overlay/Content/Title/Description/Close/Header/ Footer; size + position responsive props; sheet auto-form on narrow viewports; closePosition for the auto-X. - sema/components/dialog.ts: cascade rules use semaSelector(dialogMorfo, 'content', matchers?). Intent block adds character (haptic kind / pattern) but never overrides pitch / gain / contour — those are intent.deltas signature ownership and overriding flattens per-intent perceptual difference. demo controls + dialog page - src/lib/_demo (DemoSwitch / DemoEnum / DemoText / DemoRange) — unified controls reused across all component demos. - web/routes/dialog: live preview always rendered above tabs; per-event Sema tab with independent intent probe; signature visualisation + Play buttons with fallback target chain. documentation - CLAUDE.md: intent.deltas signature ownership rule; eidos drift defense doctrine (types over lint); 2026-05-09 hand-off entry. - morfo/README: Typed selector builder section. - eidos/README: linter section reframed as opt-in safety net for plain CSS recipes; the architectural mechanism is compile-time typing. - sema/README: open channel registry + flat cascade docs + override semantics + intent policy const + selector builder discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
--_dialog-padding: var(--dialog-content-padding-md);
--_dialog-width: var(--_dialog-content-width-override, var(--_dialog-size-width));
sema/morfo/eidos: typed selector builder + dialog wrapper + emerge color sema architecture - sema-map: 5-channel registry (motion / sound / color / presence / haptic) via SemaChannelSignatures declaration merging; engine stamps data-event-* tokens; flat CSS-style cascade replaces the eventLabel-overrides middle layer. - sema-map: emerge family gains base.color so intent deltas can shift hue / saturation / intensity. Without a base, the resolver was skipping the channel and Dialog open with intent='threat' rendered as neutral blue in the Sema tab visualisation. - types: SEMA_FAMILY_POLICY const drives compile-time + runtime intent requirements per family. Object shape so future per-family policy fields fit alongside. Emerge events MAY now declare intent (canon update — a Dialog confirming threat carries it in its very appearance). - chans: rename vibra→haptic, add HapticChannel V1 (Vibration API); SoundChannel eager-init on first user gesture (autoplay race fix). morfo selector discipline - morfo/selectors.ts (new): semaSelector(morfo, partKebab, matchers?) — type-checked against morfo.parts and morfo.events. Sema cascade rules MUST use it; hand-written strings are an architecture violation that breaks silently when morfo renames a part. - dialog morfo: open carries intent via fromProp; close-cancel / close-dismiss / close-dismiss-outside drop intent (cancellation has no evaluative load); close-save stays hardcoded fulfill (commit fulfils the user's decision regardless of dialog context). eidos dialog migration (4th pilot) - eidos/components/dialog/: full subdirectory wrapper — flat <Dialog> + compound Provider/Trigger/Overlay/Content/Title/Description/Close/Header/ Footer; size + position responsive props; sheet auto-form on narrow viewports; closePosition for the auto-X. - sema/components/dialog.ts: cascade rules use semaSelector(dialogMorfo, 'content', matchers?). Intent block adds character (haptic kind / pattern) but never overrides pitch / gain / contour — those are intent.deltas signature ownership and overriding flattens per-intent perceptual difference. demo controls + dialog page - src/lib/_demo (DemoSwitch / DemoEnum / DemoText / DemoRange) — unified controls reused across all component demos. - web/routes/dialog: live preview always rendered above tabs; per-event Sema tab with independent intent probe; signature visualisation + Play buttons with fallback target chain. documentation - CLAUDE.md: intent.deltas signature ownership rule; eidos drift defense doctrine (types over lint); 2026-05-09 hand-off entry. - morfo/README: Typed selector builder section. - eidos/README: linter section reframed as opt-in safety net for plain CSS recipes; the architectural mechanism is compile-time typing. - sema/README: open channel registry + flat cascade docs + override semantics + intent policy const + selector builder discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
position: fixed;
left: 50%;
top: 50%;
translate: -50% -50%;
z-index: calc(var(--dialog-overlay-z) + 1);
display: flex;
flex-direction: column;
gap: var(--dialog-stack-gap);
width: min(calc(100vw - var(--dialog-content-width-inset)), var(--_dialog-width));
min-width: var(--_dialog-content-min-width-override, auto);
max-width: var(--_dialog-content-max-width-override, none);
height: var(--_dialog-content-height-override, auto);
min-height: var(--_dialog-content-min-height-override, auto);
max-height: var(--_dialog-content-max-height-override, var(--dialog-content-max-height));
sema/morfo/eidos: typed selector builder + dialog wrapper + emerge color sema architecture - sema-map: 5-channel registry (motion / sound / color / presence / haptic) via SemaChannelSignatures declaration merging; engine stamps data-event-* tokens; flat CSS-style cascade replaces the eventLabel-overrides middle layer. - sema-map: emerge family gains base.color so intent deltas can shift hue / saturation / intensity. Without a base, the resolver was skipping the channel and Dialog open with intent='threat' rendered as neutral blue in the Sema tab visualisation. - types: SEMA_FAMILY_POLICY const drives compile-time + runtime intent requirements per family. Object shape so future per-family policy fields fit alongside. Emerge events MAY now declare intent (canon update — a Dialog confirming threat carries it in its very appearance). - chans: rename vibra→haptic, add HapticChannel V1 (Vibration API); SoundChannel eager-init on first user gesture (autoplay race fix). morfo selector discipline - morfo/selectors.ts (new): semaSelector(morfo, partKebab, matchers?) — type-checked against morfo.parts and morfo.events. Sema cascade rules MUST use it; hand-written strings are an architecture violation that breaks silently when morfo renames a part. - dialog morfo: open carries intent via fromProp; close-cancel / close-dismiss / close-dismiss-outside drop intent (cancellation has no evaluative load); close-save stays hardcoded fulfill (commit fulfils the user's decision regardless of dialog context). eidos dialog migration (4th pilot) - eidos/components/dialog/: full subdirectory wrapper — flat <Dialog> + compound Provider/Trigger/Overlay/Content/Title/Description/Close/Header/ Footer; size + position responsive props; sheet auto-form on narrow viewports; closePosition for the auto-X. - sema/components/dialog.ts: cascade rules use semaSelector(dialogMorfo, 'content', matchers?). Intent block adds character (haptic kind / pattern) but never overrides pitch / gain / contour — those are intent.deltas signature ownership and overriding flattens per-intent perceptual difference. demo controls + dialog page - src/lib/_demo (DemoSwitch / DemoEnum / DemoText / DemoRange) — unified controls reused across all component demos. - web/routes/dialog: live preview always rendered above tabs; per-event Sema tab with independent intent probe; signature visualisation + Play buttons with fallback target chain. documentation - CLAUDE.md: intent.deltas signature ownership rule; eidos drift defense doctrine (types over lint); 2026-05-09 hand-off entry. - morfo/README: Typed selector builder section. - eidos/README: linter section reframed as opt-in safety net for plain CSS recipes; the architectural mechanism is compile-time typing. - sema/README: open channel registry + flat cascade docs + override semantics + intent policy const + selector builder discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
padding: var(--_dialog-padding);
overflow: auto;
border: var(--dialog-content-border-width) solid var(--dialog-content-border);
border-radius: var(--dialog-content-radius);
background: var(--dialog-content-bg);
color: var(--dialog-content-color);
box-shadow: var(--dialog-content-shadow);
outline: none;
}
/* Content entrance / exit. Air only animated the overlay, leaving the
* content to snap in/out (sub-perceptual). Soma's Presence layer waits for
* `getAnimations().finished` before unmounting, so these animations gate
* the cycle by themselves. */
[data-dialog-content][data-state='open'] {
animation: dialog-content-in var(--dialog-overlay-in-duration) var(--ease-out) both;
}
[data-dialog-content][data-state='closed'] {
animation: dialog-content-out var(--dialog-overlay-out-duration) var(--ease-default) both;
}
@keyframes dialog-content-in {
from {
opacity: 0;
transform: scale(0.96);
}
}
@keyframes dialog-content-out {
to {
opacity: 0;
transform: scale(0.96);
}
}
/* ── Position (3×3 grid) ────────────────────────────────────────────────
* The default `[data-dialog-content]` rule above already centers the panel
* (`left/top: 50%; translate: -50% -50%;`) — that is the implicit
* `middle-center` form. The selectors below override the anchoring axes
* for the other 8 cells. `data-size='full'` and `data-sheet` come AFTER
* these in the cascade and win when applicable. */
[data-dialog-content][data-position='top-left'] {
top: var(--dialog-content-position-inset);
left: var(--dialog-content-position-inset);
right: auto;
bottom: auto;
translate: none;
}
[data-dialog-content][data-position='top-center'] {
top: var(--dialog-content-position-inset);
left: 50%;
right: auto;
bottom: auto;
translate: -50% 0;
}
[data-dialog-content][data-position='top-right'] {
top: var(--dialog-content-position-inset);
right: var(--dialog-content-position-inset);
left: auto;
bottom: auto;
translate: none;
}
[data-dialog-content][data-position='middle-left'] {
top: 50%;
left: var(--dialog-content-position-inset);
right: auto;
bottom: auto;
translate: 0 -50%;
}
/* `middle-center` is the default — no override needed. */
[data-dialog-content][data-position='middle-right'] {
top: 50%;
right: var(--dialog-content-position-inset);
left: auto;
bottom: auto;
translate: 0 -50%;
}
[data-dialog-content][data-position='bottom-left'] {
bottom: var(--dialog-content-position-inset);
left: var(--dialog-content-position-inset);
top: auto;
right: auto;
translate: none;
}
[data-dialog-content][data-position='bottom-center'] {
bottom: var(--dialog-content-position-inset);
left: 50%;
top: auto;
right: auto;
translate: -50% 0;
}
[data-dialog-content][data-position='bottom-right'] {
bottom: var(--dialog-content-position-inset);
right: var(--dialog-content-position-inset);
top: auto;
left: auto;
translate: none;
}
/* ── Sizing ────────────────────────────────────────────────────────────── */
[data-dialog-content][data-size='sm'] {
--_dialog-size-width: var(--dialog-content-width-sm);
sema/morfo/eidos: typed selector builder + dialog wrapper + emerge color sema architecture - sema-map: 5-channel registry (motion / sound / color / presence / haptic) via SemaChannelSignatures declaration merging; engine stamps data-event-* tokens; flat CSS-style cascade replaces the eventLabel-overrides middle layer. - sema-map: emerge family gains base.color so intent deltas can shift hue / saturation / intensity. Without a base, the resolver was skipping the channel and Dialog open with intent='threat' rendered as neutral blue in the Sema tab visualisation. - types: SEMA_FAMILY_POLICY const drives compile-time + runtime intent requirements per family. Object shape so future per-family policy fields fit alongside. Emerge events MAY now declare intent (canon update — a Dialog confirming threat carries it in its very appearance). - chans: rename vibra→haptic, add HapticChannel V1 (Vibration API); SoundChannel eager-init on first user gesture (autoplay race fix). morfo selector discipline - morfo/selectors.ts (new): semaSelector(morfo, partKebab, matchers?) — type-checked against morfo.parts and morfo.events. Sema cascade rules MUST use it; hand-written strings are an architecture violation that breaks silently when morfo renames a part. - dialog morfo: open carries intent via fromProp; close-cancel / close-dismiss / close-dismiss-outside drop intent (cancellation has no evaluative load); close-save stays hardcoded fulfill (commit fulfils the user's decision regardless of dialog context). eidos dialog migration (4th pilot) - eidos/components/dialog/: full subdirectory wrapper — flat <Dialog> + compound Provider/Trigger/Overlay/Content/Title/Description/Close/Header/ Footer; size + position responsive props; sheet auto-form on narrow viewports; closePosition for the auto-X. - sema/components/dialog.ts: cascade rules use semaSelector(dialogMorfo, 'content', matchers?). Intent block adds character (haptic kind / pattern) but never overrides pitch / gain / contour — those are intent.deltas signature ownership and overriding flattens per-intent perceptual difference. demo controls + dialog page - src/lib/_demo (DemoSwitch / DemoEnum / DemoText / DemoRange) — unified controls reused across all component demos. - web/routes/dialog: live preview always rendered above tabs; per-event Sema tab with independent intent probe; signature visualisation + Play buttons with fallback target chain. documentation - CLAUDE.md: intent.deltas signature ownership rule; eidos drift defense doctrine (types over lint); 2026-05-09 hand-off entry. - morfo/README: Typed selector builder section. - eidos/README: linter section reframed as opt-in safety net for plain CSS recipes; the architectural mechanism is compile-time typing. - sema/README: open channel registry + flat cascade docs + override semantics + intent policy const + selector builder discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
--_dialog-padding: var(--dialog-content-padding-sm);
}
[data-dialog-content][data-size='md'] {
--_dialog-size-width: var(--dialog-content-width-md);
sema/morfo/eidos: typed selector builder + dialog wrapper + emerge color sema architecture - sema-map: 5-channel registry (motion / sound / color / presence / haptic) via SemaChannelSignatures declaration merging; engine stamps data-event-* tokens; flat CSS-style cascade replaces the eventLabel-overrides middle layer. - sema-map: emerge family gains base.color so intent deltas can shift hue / saturation / intensity. Without a base, the resolver was skipping the channel and Dialog open with intent='threat' rendered as neutral blue in the Sema tab visualisation. - types: SEMA_FAMILY_POLICY const drives compile-time + runtime intent requirements per family. Object shape so future per-family policy fields fit alongside. Emerge events MAY now declare intent (canon update — a Dialog confirming threat carries it in its very appearance). - chans: rename vibra→haptic, add HapticChannel V1 (Vibration API); SoundChannel eager-init on first user gesture (autoplay race fix). morfo selector discipline - morfo/selectors.ts (new): semaSelector(morfo, partKebab, matchers?) — type-checked against morfo.parts and morfo.events. Sema cascade rules MUST use it; hand-written strings are an architecture violation that breaks silently when morfo renames a part. - dialog morfo: open carries intent via fromProp; close-cancel / close-dismiss / close-dismiss-outside drop intent (cancellation has no evaluative load); close-save stays hardcoded fulfill (commit fulfils the user's decision regardless of dialog context). eidos dialog migration (4th pilot) - eidos/components/dialog/: full subdirectory wrapper — flat <Dialog> + compound Provider/Trigger/Overlay/Content/Title/Description/Close/Header/ Footer; size + position responsive props; sheet auto-form on narrow viewports; closePosition for the auto-X. - sema/components/dialog.ts: cascade rules use semaSelector(dialogMorfo, 'content', matchers?). Intent block adds character (haptic kind / pattern) but never overrides pitch / gain / contour — those are intent.deltas signature ownership and overriding flattens per-intent perceptual difference. demo controls + dialog page - src/lib/_demo (DemoSwitch / DemoEnum / DemoText / DemoRange) — unified controls reused across all component demos. - web/routes/dialog: live preview always rendered above tabs; per-event Sema tab with independent intent probe; signature visualisation + Play buttons with fallback target chain. documentation - CLAUDE.md: intent.deltas signature ownership rule; eidos drift defense doctrine (types over lint); 2026-05-09 hand-off entry. - morfo/README: Typed selector builder section. - eidos/README: linter section reframed as opt-in safety net for plain CSS recipes; the architectural mechanism is compile-time typing. - sema/README: open channel registry + flat cascade docs + override semantics + intent policy const + selector builder discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
--_dialog-padding: var(--dialog-content-padding-md);
}
[data-dialog-content][data-size='lg'] {
--_dialog-size-width: var(--dialog-content-width-lg);
sema/morfo/eidos: typed selector builder + dialog wrapper + emerge color sema architecture - sema-map: 5-channel registry (motion / sound / color / presence / haptic) via SemaChannelSignatures declaration merging; engine stamps data-event-* tokens; flat CSS-style cascade replaces the eventLabel-overrides middle layer. - sema-map: emerge family gains base.color so intent deltas can shift hue / saturation / intensity. Without a base, the resolver was skipping the channel and Dialog open with intent='threat' rendered as neutral blue in the Sema tab visualisation. - types: SEMA_FAMILY_POLICY const drives compile-time + runtime intent requirements per family. Object shape so future per-family policy fields fit alongside. Emerge events MAY now declare intent (canon update — a Dialog confirming threat carries it in its very appearance). - chans: rename vibra→haptic, add HapticChannel V1 (Vibration API); SoundChannel eager-init on first user gesture (autoplay race fix). morfo selector discipline - morfo/selectors.ts (new): semaSelector(morfo, partKebab, matchers?) — type-checked against morfo.parts and morfo.events. Sema cascade rules MUST use it; hand-written strings are an architecture violation that breaks silently when morfo renames a part. - dialog morfo: open carries intent via fromProp; close-cancel / close-dismiss / close-dismiss-outside drop intent (cancellation has no evaluative load); close-save stays hardcoded fulfill (commit fulfils the user's decision regardless of dialog context). eidos dialog migration (4th pilot) - eidos/components/dialog/: full subdirectory wrapper — flat <Dialog> + compound Provider/Trigger/Overlay/Content/Title/Description/Close/Header/ Footer; size + position responsive props; sheet auto-form on narrow viewports; closePosition for the auto-X. - sema/components/dialog.ts: cascade rules use semaSelector(dialogMorfo, 'content', matchers?). Intent block adds character (haptic kind / pattern) but never overrides pitch / gain / contour — those are intent.deltas signature ownership and overriding flattens per-intent perceptual difference. demo controls + dialog page - src/lib/_demo (DemoSwitch / DemoEnum / DemoText / DemoRange) — unified controls reused across all component demos. - web/routes/dialog: live preview always rendered above tabs; per-event Sema tab with independent intent probe; signature visualisation + Play buttons with fallback target chain. documentation - CLAUDE.md: intent.deltas signature ownership rule; eidos drift defense doctrine (types over lint); 2026-05-09 hand-off entry. - morfo/README: Typed selector builder section. - eidos/README: linter section reframed as opt-in safety net for plain CSS recipes; the architectural mechanism is compile-time typing. - sema/README: open channel registry + flat cascade docs + override semantics + intent policy const + selector builder discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
--_dialog-padding: var(--dialog-content-padding-lg);
}
[data-dialog-content][data-size='xl'] {
--_dialog-size-width: var(--dialog-content-width-xl);
sema/morfo/eidos: typed selector builder + dialog wrapper + emerge color sema architecture - sema-map: 5-channel registry (motion / sound / color / presence / haptic) via SemaChannelSignatures declaration merging; engine stamps data-event-* tokens; flat CSS-style cascade replaces the eventLabel-overrides middle layer. - sema-map: emerge family gains base.color so intent deltas can shift hue / saturation / intensity. Without a base, the resolver was skipping the channel and Dialog open with intent='threat' rendered as neutral blue in the Sema tab visualisation. - types: SEMA_FAMILY_POLICY const drives compile-time + runtime intent requirements per family. Object shape so future per-family policy fields fit alongside. Emerge events MAY now declare intent (canon update — a Dialog confirming threat carries it in its very appearance). - chans: rename vibra→haptic, add HapticChannel V1 (Vibration API); SoundChannel eager-init on first user gesture (autoplay race fix). morfo selector discipline - morfo/selectors.ts (new): semaSelector(morfo, partKebab, matchers?) — type-checked against morfo.parts and morfo.events. Sema cascade rules MUST use it; hand-written strings are an architecture violation that breaks silently when morfo renames a part. - dialog morfo: open carries intent via fromProp; close-cancel / close-dismiss / close-dismiss-outside drop intent (cancellation has no evaluative load); close-save stays hardcoded fulfill (commit fulfils the user's decision regardless of dialog context). eidos dialog migration (4th pilot) - eidos/components/dialog/: full subdirectory wrapper — flat <Dialog> + compound Provider/Trigger/Overlay/Content/Title/Description/Close/Header/ Footer; size + position responsive props; sheet auto-form on narrow viewports; closePosition for the auto-X. - sema/components/dialog.ts: cascade rules use semaSelector(dialogMorfo, 'content', matchers?). Intent block adds character (haptic kind / pattern) but never overrides pitch / gain / contour — those are intent.deltas signature ownership and overriding flattens per-intent perceptual difference. demo controls + dialog page - src/lib/_demo (DemoSwitch / DemoEnum / DemoText / DemoRange) — unified controls reused across all component demos. - web/routes/dialog: live preview always rendered above tabs; per-event Sema tab with independent intent probe; signature visualisation + Play buttons with fallback target chain. documentation - CLAUDE.md: intent.deltas signature ownership rule; eidos drift defense doctrine (types over lint); 2026-05-09 hand-off entry. - morfo/README: Typed selector builder section. - eidos/README: linter section reframed as opt-in safety net for plain CSS recipes; the architectural mechanism is compile-time typing. - sema/README: open channel registry + flat cascade docs + override semantics + intent policy const + selector builder discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
--_dialog-padding: var(--dialog-content-padding-full);
border-radius: var(--dialog-content-full-radius);
}
[data-dialog-content][data-size='full'] {
inset: var(--dialog-content-full-inset);
translate: none;
width: var(--_dialog-content-width-override, auto);
sema/morfo/eidos: typed selector builder + dialog wrapper + emerge color sema architecture - sema-map: 5-channel registry (motion / sound / color / presence / haptic) via SemaChannelSignatures declaration merging; engine stamps data-event-* tokens; flat CSS-style cascade replaces the eventLabel-overrides middle layer. - sema-map: emerge family gains base.color so intent deltas can shift hue / saturation / intensity. Without a base, the resolver was skipping the channel and Dialog open with intent='threat' rendered as neutral blue in the Sema tab visualisation. - types: SEMA_FAMILY_POLICY const drives compile-time + runtime intent requirements per family. Object shape so future per-family policy fields fit alongside. Emerge events MAY now declare intent (canon update — a Dialog confirming threat carries it in its very appearance). - chans: rename vibra→haptic, add HapticChannel V1 (Vibration API); SoundChannel eager-init on first user gesture (autoplay race fix). morfo selector discipline - morfo/selectors.ts (new): semaSelector(morfo, partKebab, matchers?) — type-checked against morfo.parts and morfo.events. Sema cascade rules MUST use it; hand-written strings are an architecture violation that breaks silently when morfo renames a part. - dialog morfo: open carries intent via fromProp; close-cancel / close-dismiss / close-dismiss-outside drop intent (cancellation has no evaluative load); close-save stays hardcoded fulfill (commit fulfils the user's decision regardless of dialog context). eidos dialog migration (4th pilot) - eidos/components/dialog/: full subdirectory wrapper — flat <Dialog> + compound Provider/Trigger/Overlay/Content/Title/Description/Close/Header/ Footer; size + position responsive props; sheet auto-form on narrow viewports; closePosition for the auto-X. - sema/components/dialog.ts: cascade rules use semaSelector(dialogMorfo, 'content', matchers?). Intent block adds character (haptic kind / pattern) but never overrides pitch / gain / contour — those are intent.deltas signature ownership and overriding flattens per-intent perceptual difference. demo controls + dialog page - src/lib/_demo (DemoSwitch / DemoEnum / DemoText / DemoRange) — unified controls reused across all component demos. - web/routes/dialog: live preview always rendered above tabs; per-event Sema tab with independent intent probe; signature visualisation + Play buttons with fallback target chain. documentation - CLAUDE.md: intent.deltas signature ownership rule; eidos drift defense doctrine (types over lint); 2026-05-09 hand-off entry. - morfo/README: Typed selector builder section. - eidos/README: linter section reframed as opt-in safety net for plain CSS recipes; the architectural mechanism is compile-time typing. - sema/README: open channel registry + flat cascade docs + override semantics + intent policy const + selector builder discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
border-radius: var(--dialog-content-full-radius);
--_dialog-padding: var(--dialog-content-padding-full);
}
/* Auto-sheet: the eidos wrapper sets `data-sheet=""` on Content when the
* viewport is narrower than the `sm` breakpoint AND the requested size is
* not `full`. Bottom-anchored, full-width, top-rounded. */
[data-dialog-content][data-sheet] {
left: 0;
top: auto;
bottom: 0;
translate: none;
width: 100%;
max-height: var(--dialog-content-max-height-sheet);
border-radius: var(--dialog-content-radius) var(--dialog-content-radius) 0 0;
--_dialog-padding: var(--dialog-content-padding-sm);
}
/* ── Color (intent → palette) ──────────────────────────────────────────────
* Modal subset of the 8 system tokens (canon §3.1). Soma resolves the
* consumer's `intent` prop to `data-color`. The subset is intentionally
* tight: a dialog is not a hierarchy and irreversible loss should not be
* a dialog at all. Each intent tints the panel border and (for evaluative
* intents) the title color. The body background stays neutral so long-form
* content doesn't compete with the intent signal. */
[data-dialog-content][data-color='neutral'] {
border-color: var(--dialog-content-border);
}
[data-dialog-content][data-color='risk'] {
border-color: var(--color-risk-border);
}
[data-dialog-content][data-color='risk'] [data-dialog-title] {
color: var(--color-risk-text);
}
[data-dialog-content][data-color='threat'] {
border-color: var(--color-threat-border);
}
[data-dialog-content][data-color='threat'] [data-dialog-title] {
color: var(--color-threat-text);
}
/* ── Layout shells (eidos-only, no morfo backing) ──────────────────────── */
[data-dialog-header] {
display: flex;
flex-direction: column;
align-items: start;
gap: var(--dialog-header-gap);
/* Reserve space on the trailing edge so a top-right close doesn't
* collide with title text. The padding flips when a close is anchored
* top-left via the rules below. */
padding-inline-end: calc(var(--dialog-close-size) + var(--space-2));
}
[data-dialog-content]:has([data-dialog-close][data-position^='top-left']) [data-dialog-header] {
padding-inline-end: 0;
padding-inline-start: calc(var(--dialog-close-size) + var(--space-2));
}
[data-dialog-content]:has([data-dialog-close][data-position^='bottom-']) [data-dialog-header],
[data-dialog-content]:has([data-dialog-close][data-position='top-center']) [data-dialog-header] {
padding-inline: 0;
}
[data-dialog-footer] {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: end;
gap: var(--dialog-footer-gap);
margin-top: var(--dialog-footer-margin-top);
}
/* ── Title / Description ───────────────────────────────────────────────── */
[data-dialog-title] {
margin: 0;
font-family: var(--dialog-title-font-family);
font-size: var(--dialog-title-font-size);
font-weight: var(--dialog-title-font-weight);
line-height: var(--dialog-title-line-height);
color: var(--dialog-title-color);
text-wrap: balance;
}
[data-dialog-description] {
margin: 0;
font-family: var(--dialog-description-font-family);
font-size: var(--dialog-description-font-size);
line-height: var(--dialog-description-line-height);
color: var(--dialog-description-color);
}
/* ── Close ─────────────────────────────────────────────────────────────── */
[data-dialog-close] {
display: inline-flex;
align-items: center;
justify-content: center;
flex: 0 0 auto;
min-inline-size: var(--dialog-close-size);
block-size: var(--dialog-close-size);
padding-inline: var(--dialog-close-px);
border: var(--dialog-close-border-width) solid var(--dialog-close-border);
border-radius: var(--dialog-close-radius);
background: var(--dialog-close-bg);
color: var(--dialog-close-color);
cursor: pointer;
transition:
background var(--dialog-close-transition-duration) var(--dialog-close-transition-ease),
color var(--dialog-close-transition-duration) var(--dialog-close-transition-ease),
border-color var(--dialog-close-transition-duration) var(--dialog-close-transition-ease),
box-shadow var(--dialog-close-transition-duration) var(--dialog-close-transition-ease);
}
/* Floating close — only when the wrapper / consumer assigns `data-position`.
* Closes WITHOUT data-position (e.g. a <DialogClose> in an actions snippet)
* flow inline. */
[data-dialog-close][data-position] {
position: absolute;
z-index: 1;
}
/* ── Close position (subset of canonical Position — corners + top/bottom centers) ── */
/* Default: top-right (matches the eidos wrapper's `closePosition` default). */
[data-dialog-close][data-position='top-right'] {
top: var(--dialog-close-inset);
right: var(--dialog-close-inset);
}
[data-dialog-close][data-position='top-left'] {
top: var(--dialog-close-inset);
left: var(--dialog-close-inset);
}
[data-dialog-close][data-position='top-center'] {
top: var(--dialog-close-inset);
left: 50%;
translate: -50% 0;
}
[data-dialog-close][data-position='bottom-right'] {
bottom: var(--dialog-close-inset);
right: var(--dialog-close-inset);
}
[data-dialog-close][data-position='bottom-left'] {
bottom: var(--dialog-close-inset);
left: var(--dialog-close-inset);
}
[data-dialog-close][data-position='bottom-center'] {
bottom: var(--dialog-close-inset);
left: 50%;
translate: -50% 0;
}
[data-dialog-close][data-icon-only] {
inline-size: var(--dialog-close-size);
padding-inline: 0;
}
[data-dialog-close]:hover {
background: var(--dialog-close-bg-hover);
color: var(--dialog-close-color-hover);
}
[data-dialog-close]:focus-visible {
outline: none;
box-shadow:
0 0 0 var(--dialog-close-focus-ring-offset) var(--dialog-content-bg),
0 0 0 calc(var(--dialog-close-focus-ring-offset) + var(--dialog-close-focus-ring-width))
var(--dialog-close-focus-ring-color);
}
[data-dialog-close]:disabled,
[data-dialog-close][data-disabled] {
cursor: default;
opacity: 0.5;
}
/* ── data-last-action exit tinting ─────────────────────────────────────────
* The dialog morfo declares `prewrite` on every close-* event that writes
* `data-last-action` before `data-state` flips to 'closed'. Both attrs
* coexist during the exit animation; CSS tints the border-top by causa.
*/
[data-dialog-content][data-state='closed'][data-last-action='saved'] {
border-top-color: var(--color-fulfill-element);
}
[data-dialog-content][data-state='closed'][data-last-action='failed'] {
border-top-color: var(--color-threat-element);
}
[data-dialog-content][data-state='closed'][data-last-action='cancelled'],
[data-dialog-content][data-state='closed'][data-last-action='dismissed'],
[data-dialog-content][data-state='closed'][data-last-action='dismissed-outside'] {
border-top-color: var(--color-neutral-element);
}

Powered by TurnKey Linux.