Spaces:
Running
Running
Download dee/static/motion.css from WINTER4000/syntheogenesis: direct link, hf CLI and curl.
- Browser
- Download file 14.9 kB
-
https://huggingface.co/spaces/WINTER4000/syntheogenesis/resolve/main/dee/static/motion.css
- Command line
-
hf download hf://spaces/WINTER4000/syntheogenesis/dee/static/motion.css
-
curl -L -o motion.css https://huggingface.co/spaces/WINTER4000/syntheogenesis/resolve/main/dee/static/motion.css
14.9 kB
| /* Depth and motion for Mission Control. | |
| * | |
| * WHAT WAS WRONG, MEASURED | |
| * | |
| * Of 84 elements painted in the first screen, THREE had any box-shadow. The | |
| * whole interface sat on one plane, so nothing was above anything else and | |
| * every separation had to be drawn with a hairline -- 410 `1px solid` rules | |
| * across the stylesheets. That flatness, not the palette, is what reads as | |
| * old. | |
| * | |
| * Motion had the same shape of problem. 138 of the transitions in the first | |
| * screen animate `background`, `color` or `border-color` -- point at a thing | |
| * and it changes colour -- against 4 that touch `opacity` and 4 that touch a | |
| * dimension. Nothing arrives, nothing settles, nothing answers a press. The | |
| * vocabulary was hover-recolour, which is the interaction language of 2004. | |
| * | |
| * WHAT THIS IS NOT | |
| * | |
| * Not a repaint: this file sets no colour. The palette was not the complaint | |
| * and is not touched. | |
| * | |
| * SCOPE | |
| * | |
| * Mission Control only, on purpose. The elevation and motion scales below are | |
| * general, but they are applied to .mc-* and nothing else until they have been | |
| * looked at on a real screen. Four other views keep exactly the styling they | |
| * have today. | |
| */ | |
| /* ββ the theme bridge ββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| Open Props derives all six shadow levels from two inputs and switches them | |
| on `prefers-color-scheme`. The engine's theme is a USER choice carried on | |
| [data-theme], so somebody running the dark theme on a light OS would get | |
| light-mode shadows: a pale grey smudge under a dark card instead of depth. | |
| Re-declare the two inputs against our switch -- with Open Props' own values, | |
| so the two systems cannot drift -- and its scale follows. The OS-default | |
| case needs nothing; Open Props already handles it. */ | |
| /* STRENGTH, not level. Open Props' light default is 1%, tuned for a card on | |
| a PURE WHITE page where almost nothing is needed to separate the two. This | |
| app's ground is off-white and the cards are white, so at 1% every level of | |
| the ramp under-read: measured live, a 680x180 card carried a shadow nobody | |
| could see, and raising the LEVEL only lengthened a blur that was still too | |
| faint. Raising the strength lifts the whole ramp at once and keeps the | |
| relationships between its six steps intact, which is the point of having a | |
| ramp. 4% on the light ground; dark keeps Open Props' own 25%. | |
| Three declarations, not two: the first covers the DEFAULT case, where the | |
| reader has expressed no preference and no [data-theme] attribute exists β | |
| without it, anyone who never touched the theme toggle keeps the invisible | |
| 1%. The media query then restores dark for that same default case, because | |
| a bare :root here would otherwise beat Open Props' own dark block. */ | |
| :root { --shadow-strength: 4%; } | |
| @media (prefers-color-scheme: dark) { :root { --shadow-strength: 25%; } } | |
| :root[data-theme="light"] { --shadow-color: 220 3% 15%; --shadow-strength: 4%; } | |
| :root[data-theme="dark"] { --shadow-color: 220 40% 2%; --shadow-strength: 25%; } | |
| /* ββ elevation by role βββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| Height has to MEAN something or it is just decoration on every box. Three | |
| roles, and nothing else in Mission Control lifts: | |
| rest (--shadow-2) a card is an object sitting on the page | |
| raised (--shadow-4) the pointer is on it and it can be acted on | |
| press (--shadow-1) it has been pushed back down into the page | |
| The 2px rise is small on purpose. A card that jumps is a card that was | |
| designed to be noticed rather than used. */ | |
| .mc-cx { | |
| box-shadow: var(--shadow-2); | |
| /* Explicit properties, never `transition: all`: `all` animates things we | |
| never chose -- including layout properties, which is where jank comes | |
| from -- and it is set on 177 elements in the first screen today. */ | |
| transition: box-shadow var(--t-slow) var(--ease-3), | |
| transform var(--t-slow) var(--ease-3), | |
| border-color var(--t-fast) var(--ease-3); | |
| } | |
| @media (prefers-reduced-motion: no-preference) { | |
| .mc-cx:hover { transform: translateY(-2px); } | |
| /* The press answers in --t-fast: lift can be leisurely, but feedback to a | |
| finger cannot be, or the control feels like it missed the click. */ | |
| .mc-cx:active { | |
| transform: translateY(0) scale(0.995); | |
| transition-duration: var(--t-fast); | |
| } | |
| } | |
| /* Depth still changes without motion -- somebody on reduced-motion should | |
| lose the movement, not the affordance. */ | |
| .mc-cx:hover { box-shadow: var(--shadow-4); } | |
| .mc-cx:active { box-shadow: var(--shadow-1); } | |
| /* A focus ring and an elevation live in the same property, so the ring has to | |
| carry the shadow with it or keyboard focus would flatten the card. */ | |
| .mc-cx:focus-visible { | |
| box-shadow: var(--ring) var(--brand-ring), var(--shadow-4); | |
| outline: none; | |
| } | |
| /* ββ the press on the primary action βββββββββββββββββββββββββββββββββββββ | |
| The one control on this screen that starts work. It had a colour change and | |
| nothing else. */ | |
| @media (prefers-reduced-motion: no-preference) { | |
| .mc-enter-cta { transition: transform var(--t-fast) var(--ease-3), | |
| box-shadow var(--t-fast) var(--ease-3), | |
| background var(--t-fast) var(--ease), | |
| color var(--t-fast) var(--ease); } | |
| .mc-enter-cta:hover { transform: translateY(-1px); } | |
| .mc-enter-cta:active { transform: translateY(0) scale(0.97); } | |
| } | |
| /* The filled CTA takes LESS than a card, not more. Its dark fill already | |
| separates it from the page; at the raised strength, a card-weight shadow | |
| under it reads as a sticker. */ | |
| .mc-enter-cta { box-shadow: var(--shadow-1); } | |
| .mc-enter-cta:active { box-shadow: var(--shadow-1); } | |
| /* ββ entrance ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| THE RULE THIS FILE MUST NOT BREAK: content is never parked invisible. | |
| Every animation here lives inside `prefers-reduced-motion: no-preference` | |
| and is applied by a class that app.js adds and then removes. If the CSS | |
| never loads, if the JS never runs, if the browser refuses the animation -- | |
| the resting state is the finished state and the cards are simply there. | |
| An entrance that can strand a paying customer on a blank grid is worse than | |
| no entrance at all. | |
| It also runs ONCE, when the view is first populated. Mission Control | |
| repaints whenever work lands, and a grid that replays its arrival every | |
| time somebody saves is a grid that punishes you for working. */ | |
| @media (prefers-reduced-motion: no-preference) { | |
| .mc-grid.is-entering > * { | |
| /* `backwards` so the delay holds the start frame rather than showing | |
| the element, hiding it, then animating it in. */ | |
| animation: mc-rise var(--t-slow) var(--ease-3) backwards; | |
| } | |
| /* Stagger, capped. Open Props' own slide-in-up travels 100%, which is | |
| right for a panel and wrong for a card in a grid, so the distance is | |
| ours; the easing is theirs. */ | |
| .mc-grid.is-entering > *:nth-child(1) { animation-delay: 0ms; } | |
| .mc-grid.is-entering > *:nth-child(2) { animation-delay: 40ms; } | |
| .mc-grid.is-entering > *:nth-child(3) { animation-delay: 80ms; } | |
| .mc-grid.is-entering > *:nth-child(4) { animation-delay: 120ms; } | |
| .mc-grid.is-entering > *:nth-child(5) { animation-delay: 160ms; } | |
| /* Everything past the fifth arrives together. A stagger long enough to | |
| watch is a stagger that has become a loading screen. */ | |
| .mc-grid.is-entering > *:nth-child(n+6) { animation-delay: 200ms; } | |
| } | |
| @keyframes mc-rise { | |
| from { opacity: 0; transform: translateY(8px); } | |
| /* No `to`: the resting state IS the destination, so this keyframe cannot | |
| disagree with the stylesheet about where the card ends up. */ | |
| } | |
| /* ββ the label leans toward its action βββββββββββββββββββββββββββββββββββ | |
| "Review research β" is the thing the card is FOR, and it sat perfectly | |
| still while the card lit up around it. A 2px lean on hover is the oldest | |
| refined micro-interaction there is and it still works: the eye reads it as | |
| the card pointing at where the click goes. | |
| The nudge is on the whole label rather than the arrow alone because the | |
| arrow is a bare → inside the text node -- wrapping it would mean | |
| touching two markup sites in app.js for two pixels. */ | |
| @media (prefers-reduced-motion: no-preference) { | |
| .mc-cx-act-go { transition: transform var(--t-slow) var(--ease-3); } | |
| .mc-cx:hover .mc-cx-act-go { transform: translateX(2px); } | |
| } | |
| /* ββ the secondary controls answer the same way ββββββββββββββββββββββββββ | |
| The primary CTA got a press in the last pass and the two controls beside | |
| it did not, which reads worse than if none of them had: one button in a row | |
| behaving differently is a bug the eye notices before the mind does. */ | |
| @media (prefers-reduced-motion: no-preference) { | |
| .mc-enter-find, | |
| .ws-entry { transition: transform var(--t-fast) var(--ease-3), | |
| box-shadow var(--t-fast) var(--ease-3), | |
| border-color var(--t-fast) var(--ease-3), | |
| color var(--t-fast) var(--ease); } | |
| .mc-enter-find:active, | |
| .ws-entry:active { transform: scale(0.97); } | |
| /* Nav items take the press but never the lift: a sidebar that rises under | |
| the pointer turns a list into a row of buttons competing with the work. | |
| The transition lives on .nav-item in app.css, alongside the hover fade | |
| it already had β declaring a second one here would have replaced that | |
| fade rather than extended it. */ | |
| .nav-item:active { transform: scale(0.985); } | |
| } | |
| /* ββ focus, everywhere the press went ββββββββββββββββββββββββββββββββββββ | |
| Keyboard users get the same geometry as the mouse: one ring, carried on | |
| var(--ring) so test_shape_scale stays true, and never `outline: none` | |
| without a replacement. */ | |
| .mc-enter-cta:focus-visible, | |
| .mc-enter-find:focus-visible, | |
| .ws-entry:focus-visible { | |
| box-shadow: var(--ring) var(--brand-ring); | |
| outline: none; | |
| } | |
| /* ββ ENGINE-WIDE INTERACTION βββββββββββββββββββββββββββββββββββββββββββββ | |
| Mission Control was the pilot. This extends the same vocabulary to the | |
| rest of the engine β and the operative word is VOCABULARY, not coverage. | |
| There are 357 rules in these stylesheets that draw a bordered, filled, | |
| rounded box. Elevating all of them would raise everything, and a page | |
| where everything is raised reads exactly like a page where nothing is: | |
| depth only means something while most things stay on the ground. | |
| So: two roles, assigned by what the thing DOES, and nothing else gets | |
| touched. | |
| A CARD is content you open. It lifts under the pointer and presses in. | |
| A CONTROL is a thing you press. It presses, and never lifts β a toolbar | |
| that rises under the cursor turns into a row of hovering chiclets. | |
| Floating surfaces (.modal-panel, .acct-menu, .toast) already carry their | |
| own elevation and are deliberately absent: they are never pressed, and | |
| restating their shadow here would fight the sheet that owns them. */ | |
| /* ββ cards: lift, then press βββββββββββββββββββββββββββββββββββββββββββββ | |
| Gated on being ACTIVATABLE, not on carrying a card-ish class name. | |
| Measured on the live engine: `.card` is 23 <section> elements and NONE of | |
| them is clickable β it is a layout container. Lifting it would be a false | |
| affordance, content that rises under the pointer and then does nothing | |
| when you press it, which is worse than no motion at all. | |
| `:is(button, a, [role=button])` makes that rule structural instead of a | |
| list I maintain by hand: a class only gets the lift on the routes where it | |
| is actually a control, and a future <section class="card"> never does. */ | |
| :is(button, a, [role="button"]):is(.mc-recent, .card, .model-card, .primer-card, .cp-eg, .lib-row, .hist-item, .cds-item):hover { box-shadow: var(--shadow-4); } | |
| :is(button, a, [role="button"]):is(.mc-recent, .card, .model-card, .primer-card, .cp-eg, .lib-row, .hist-item, .cds-item) { transition: box-shadow var(--t-slow) var(--ease-3), | |
| transform var(--t-slow) var(--ease-3), | |
| border-color var(--t-fast) var(--ease-3); } | |
| :is(button, a, [role="button"]):is(.mc-recent, .card, .model-card, .primer-card, .cp-eg, .lib-row, .hist-item, .cds-item):active { box-shadow: var(--shadow-1); } | |
| @media (prefers-reduced-motion: no-preference) { | |
| :is(button, a, [role="button"]):is(.mc-recent, .card, .model-card, .primer-card, .cp-eg, .lib-row, .hist-item, .cds-item):hover { transform: translateY(-2px); } | |
| :is(button, a, [role="button"]):is(.mc-recent, .card, .model-card, .primer-card, .cp-eg, .lib-row, .hist-item, .cds-item):active { transform: translateY(0) scale(0.995); | |
| transition-duration: var(--t-fast); } | |
| } | |
| :is(button, a, [role="button"]):is(.mc-recent, .card, .model-card, .primer-card, .cp-eg, .lib-row, .hist-item, .cds-item):focus-visible { | |
| box-shadow: var(--ring) var(--brand-ring), var(--shadow-4); | |
| outline: none; | |
| } | |
| /* ββ controls: press only ββββββββββββββββββββββββββββββββββββββββββββββββ | |
| Every one of these already transitions its own colours; the property | |
| lists in app.css were widened to include `transform` in the same change | |
| that retired `transition: all`, so this adds the state and not a second, | |
| competing shorthand. */ | |
| @media (prefers-reduced-motion: no-preference) { | |
| .primary:not(:disabled):active, | |
| .primary-ghost:not(:disabled):active, | |
| .ghost:not(:disabled):active, | |
| .identify-btn:not(:disabled):active, | |
| .copy-btn:active, .expand-toggle:active, .modal-close:active, | |
| .nav-toggle:active, .theme-toggle:active, .cmd-trigger:active, | |
| .acct-trigger:active, .filter-clear:active, | |
| .crispr-vendor-btn:not(:disabled):active, | |
| .crispr-struct-mini:active, | |
| .tab:active { | |
| transform: scale(0.97); | |
| } | |
| } | |