mnfst 0.5.230 → 0.5.232

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/manifest.css CHANGED
@@ -2922,136 +2922,139 @@
2922
2922
 
2923
2923
  @layer base, components, utilities;
2924
2924
 
2925
- /* Self-contained: every rule the plugin needs lives here, so this stylesheet works
2926
- on its own. Authors override without specificity battles — rules are :where()
2927
- wrapped and keyed off data-edit-* attributes, including the injected affordances
2928
- (handles, overlay, live region, toolbar, menu). No class names to collide with. */
2925
+ /* Rules are :where()-wrapped and keyed off data-edit-* attributes, so authors
2926
+ override without specificity battles. Visuals are on for every area;
2927
+ x-edit.bare (data-edit-area="bare") keeps the behaviour and draws none of them. */
2929
2928
 
2930
2929
  @layer utilities {
2931
2930
 
2932
- /* ---- Editing UI scope ----
2933
- ALL chrome — cursors, movable/text outlines, size-handle hairlines, drop
2934
- targets, the floating toolbar — lives under ONE scope: [data-edit-ui], on
2935
- the region itself or any ancestor (e.g. <body data-edit-ui> for a whole
2936
- editor view). The plugin sets it on `.authoring` regions automatically;
2937
- everything else opts in with the attribute. A region outside the scope is
2938
- just as editable — it simply carries no visual cues. */
2931
+ /* ---- Pieces ---- */
2932
+ :where([data-edit-piece]) {
2933
+ cursor: grab;
2934
+ touch-action: none;
2935
+ transition: opacity 0.12s ease, outline-color 0.12s ease;
2936
+ }
2939
2937
 
2940
- /* ---- Editable area (armed) ---- */
2941
- :where([data-edit-armed]) {
2942
- position: relative;
2938
+ :where([data-edit-piece]):where(:hover):where(:not([data-edit-area="bare"], [data-edit-area="bare"] *, [data-edit-dragging], [data-edit-ghost], :has([data-edit-dragging]) *)) {
2939
+ outline: 1px solid color-mix(in oklch, var(--edit-accent, var(--color-brand-content)) 45%, transparent);
2940
+ outline-offset: 3px;
2943
2941
  }
2944
2942
 
2945
- /* No default region boundary or label: a page being edited should look
2946
- like the page, not a diagram of its regions. The hooks remain for a real
2947
- editor product to draw its own — [data-edit-authoring] marks the region
2948
- and data-edit-label carries "key · regime". */
2943
+ :where([data-edit-piece]):focus-visible:where(:not([data-edit-area="bare"], [data-edit-area="bare"] *)) {
2944
+ outline: 2px solid var(--edit-accent, var(--color-brand-content));
2945
+ outline-offset: 3px;
2946
+ }
2949
2947
 
2950
- /* ---- Reorder (pointer + keyboard; touch-action:none lets touch-drag beat scroll) ---- */
2951
- :where([data-edit-sortable]) {
2948
+ /* Grip: drags a text piece; sits at its inline-start edge */
2949
+ :where([data-edit-grip]) {
2950
+ position: fixed;
2951
+ z-index: 1001;
2952
+ width: var(--edit-grip-size, 0.75rem);
2953
+ height: calc(var(--edit-grip-size, 0.75rem) * 1.5);
2954
+ translate: calc(-100% - var(--edit-grip-offset, 0.25rem)) 0;
2955
+ border-radius: 3px;
2956
+ color: var(--edit-accent, var(--color-brand-content));
2957
+ background: radial-gradient(circle, currentColor 1px, transparent 1.5px) center / 6px 6px;
2958
+ opacity: 0.6;
2952
2959
  cursor: grab;
2953
2960
  touch-action: none;
2954
- transition: opacity 0.12s ease, outline-color 0.12s ease;
2961
+ user-select: none;
2962
+
2963
+ &:hover {
2964
+ opacity: 1;
2965
+ }
2955
2966
  }
2956
2967
 
2957
- /* No injected grip: the row itself is the handle (grab cursor), while text
2958
- inside stays a text surface (text cursor, below). Rows that are pure text
2959
- still reorder by keyboard. */
2968
+ :where([data-edit-grip]:dir(rtl)) {
2969
+ translate: var(--edit-grip-offset, 0.25rem) 0;
2970
+ }
2960
2971
 
2961
- :where([data-edit-sortable], [data-edit-movable]):focus-visible {
2962
- outline: 2px solid var(--edit-accent, var(--color-brand-content));
2963
- outline-offset: 3px;
2972
+ :where([data-edit-grip][hidden]) {
2973
+ display: none;
2964
2974
  }
2965
2975
 
2966
- /* Lifted out of the flow and following the pointer. */
2967
- :where([data-edit-sortable][data-edit-dragging]) {
2976
+ /* Lifted, following the pointer */
2977
+ :where([data-edit-dragging=""]) {
2968
2978
  z-index: 1000;
2969
2979
  cursor: grabbing;
2980
+ }
2981
+
2982
+ :where([data-edit-dragging=""]):where(:not([data-edit-area="bare"], [data-edit-area="bare"] *)) {
2970
2983
  box-shadow: 0 8px 24px rgb(0 0 0 / 0.18);
2971
2984
  }
2972
2985
 
2973
- /* The stand-in holding the slot the drop would land in — a translucent copy of
2974
- the element by default, because the clearest preview of where it lands is the
2975
- thing itself. Restyle it freely: hide its contents for an empty outlined slot,
2976
- give it a background, animate it. */
2986
+ /* Grabbed from the keyboard */
2987
+ :where([data-edit-dragging="keyboard"]):where(:not([data-edit-area="bare"], [data-edit-area="bare"] *)) {
2988
+ outline: 2px dashed var(--edit-accent, var(--color-brand-content));
2989
+ outline-offset: 3px;
2990
+ }
2991
+
2992
+ /* The stand-in holding the slot the drop would land in */
2977
2993
  :where([data-edit-ghost]) {
2978
2994
  opacity: var(--edit-ghost-opacity, 0.4);
2979
2995
  pointer-events: none;
2980
2996
  }
2981
2997
 
2982
- /* Valid cross-region destinations during a drag: a dashed invitation, and
2983
- enough height that an EMPTY region can be dropped onto at all. */
2984
- :where([data-edit-drop-target]) {
2998
+ :where([data-edit-area="bare"] [data-edit-ghost]) {
2999
+ opacity: 0;
3000
+ }
3001
+
3002
+ /* The container the drop would land in */
3003
+ :where(:has(> [data-edit-ghost])):where(:not([data-edit-area="bare"], [data-edit-area="bare"] *)) {
2985
3004
  outline: 1px dashed color-mix(in oklch, var(--edit-accent, var(--color-brand-content)) 55%, transparent);
2986
3005
  outline-offset: 4px;
3006
+ }
3007
+
3008
+ /* Other areas a drag can land in; an empty one still has a surface */
3009
+ :where([data-edit-drop-target]):where(:not([data-edit-area="bare"])) {
3010
+ min-height: 2.5rem;
3011
+ outline: 1px dashed color-mix(in oklch, var(--edit-accent, var(--color-brand-content)) 55%, transparent);
3012
+ outline-offset: 4px;
3013
+ }
3014
+
3015
+ /* While dragging: empty containers can be dropped into, nothing else reacts */
3016
+ :where([data-edit-area]:not([data-edit-area="bare"]):has([data-edit-dragging=""])) :where(:empty:not(img, input, br, hr, svg, video, canvas, iframe, textarea, [data-edit-ghost], [data-edit-handle], [data-edit-area="bare"], [data-edit-area="bare"] *)) {
2987
3017
  min-height: 2.5rem;
2988
3018
  }
2989
3019
 
2990
- /* Nothing else should react while a drag is in progress */
2991
- :where([data-edit-dragging-in]) {
3020
+ :where([data-edit-area]:has([data-edit-dragging=""])) {
2992
3021
  cursor: grabbing;
2993
3022
  user-select: none;
2994
3023
 
2995
- & :where([data-edit-sortable]:not([data-edit-dragging])) {
3024
+ & :where([data-edit-piece]:not([data-edit-dragging])) {
2996
3025
  cursor: grabbing;
2997
3026
  }
2998
3027
  }
2999
3028
 
3000
- :where([data-edit-grabbed]) {
3001
- outline: 2px dashed var(--edit-accent, var(--color-brand-content));
3002
- outline-offset: 3px;
3003
- }
3004
-
3005
- /* ---- Move (positioned children) ---- */
3006
- :where([data-edit-movable]) {
3007
- cursor: move;
3008
- touch-action: none;
3009
- }
3010
-
3011
- :where([data-edit-ui] [data-edit-movable], [data-edit-ui][data-edit-movable]):hover {
3012
- outline: 1px solid var(--edit-accent, var(--color-brand-content));
3013
- outline-offset: 2px;
3014
- }
3015
-
3016
- /* ---- Inline text ----
3017
- One weight everywhere: hover hints and the focused caret both use the same
3018
- 1px line, so focusing doesn't make the page jump a weight class. */
3019
- :where([data-edit-ui]) :where([data-edit-armed]) [contenteditable="true"],
3020
- :where([data-edit-ui])[data-edit-armed] [contenteditable="true"] {
3029
+ /* ---- Inline text ---- */
3030
+ :where([data-edit-area]:not([data-edit-area="bare"])) :where([contenteditable="true"], [data-edit-text]):where(:not([data-edit-area="bare"] *)),
3031
+ :where([data-edit-area]:is([contenteditable="true"], [data-edit-text]):not([data-edit-area="bare"])) {
3021
3032
  cursor: text;
3022
3033
  outline: 1px solid transparent;
3023
3034
  outline-offset: 2px;
3024
3035
  border-radius: 3px;
3025
3036
  transition: outline-color 0.12s ease;
3026
- }
3027
3037
 
3028
- :where([data-edit-ui]) :where([data-edit-armed]) [contenteditable="true"]:hover,
3029
- :where([data-edit-ui])[data-edit-armed] [contenteditable="true"]:hover {
3030
- outline-color: color-mix(in oklch, var(--edit-accent, var(--color-brand-content)) 45%, transparent);
3031
- }
3038
+ &:hover {
3039
+ outline-color: color-mix(in oklch, var(--edit-accent, var(--color-brand-content)) 45%, transparent);
3040
+ }
3032
3041
 
3033
- :where([data-edit-ui]) :where([data-edit-armed]) [contenteditable="true"]:focus,
3034
- :where([data-edit-ui])[data-edit-armed] [contenteditable="true"]:focus {
3035
- outline-color: var(--edit-accent, var(--color-brand-content));
3042
+ &:focus {
3043
+ outline-color: var(--edit-accent, var(--color-brand-content));
3044
+ }
3036
3045
  }
3037
3046
 
3038
- /* ---- Size handles ----
3039
- Injected as siblings of the element's own markup, so its native :hover and
3040
- :focus still fire and its body stays interactive. */
3041
- :where([data-edit-sizable]) {
3047
+ /* ---- Size handles ---- */
3048
+ :where(:has(> [data-edit-handle])) {
3042
3049
  position: relative;
3043
3050
  }
3044
3051
 
3045
- /* Handles reveal on approach rather than sitting on the element permanently.
3046
- The hairline is chrome, so it follows the [data-edit-ui] scope like every
3047
- other affordance; outside the scope the handles still work (hit areas and
3048
- resize cursors stay), they just draw nothing. */
3049
- :where([data-edit-sizable]) :where([data-edit-handle])::before {
3052
+ :where([data-edit-handle])::before {
3050
3053
  opacity: 0;
3051
3054
  transition: opacity 0.12s ease, background-color 0.15s ease;
3052
3055
  }
3053
3056
 
3054
- :where([data-edit-ui] [data-edit-sizable], [data-edit-ui][data-edit-sizable]):is(:hover, :focus-within) :where([data-edit-handle])::before {
3057
+ :where(:has(> [data-edit-handle])):is(:hover, :focus-within):where(:not([data-edit-area="bare"], [data-edit-area="bare"] *)) > :where([data-edit-handle])::before {
3055
3058
  opacity: 1;
3056
3059
  }
3057
3060
 
@@ -3059,9 +3062,9 @@
3059
3062
  position: absolute;
3060
3063
  z-index: 100;
3061
3064
  background: transparent;
3065
+ touch-action: none;
3062
3066
  --h: var(--edit-size-handle, 1rem);
3063
3067
 
3064
- /* Hairline, revealed on hover */
3065
3068
  &::before {
3066
3069
  content: '';
3067
3070
  position: absolute;
@@ -3081,11 +3084,10 @@
3081
3084
  }
3082
3085
  }
3083
3086
 
3084
- :where([data-edit-handle]):focus-visible {
3087
+ :where([data-edit-handle]):focus-visible:where(:not([data-edit-area="bare"], [data-edit-area="bare"] *)) {
3085
3088
  outline: 2px solid var(--edit-accent, var(--color-brand-content));
3086
3089
  }
3087
3090
 
3088
- /* Edges span their axis; corners are square. A corner value contains a hyphen. */
3089
3091
  :where([data-edit-handle="top"], [data-edit-handle="bottom"]) {
3090
3092
  left: 0;
3091
3093
  width: 100%;
@@ -3113,8 +3115,6 @@
3113
3115
  height: var(--h);
3114
3116
  }
3115
3117
 
3116
- /* Inset — each handle straddles its edge; a corner matches one rule per axis.
3117
- inset-inline-* carries the logical start/end values, so they flip for RTL. */
3118
3118
  :where([data-edit-handle^="top"]) {
3119
3119
  top: calc(var(--h) * -0.5);
3120
3120
  }
@@ -3139,7 +3139,6 @@
3139
3139
  inset-inline-end: calc(var(--h) * -0.5);
3140
3140
  }
3141
3141
 
3142
- /* Corner cursors; the logical pair flips with direction. */
3143
3142
  :where([data-edit-handle="top-left"], [data-edit-handle="bottom-right"], [data-edit-handle="top-start"], [data-edit-handle="bottom-end"]) {
3144
3143
  cursor: nwse-resize;
3145
3144
  }
@@ -3156,12 +3155,12 @@
3156
3155
  cursor: nwse-resize;
3157
3156
  }
3158
3157
 
3159
- /* Collapsed past --edit-size-collapse-* — authors restyle freely */
3160
- :where([data-edit-collapsed]) {
3161
- opacity: 0.45;
3158
+ /* Bare: handles keep their hit areas and cursors, draw nothing */
3159
+ :where([data-edit-area="bare"] [data-edit-handle])::before {
3160
+ content: none;
3162
3161
  }
3163
3162
 
3164
- /* Full-viewport capture layer during a size or move drag */
3163
+ /* Pointer capture layer during a resize */
3165
3164
  :where([data-edit-overlay]) {
3166
3165
  position: fixed;
3167
3166
  inset: 0;
@@ -3169,7 +3168,7 @@
3169
3168
  background: transparent;
3170
3169
  }
3171
3170
 
3172
- /* Screen-reader announcements (keyboard grab / move / drop) */
3171
+ /* Screen-reader announcements */
3173
3172
  :where([data-edit-live]) {
3174
3173
  position: absolute;
3175
3174
  width: 1px;
@@ -3184,69 +3183,13 @@
3184
3183
 
3185
3184
  @media (prefers-reduced-motion: reduce) {
3186
3185
 
3187
- :where([data-edit-armed]) > [draggable="true"],
3186
+ :where([data-edit-piece]),
3188
3187
  :where([data-edit-handle])::before {
3189
3188
  transition: none;
3190
3189
  }
3191
3190
  }
3192
3191
  }
3193
3192
 
3194
- /* ---- Authoring chrome (toolbar + class/scope menu) ---- */
3195
- @layer components {
3196
-
3197
- /* Presence is script's business — it knows which route is on screen. Whether it
3198
- is seen is not, so the toolbar is styled and revealed here. */
3199
- :where([data-edit-toolbar]) {
3200
- display: none;
3201
- position: fixed;
3202
- inset-block-end: 1rem;
3203
- inset-inline-end: 1rem;
3204
- z-index: 9999;
3205
- gap: 0.5rem;
3206
- align-items: center;
3207
-
3208
- & button[disabled] {
3209
- opacity: 0.35;
3210
- pointer-events: none;
3211
- }
3212
- }
3213
-
3214
- /* --edit-toolbar: none (any scope up to :root) suppresses it — e.g. a site
3215
- that demos .authoring regions but has its own publish flow. */
3216
- :root[data-edit-active] :where([data-edit-toolbar]) {
3217
- display: var(--edit-toolbar, flex);
3218
- }
3219
-
3220
- /* A popover: the top layer sits above every stacking context, so no handle,
3221
- overlay or z-index anywhere on the page can paint over it. */
3222
- :where([data-edit-menu]) {
3223
- position: fixed;
3224
- margin: 0;
3225
- width: 16rem;
3226
- padding: 0.6rem;
3227
- display: flex;
3228
- flex-direction: column;
3229
- gap: 0.4rem;
3230
- background: var(--color-surface-1);
3231
- border: 1px solid var(--color-line);
3232
- border-radius: var(--radius);
3233
- box-shadow: 0 8px 30px rgb(0 0 0 / 0.2);
3234
-
3235
- & input {
3236
- width: 100%;
3237
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
3238
- font-size: 0.75rem;
3239
- }
3240
-
3241
- & small {
3242
- font-size: 0.7rem;
3243
- text-transform: uppercase;
3244
- letter-spacing: 0.05em;
3245
- color: var(--color-content-subtle);
3246
- }
3247
- }
3248
- }
3249
-
3250
3193
  /* Manifest Forms */
3251
3194
 
3252
3195
  @layer base, components, utilities;
@@ -3911,6 +3854,260 @@
3911
3854
  }
3912
3855
  }
3913
3856
 
3857
+ /* Manifest Rich Text */
3858
+
3859
+ @layer base, components, utilities;
3860
+
3861
+ @layer components {
3862
+
3863
+ :where([data-rich-text]:not([data-edit-text])) {
3864
+ position: relative;
3865
+ overflow-y: auto;
3866
+ max-height: var(--rich-text-max-height, none);
3867
+ outline: none;
3868
+
3869
+ /* Document-wide styles (.all controls, $rich.all) */
3870
+ font-family: var(--rich-text-font, inherit);
3871
+ font-size: var(--rich-text-size, inherit);
3872
+ line-height: var(--rich-text-leading, inherit);
3873
+ text-align: var(--rich-text-align, start);
3874
+ color: var(--rich-text-color, inherit);
3875
+
3876
+ /* Placeholder overlays the first line */
3877
+ &[data-rich-text-empty]::before {
3878
+ content: attr(placeholder);
3879
+ position: absolute;
3880
+ inset-block-start: var(--rich-text-padding, 0.75rem);
3881
+ inset-inline: var(--rich-text-padding, 0.75rem);
3882
+ color: var(--color-content-subtle);
3883
+ pointer-events: none;
3884
+ }
3885
+ }
3886
+
3887
+ /* .all background on an unstyled area */
3888
+ :where([data-rich-text].unstyle[style*="--rich-text-background"]) {
3889
+ background: var(--rich-text-background);
3890
+ }
3891
+
3892
+ /* Unstyled: placeholder hugs the line */
3893
+ :where([data-rich-text].unstyle)[data-rich-text-empty]::before {
3894
+ inset-block-start: 0;
3895
+ inset-inline: 0;
3896
+ }
3897
+
3898
+ /* Field look; .unstyle drops it */
3899
+ :where([data-rich-text]:not(.unstyle, [data-edit-text])) {
3900
+ min-height: var(--rich-text-min-height, 8rem);
3901
+ padding: var(--rich-text-padding, 0.75rem);
3902
+ background: var(--rich-text-background, var(--color-surface-1));
3903
+ border: 1px solid var(--color-line);
3904
+ border-radius: var(--radius);
3905
+
3906
+ /* Held while a focus-taking control acts on the area */
3907
+ &:focus,
3908
+ &[data-rich-text-focused] {
3909
+ border-color: var(--color-content-subtle);
3910
+ }
3911
+ }
3912
+
3913
+ /* Single-line (.inline) */
3914
+ :where([data-rich-text-inline]:not(.unstyle, [data-edit-text])) {
3915
+ min-height: var(--rich-text-min-height, auto);
3916
+ }
3917
+
3918
+ /* ---- Selection menu (x-rich-text-menu) ---- */
3919
+ :where([data-rich-text-menu]) {
3920
+ position: fixed;
3921
+ margin: 0;
3922
+ inset: auto;
3923
+ left: var(--rich-text-selection-center);
3924
+ top: var(--rich-text-selection-y);
3925
+ transform: translate(-50%, calc(-100% - 0.5rem));
3926
+ gap: 0.25rem;
3927
+ align-items: center;
3928
+ padding: 0.25rem;
3929
+ background: var(--color-surface-1);
3930
+ border: 1px solid var(--color-line);
3931
+ border-radius: var(--radius);
3932
+ box-shadow: 0 8px 30px rgb(0 0 0 / 0.2);
3933
+ }
3934
+
3935
+ /* Display only while open */
3936
+ :where([data-rich-text-menu]:popover-open) {
3937
+ display: flex;
3938
+ }
3939
+
3940
+ /* No Popover API: hidden */
3941
+ @supports not selector(:popover-open) {
3942
+ :where([data-rich-text-menu]) {
3943
+ display: none;
3944
+ }
3945
+ }
3946
+
3947
+ /* ---- Controls ---- */
3948
+ :where([data-rich-text-control]) {
3949
+ &[data-rich-text-active] {
3950
+ background: color-mix(in oklch, var(--color-content-stark) 10%, transparent);
3951
+ color: var(--color-content-stark);
3952
+ }
3953
+
3954
+ & > svg {
3955
+ width: 1rem;
3956
+ height: 1rem;
3957
+ }
3958
+ }
3959
+
3960
+ /* Icon-only buttons */
3961
+ :where(button[data-rich-text-control]:has(> svg:only-child)) {
3962
+ padding: 0.35rem;
3963
+ line-height: 0;
3964
+ }
3965
+
3966
+ /* Disabled controls still catch the click, so the area keeps focus */
3967
+ :where([data-rich-text-control][aria-disabled=true]) {
3968
+ pointer-events: auto;
3969
+ }
3970
+
3971
+ /* ---- Editable content ---- */
3972
+ :where([data-rich-text]:not([data-edit-text])) {
3973
+
3974
+ & > * + * {
3975
+ margin-block-start: 0.75em;
3976
+ }
3977
+
3978
+ & :where(h1, h2, h3, h4, h5, h6) {
3979
+ font-weight: 600;
3980
+ line-height: 1.25;
3981
+ }
3982
+
3983
+ & h1 { font-size: 1.6em }
3984
+ & h2 { font-size: 1.35em }
3985
+ & h3 { font-size: 1.15em }
3986
+
3987
+ & :where(ul, ol) {
3988
+ padding-inline-start: 1.5em;
3989
+ }
3990
+
3991
+ & li {
3992
+ list-style: revert;
3993
+ }
3994
+
3995
+ & blockquote {
3996
+ padding-inline-start: 0.85em;
3997
+ border-inline-start: 2px solid var(--color-line);
3998
+ color: var(--color-content-neutral);
3999
+ }
4000
+
4001
+ & code {
4002
+ padding: 0.1em 0.3em;
4003
+ border-radius: 4px;
4004
+ font-size: 0.9em;
4005
+ background: color-mix(in oklch, var(--color-content-stark) 8%, transparent);
4006
+ }
4007
+
4008
+ & pre {
4009
+ padding: 0.75em;
4010
+ border-radius: var(--radius);
4011
+ overflow-x: auto;
4012
+ background: color-mix(in oklch, var(--color-content-stark) 8%, transparent);
4013
+
4014
+ & code {
4015
+ padding: 0;
4016
+ background: none;
4017
+ }
4018
+ }
4019
+
4020
+ & a {
4021
+ color: var(--color-brand-content);
4022
+ text-decoration: underline;
4023
+ }
4024
+
4025
+ & hr {
4026
+ margin-block: 1em;
4027
+ }
4028
+
4029
+ & img {
4030
+ max-width: 100%;
4031
+ }
4032
+
4033
+ & table {
4034
+ width: 100%;
4035
+ table-layout: fixed;
4036
+
4037
+ & :where(td, th) {
4038
+ padding: 0.35em 0.5em;
4039
+ border: 1px solid var(--color-line);
4040
+ vertical-align: top;
4041
+ }
4042
+
4043
+ & th {
4044
+ font-weight: 600;
4045
+ text-align: start;
4046
+ background: var(--color-surface-2);
4047
+ }
4048
+ }
4049
+
4050
+ /* Cell block selection */
4051
+ & :where(td, th)[data-rich-text-cell] {
4052
+ background: color-mix(in oklch, var(--color-brand-content) 18%, transparent);
4053
+ }
4054
+
4055
+ /* Table border resizing */
4056
+ &[data-rich-text-border="x"] { cursor: col-resize }
4057
+ &[data-rich-text-border="y"] { cursor: row-resize }
4058
+ &[data-rich-text-resizing] { user-select: none }
4059
+ &[data-rich-text-resizing="x"] { cursor: col-resize }
4060
+ &[data-rich-text-resizing="y"] { cursor: row-resize }
4061
+
4062
+ /* Task lists */
4063
+ & :where(ul[data-checklist]) {
4064
+ padding-inline-start: 0.25em;
4065
+ list-style: none;
4066
+
4067
+ & li {
4068
+ display: flex;
4069
+ align-items: baseline;
4070
+ gap: 0.5em;
4071
+ list-style: none;
4072
+ }
4073
+ }
4074
+
4075
+ & :where(dt) {
4076
+ font-weight: 600;
4077
+ }
4078
+
4079
+ & :where(dd) {
4080
+ margin-inline-start: 1.5em;
4081
+ }
4082
+
4083
+ & :where(kbd) {
4084
+ padding: 0.1em 0.35em;
4085
+ border: 1px solid var(--color-line);
4086
+ border-radius: 4px;
4087
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
4088
+ font-size: 0.85em;
4089
+ }
4090
+
4091
+ & :where(mark) {
4092
+ background: color-mix(in oklch, var(--color-brand-content) 25%, transparent);
4093
+ color: inherit;
4094
+ }
4095
+
4096
+ & :where(small) {
4097
+ font-size: 0.8em;
4098
+ }
4099
+
4100
+ & :where(figcaption) {
4101
+ font-size: 0.8em;
4102
+ color: var(--color-content-neutral);
4103
+ }
4104
+
4105
+ & :where(abbr, dfn) {
4106
+ text-decoration: underline dotted;
4107
+ }
4108
+ }
4109
+ }
4110
+
3914
4111
  /* Manifest Sidebars */
3915
4112
 
3916
4113
  @layer base, components, utilities;
@@ -4207,268 +4404,6 @@
4207
4404
  }
4208
4405
  }
4209
4406
 
4210
- /* Manifest Text Edit */
4211
-
4212
- @layer base, components, utilities;
4213
-
4214
- /* Self-contained. The editable area is a field first — it borrows the tokens inputs
4215
- and textareas use, so it sits in a form without looking bolted on. Controls are
4216
- styled where they are, not by where they sit, because they can be anywhere. */
4217
-
4218
- @layer components {
4219
-
4220
- :where([data-text-edit]) {
4221
- position: relative;
4222
- overflow-y: auto;
4223
- max-height: var(--text-edit-max-height, none);
4224
- outline: none;
4225
-
4226
- /* Page-level styling — set by .page controls, read back by $text.page.
4227
- Presentation, so it lives here rather than inside the stored markup. */
4228
- font-family: var(--text-edit-font, inherit);
4229
- font-size: var(--text-edit-size, inherit);
4230
- line-height: var(--text-edit-leading, inherit);
4231
- text-align: var(--text-edit-align, start);
4232
- color: var(--text-edit-color, inherit);
4233
-
4234
- /* Flagged from script: :empty never matches the <br> a contenteditable
4235
- keeps, and the tag holding it is not predictable after a wipe. The
4236
- placeholder OVERLAYS the first line (it is not a line of its own), so
4237
- the caret sits on top of it and nothing jumps when typing starts. */
4238
- &[data-text-edit-empty]::before {
4239
- content: attr(placeholder);
4240
- position: absolute;
4241
- inset-block-start: var(--text-edit-padding, 0.75rem);
4242
- inset-inline: var(--text-edit-padding, 0.75rem);
4243
- color: var(--color-content-subtle);
4244
- pointer-events: none;
4245
- }
4246
- }
4247
-
4248
- /* An unstyled area has no field padding, so its placeholder hugs the line. */
4249
- :where([data-text-edit].unstyle)[data-text-edit-empty]::before {
4250
- inset-block-start: 0;
4251
- inset-inline: 0;
4252
- }
4253
-
4254
- /* The FIELD look. `.unstyle` drops it so an area can sit seamlessly in a
4255
- page — a WYSIWYG document inherits its element's own type and colours;
4256
- everything above (caret custody, placeholder, commands) still works. */
4257
- :where([data-text-edit]:not(.unstyle)) {
4258
- min-height: var(--text-edit-min-height, 8rem);
4259
- padding: var(--text-edit-padding, 0.75rem);
4260
- background: var(--text-edit-background, var(--color-surface-1));
4261
- border: 1px solid var(--color-line);
4262
- border-radius: var(--radius);
4263
-
4264
- /* Held while the area owns the editing session — a <select> or colour
4265
- control takes NATIVE focus by design, and the ring must not flicker
4266
- off while the writer is mid-command. */
4267
- &:focus,
4268
- &[data-text-edit-focused] {
4269
- border-color: var(--color-content-subtle);
4270
- }
4271
- }
4272
-
4273
- /* ---- Selection menu (x-text-edit-menu) ----
4274
- Positioned by the --text-edit-selection-* variables the plugin writes to
4275
- :root, so the default needs no script; restyle or reposition freely. */
4276
- :where([data-text-edit-menu]) {
4277
- position: fixed;
4278
- margin: 0;
4279
- inset: auto;
4280
- left: var(--text-edit-selection-center);
4281
- top: var(--text-edit-selection-y);
4282
- transform: translate(-50%, calc(-100% - 0.5rem));
4283
- gap: 0.25rem;
4284
- align-items: center;
4285
- padding: 0.25rem;
4286
- background: var(--color-surface-1);
4287
- border: 1px solid var(--color-line);
4288
- border-radius: var(--radius);
4289
- box-shadow: 0 8px 30px rgb(0 0 0 / 0.2);
4290
- }
4291
-
4292
- /* display only while OPEN: an author display on the base rule would beat
4293
- the UA's closed-popover display:none, leaving the menu floating fixed
4294
- over the page before any selection exists. */
4295
- :where([data-text-edit-menu]:popover-open) {
4296
- display: flex;
4297
- }
4298
-
4299
- /* Without the Popover API the attribute is inert and the menu would render
4300
- permanently fixed on the page — hide it there; the bubble is progressive
4301
- enhancement. (In supporting browsers a closed popover is hidden natively.) */
4302
- @supports not selector(:popover-open) {
4303
- :where([data-text-edit-menu]) {
4304
- display: none;
4305
- }
4306
- }
4307
-
4308
- /* ---- Controls ----
4309
- A control is marked wherever it lives, so a toolbar is optional markup and
4310
- never a requirement. The reset already dims [aria-disabled=true]. */
4311
- :where([data-text-edit-control]) {
4312
- &[data-text-edit-active] {
4313
- background: color-mix(in oklch, var(--color-content-stark) 10%, transparent);
4314
- color: var(--color-content-stark);
4315
- }
4316
-
4317
- & > svg {
4318
- width: 1rem;
4319
- height: 1rem;
4320
- }
4321
- }
4322
-
4323
- :where(button[data-text-edit-control]) {
4324
- padding: 0.35rem;
4325
- line-height: 0;
4326
- }
4327
-
4328
- /* ---- Editable content ----
4329
- The editor authors real block elements, so style them as elements. Deliberately
4330
- lighter than the .prose class, which sets a reading measure this field can't use. */
4331
- :where([data-text-edit]) {
4332
-
4333
- & > * + * {
4334
- margin-block-start: 0.75em;
4335
- }
4336
-
4337
- & :where(h1, h2, h3, h4, h5, h6) {
4338
- font-weight: 600;
4339
- line-height: 1.25;
4340
- }
4341
-
4342
- & h1 { font-size: 1.6em }
4343
- & h2 { font-size: 1.35em }
4344
- & h3 { font-size: 1.15em }
4345
-
4346
- & :where(ul, ol) {
4347
- padding-inline-start: 1.5em;
4348
- }
4349
-
4350
- & li {
4351
- list-style: revert;
4352
- }
4353
-
4354
- & blockquote {
4355
- padding-inline-start: 0.85em;
4356
- border-inline-start: 2px solid var(--color-line);
4357
- color: var(--color-content-neutral);
4358
- }
4359
-
4360
- & code {
4361
- padding: 0.1em 0.3em;
4362
- border-radius: 4px;
4363
- font-size: 0.9em;
4364
- background: color-mix(in oklch, var(--color-content-stark) 8%, transparent);
4365
- }
4366
-
4367
- & pre {
4368
- padding: 0.75em;
4369
- border-radius: var(--radius);
4370
- overflow-x: auto;
4371
- background: color-mix(in oklch, var(--color-content-stark) 8%, transparent);
4372
-
4373
- & code {
4374
- padding: 0;
4375
- background: none;
4376
- }
4377
- }
4378
-
4379
- & a {
4380
- color: var(--color-brand-content);
4381
- text-decoration: underline;
4382
- }
4383
-
4384
- & hr {
4385
- margin-block: 1em;
4386
- }
4387
-
4388
- & img {
4389
- max-width: 100%;
4390
- }
4391
-
4392
- & table {
4393
- width: 100%;
4394
- table-layout: fixed;
4395
-
4396
- & :where(td, th) {
4397
- padding: 0.35em 0.5em;
4398
- border: 1px solid var(--color-line);
4399
- vertical-align: top;
4400
- }
4401
-
4402
- & th {
4403
- font-weight: 600;
4404
- text-align: start;
4405
- background: var(--color-surface-2);
4406
- }
4407
- }
4408
-
4409
- /* A block selection across cells. The browser can only highlight text, so an
4410
- empty cell shows nothing — this is what makes a spreadsheet-style
4411
- selection visible. */
4412
- & :where(td, th)[data-text-edit-cell] {
4413
- background: color-mix(in oklch, var(--color-brand-content) 18%, transparent);
4414
- }
4415
-
4416
- /* Borders read as grabbable only when the pointer is on one */
4417
- &[data-text-edit-border="x"] { cursor: col-resize }
4418
- &[data-text-edit-border="y"] { cursor: row-resize }
4419
- &[data-text-edit-resizing] { user-select: none }
4420
- &[data-text-edit-resizing="x"] { cursor: col-resize }
4421
- &[data-text-edit-resizing="y"] { cursor: row-resize }
4422
-
4423
- /* Task lists — the checkbox replaces the marker */
4424
- & :where(ul[data-checklist]) {
4425
- padding-inline-start: 0.25em;
4426
- list-style: none;
4427
-
4428
- & li {
4429
- display: flex;
4430
- align-items: baseline;
4431
- gap: 0.5em;
4432
- list-style: none;
4433
- }
4434
- }
4435
-
4436
- & :where(dt) {
4437
- font-weight: 600;
4438
- }
4439
-
4440
- & :where(dd) {
4441
- margin-inline-start: 1.5em;
4442
- }
4443
-
4444
- & :where(kbd) {
4445
- padding: 0.1em 0.35em;
4446
- border: 1px solid var(--color-line);
4447
- border-radius: 4px;
4448
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
4449
- font-size: 0.85em;
4450
- }
4451
-
4452
- & :where(mark) {
4453
- background: color-mix(in oklch, var(--color-brand-content) 25%, transparent);
4454
- color: inherit;
4455
- }
4456
-
4457
- & :where(small) {
4458
- font-size: 0.8em;
4459
- }
4460
-
4461
- & :where(figcaption) {
4462
- font-size: 0.8em;
4463
- color: var(--color-content-neutral);
4464
- }
4465
-
4466
- & :where(abbr, dfn) {
4467
- text-decoration: underline dotted;
4468
- }
4469
- }
4470
- }
4471
-
4472
4407
  /* ManifestToasts */
4473
4408
 
4474
4409
  @layer base, components, utilities;