@openpresentation/opf-editor 0.24.2 → 0.25.0

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/dist/styles.css CHANGED
@@ -570,6 +570,787 @@
570
570
  .opf-handoff *::after { transition: none !important; animation: none !important; }
571
571
  }
572
572
 
573
+ /* layout-editor.css */
574
+ /* Layout editor (RR-99): palette, canvas, layers and inspector. Only --opf-ui-* tokens (src/styles/tokens.css); the few --opf-lx-* variables
575
+ below are sizes local to this file. Prefix: opf-lx-. */
576
+
577
+ .opf-lx,
578
+ .opf-lx-palette,
579
+ .opf-lx-canvas,
580
+ .opf-lx-layers,
581
+ .opf-lx-inspector {
582
+ --opf-lx-h: var(--opf-ui-control-h);
583
+ --opf-lx-row: calc(var(--opf-ui-control-h) - 4px);
584
+ --opf-lx-indent: 14px;
585
+ --opf-lx-slot: 20px;
586
+ --opf-lx-pad: 16px;
587
+ --opf-lx-chip: calc(var(--opf-ui-control-h) - 4px);
588
+ font-family: var(--opf-ui-font);
589
+ font-size: 13px;
590
+ color: var(--opf-ui-fg);
591
+ }
592
+ .opf-lx [hidden],
593
+ .opf-lx-palette [hidden],
594
+ .opf-lx-canvas [hidden],
595
+ .opf-lx-layers [hidden],
596
+ .opf-lx-inspector [hidden] { display: none !important; }
597
+ .opf-lx button,
598
+ .opf-lx-palette button,
599
+ .opf-lx-canvas button,
600
+ .opf-lx-layers button,
601
+ .opf-lx-inspector button { font: inherit; color: inherit; }
602
+ .opf-lx-visually-hidden {
603
+ position: absolute;
604
+ width: 1px;
605
+ height: 1px;
606
+ margin: -1px;
607
+ padding: 0;
608
+ overflow: hidden;
609
+ clip-path: inset(50%);
610
+ white-space: nowrap;
611
+ }
612
+
613
+ /* The composed editor */
614
+ .opf-lx {
615
+ display: flex;
616
+ flex-direction: column;
617
+ min-width: 0;
618
+ height: 100%;
619
+ min-height: 480px;
620
+ background: var(--opf-ui-bg);
621
+ border: 1px solid var(--opf-ui-border);
622
+ border-radius: var(--opf-ui-radius-md);
623
+ overflow: hidden;
624
+ }
625
+ .opf-lx-topbar {
626
+ display: flex;
627
+ align-items: center;
628
+ gap: 12px;
629
+ flex: none;
630
+ min-height: calc(var(--opf-ui-control-h) + 12px);
631
+ padding: 6px 10px;
632
+ background: var(--opf-ui-surface);
633
+ border-bottom: 1px solid var(--opf-ui-border);
634
+ }
635
+ .opf-lx-history { display: inline-flex; gap: 2px; }
636
+ .opf-lx-top-button {
637
+ display: inline-flex;
638
+ align-items: center;
639
+ justify-content: center;
640
+ width: var(--opf-lx-h);
641
+ height: var(--opf-lx-h);
642
+ padding: 0;
643
+ background: transparent;
644
+ border: 0;
645
+ border-radius: var(--opf-ui-radius);
646
+ color: var(--opf-ui-muted-fg);
647
+ cursor: pointer;
648
+ transition: color var(--opf-ui-ease), background-color var(--opf-ui-ease);
649
+ }
650
+ .opf-lx-top-button:hover:not(:disabled) { color: var(--opf-ui-fg); background: var(--opf-ui-muted); }
651
+ .opf-lx-top-button:disabled { opacity: 0.4; cursor: default; }
652
+ .opf-lx-doc-name { display: flex; align-items: baseline; gap: 8px; flex: 1; min-width: 0; overflow: hidden; }
653
+ .opf-lx-doc-title { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
654
+ .opf-lx-doc-id { font: 11.5px var(--opf-ui-mono); color: var(--opf-ui-muted-fg); white-space: nowrap; }
655
+ .opf-lx-validity {
656
+ display: inline-flex;
657
+ align-items: center;
658
+ gap: 6px;
659
+ height: calc(var(--opf-lx-h) - 6px);
660
+ padding: 0 10px;
661
+ background: transparent;
662
+ border: 1px solid var(--opf-ui-border);
663
+ border-radius: var(--opf-ui-radius);
664
+ font: 11.5px var(--opf-ui-mono);
665
+ color: var(--opf-ui-success);
666
+ cursor: default;
667
+ }
668
+ .opf-lx-validity[data-state="invalid"] { color: var(--opf-ui-danger); border-color: var(--opf-ui-danger); cursor: pointer; }
669
+ .opf-lx-validity:disabled { opacity: 1; }
670
+ .opf-lx-main {
671
+ display: grid;
672
+ grid-template-columns: auto minmax(0, 1fr) minmax(260px, 320px);
673
+ flex: 1;
674
+ min-height: 0;
675
+ }
676
+ .opf-lx-palette-host { display: flex; min-height: 0; }
677
+ .opf-lx-canvas-host { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
678
+ .opf-lx-canvas-host > .opf-lx-canvas { flex: 1; }
679
+ .opf-lx-side {
680
+ display: flex;
681
+ flex-direction: column;
682
+ min-width: 0;
683
+ min-height: 0;
684
+ background: var(--opf-ui-surface);
685
+ border-left: 1px solid var(--opf-ui-border);
686
+ }
687
+ .opf-lx-side > .opf-lx-panel { display: flex; flex-direction: column; min-height: 0; }
688
+ .opf-lx-side > .opf-lx-panel[data-panel="layers"] { flex: 0 1 42%; border-bottom: 1px solid var(--opf-ui-border); }
689
+ .opf-lx-side > .opf-lx-panel[data-panel="inspector"] { flex: 1 1 58%; }
690
+ .opf-lx-side .opf-lx-layers,
691
+ .opf-lx-side .opf-lx-inspector { flex: 1; min-height: 0; }
692
+ .opf-lx-tabs { display: none; }
693
+
694
+ /* Narrow container: the palette is a row above the canvas; Layers and Inspector are tabs under it. */
695
+ .opf-lx[data-compact="true"] { min-height: 0; height: auto; }
696
+ .opf-lx[data-compact="true"] .opf-lx-main { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto auto; }
697
+ .opf-lx[data-compact="true"] .opf-lx-palette-host { overflow-x: auto; border-bottom: 1px solid var(--opf-ui-border); }
698
+ .opf-lx[data-compact="true"] .opf-lx-palette { flex-direction: row; flex: 1; padding: 4px 8px; border-right: 0; }
699
+ .opf-lx[data-compact="true"] .opf-lx-tool-gap { width: 1px; height: auto; margin: 4px; }
700
+ .opf-lx[data-compact="true"] .opf-lx-viewport { min-height: 220px; }
701
+ .opf-lx[data-compact="true"] .opf-lx-side { border-left: 0; border-top: 1px solid var(--opf-ui-border); }
702
+ .opf-lx[data-compact="true"] .opf-lx-tabs {
703
+ display: flex;
704
+ gap: 0;
705
+ border-bottom: 1px solid var(--opf-ui-border);
706
+ }
707
+ .opf-lx-tab {
708
+ flex: 1;
709
+ height: var(--opf-lx-h);
710
+ background: transparent;
711
+ border: 0;
712
+ border-bottom: 2px solid transparent;
713
+ color: var(--opf-ui-muted-fg);
714
+ font: inherit;
715
+ font-weight: 500;
716
+ cursor: pointer;
717
+ transition: color var(--opf-ui-ease), border-color var(--opf-ui-ease);
718
+ }
719
+ .opf-lx-tab:hover { color: var(--opf-ui-fg); }
720
+ .opf-lx-tab[aria-selected="true"] { color: var(--opf-ui-accent-strong); border-bottom-color: var(--opf-ui-accent); }
721
+ .opf-lx[data-compact="true"] .opf-lx-side > .opf-lx-panel { flex: none; border-bottom: 0; max-height: 360px; }
722
+ .opf-lx[data-compact="true"][data-panel="layers"] .opf-lx-panel[data-panel="inspector"],
723
+ .opf-lx[data-compact="true"][data-panel="inspector"] .opf-lx-panel[data-panel="layers"] { display: none; }
724
+
725
+ /* Tool palette */
726
+ .opf-lx-palette {
727
+ display: flex;
728
+ flex-direction: column;
729
+ align-items: center;
730
+ gap: 2px;
731
+ padding: 8px 6px;
732
+ background: var(--opf-ui-surface);
733
+ border-right: 1px solid var(--opf-ui-border);
734
+ }
735
+ .opf-lx-tool {
736
+ display: inline-flex;
737
+ align-items: center;
738
+ justify-content: center;
739
+ flex: none;
740
+ width: var(--opf-lx-h);
741
+ height: var(--opf-lx-h);
742
+ padding: 0;
743
+ background: transparent;
744
+ border: 1px solid transparent;
745
+ border-radius: var(--opf-ui-radius);
746
+ color: var(--opf-ui-muted-fg);
747
+ cursor: pointer;
748
+ transition: color var(--opf-ui-ease), background-color var(--opf-ui-ease), border-color var(--opf-ui-ease);
749
+ }
750
+ .opf-lx-tool:hover:not(:disabled) { color: var(--opf-ui-fg); background: var(--opf-ui-muted); }
751
+ .opf-lx-tool.is-active,
752
+ .opf-lx-tool[aria-pressed="true"] {
753
+ color: var(--opf-ui-accent-strong);
754
+ background: color-mix(in srgb, var(--opf-ui-accent) 10%, transparent);
755
+ border-color: color-mix(in srgb, var(--opf-ui-accent) 40%, transparent);
756
+ }
757
+ .opf-lx-tool:disabled { opacity: 0.4; cursor: default; }
758
+ .opf-lx-tool-gap { align-self: stretch; height: 1px; margin: 4px 2px; background: var(--opf-ui-border); }
759
+
760
+ /* Canvas */
761
+ .opf-lx-canvas {
762
+ position: relative;
763
+ display: flex;
764
+ flex-direction: column;
765
+ min-width: 0;
766
+ min-height: 0;
767
+ height: 100%;
768
+ background: var(--opf-ui-muted-2);
769
+ }
770
+ .opf-lx-viewport {
771
+ display: flex;
772
+ flex: 1;
773
+ min-height: 320px;
774
+ container-type: size;
775
+ overflow: auto;
776
+ }
777
+ .opf-lx-stage { flex: none; margin: auto; padding: var(--opf-lx-pad); }
778
+ .opf-lx-frame {
779
+ position: relative;
780
+ flex: none;
781
+ width: calc(min(100cqw - 2 * var(--opf-lx-pad), (100cqh - 2 * var(--opf-lx-pad)) * 16 / 9) * var(--opf-lx-zoom, 1));
782
+ min-width: 160px;
783
+ aspect-ratio: 16 / 9;
784
+ background: var(--opf-ui-surface);
785
+ border: 1px solid var(--opf-ui-border-strong);
786
+ touch-action: none;
787
+ -webkit-user-select: none;
788
+ user-select: none;
789
+ }
790
+ .opf-lx-frame:focus-visible { outline: 2px solid var(--opf-ui-ring); outline-offset: 2px; }
791
+ .opf-lx-render { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
792
+ .opf-lx-render svg { display: block; width: 100%; height: 100%; }
793
+ .opf-lx-content { position: absolute; inset: 8% 4.5%; }
794
+ .opf-lx-layer { position: absolute; inset: 0; pointer-events: none; }
795
+ .opf-lx-overlay { position: absolute; inset: 0; z-index: 12; pointer-events: none; }
796
+ .opf-lx-overlay > * { pointer-events: auto; }
797
+ .opf-lx-canvas[data-tool="select"] .opf-lx-content { cursor: default; }
798
+ .opf-lx-canvas[data-tool="split-row"] .opf-lx-content,
799
+ .opf-lx-canvas[data-tool="split-column"] .opf-lx-content { cursor: crosshair; }
800
+ .opf-lx-canvas[data-tool="hand"] .opf-lx-viewport,
801
+ .opf-lx-canvas[data-space="true"] .opf-lx-viewport { cursor: grab; }
802
+ .opf-lx-canvas[data-panning="true"] .opf-lx-viewport { cursor: grabbing; }
803
+ .opf-lx-canvas[data-tool="hand"] .opf-lx-content,
804
+ .opf-lx-canvas[data-space="true"] .opf-lx-content { cursor: grab; }
805
+
806
+ .opf-lx-implicit {
807
+ position: absolute;
808
+ display: flex;
809
+ align-items: center;
810
+ justify-content: center;
811
+ border: 1px dashed var(--opf-ui-border-strong);
812
+ border-radius: var(--opf-ui-radius-sm);
813
+ color: var(--opf-ui-muted-fg);
814
+ font: 10.5px var(--opf-ui-mono);
815
+ letter-spacing: 0.08em;
816
+ text-transform: uppercase;
817
+ pointer-events: none;
818
+ }
819
+
820
+ .opf-lx-node {
821
+ position: absolute;
822
+ display: block;
823
+ background: var(--opf-ui-muted-2);
824
+ border: 1.5px solid var(--opf-ui-border-strong);
825
+ border-radius: var(--opf-ui-radius-sm);
826
+ pointer-events: none;
827
+ transition: background-color var(--opf-ui-ease), border-color var(--opf-ui-ease);
828
+ }
829
+ .opf-lx-node[data-kind="split"] {
830
+ background: transparent;
831
+ border: 0;
832
+ outline: 1.5px dashed var(--opf-ui-border-strong);
833
+ outline-offset: 4px;
834
+ border-radius: var(--opf-ui-radius);
835
+ overflow: visible;
836
+ }
837
+ .opf-lx-node[data-heading="true"] { background: var(--opf-ui-muted); }
838
+ .opf-lx-node[data-hover="true"] { border-color: var(--opf-ui-accent); }
839
+ .opf-lx-node[data-kind="split"][data-hover="true"] { outline-color: var(--opf-ui-accent); }
840
+ .opf-lx-node.is-selected {
841
+ border-color: var(--opf-ui-accent);
842
+ border-style: solid;
843
+ border-width: 2px;
844
+ background: color-mix(in srgb, var(--opf-ui-accent) 10%, var(--opf-ui-muted-2));
845
+ }
846
+ .opf-lx-node[data-kind="split"].is-selected { background: color-mix(in srgb, var(--opf-ui-accent) 6%, transparent); outline: 2px solid var(--opf-ui-accent); border: 0; }
847
+ .opf-lx-node.is-dragging { opacity: 0.45; }
848
+ .opf-lx-node[data-into="true"] { border-color: var(--opf-ui-accent); border-style: solid; background: color-mix(in srgb, var(--opf-ui-accent) 8%, transparent); }
849
+ .opf-lx-node[data-kind="split"][data-into="true"] { outline: 2px solid var(--opf-ui-accent); border: 0; }
850
+ .opf-lx-node[data-finding="error"] { border-color: var(--opf-ui-danger); }
851
+ .opf-lx-node[data-kind="split"][data-finding="error"],
852
+ .opf-lx-node[data-kind="split"][data-finding="within"] { outline-color: var(--opf-ui-danger); }
853
+ .opf-lx-node:focus-visible { outline: 2px solid var(--opf-ui-ring); outline-offset: 2px; }
854
+ /* The chip: the region's name and size, outside the box's top edge, in the gutter between regions. A split's tag sits at its top right. */
855
+ .opf-lx-label {
856
+ --opf-lx-chip-h: 17px;
857
+ position: absolute;
858
+ bottom: calc(100% + 2px);
859
+ left: -2px;
860
+ z-index: 2;
861
+ display: block;
862
+ max-width: calc(100% + 3px);
863
+ height: var(--opf-lx-chip-h);
864
+ padding: 0 6px;
865
+ overflow: hidden;
866
+ text-overflow: ellipsis;
867
+ white-space: nowrap;
868
+ background: var(--opf-ui-surface);
869
+ border: 1px solid var(--opf-ui-border-strong);
870
+ border-bottom: 0;
871
+ border-radius: var(--opf-ui-radius-sm) var(--opf-ui-radius-sm) 0 0;
872
+ font: 500 11px/16px var(--opf-ui-mono);
873
+ color: var(--opf-ui-fg);
874
+ }
875
+ .opf-lx-label::before { content: attr(data-text); }
876
+ .opf-lx-label::after { content: " · " attr(data-size); font-weight: 400; color: var(--opf-ui-muted-fg); }
877
+ .opf-lx-node[data-heading="true"] > .opf-lx-label { background: var(--opf-ui-muted); }
878
+ .opf-lx-node[data-kind="split"] > .opf-lx-label {
879
+ bottom: calc(100% + 6px);
880
+ left: auto;
881
+ right: -2px;
882
+ max-width: 45%;
883
+ border-style: dashed;
884
+ border-bottom: 0;
885
+ background: var(--opf-ui-surface);
886
+ font-size: 10.5px;
887
+ font-weight: 400;
888
+ letter-spacing: 0.06em;
889
+ text-transform: uppercase;
890
+ color: var(--opf-ui-muted-fg);
891
+ }
892
+ .opf-lx-node.is-selected > .opf-lx-label {
893
+ background: color-mix(in srgb, var(--opf-ui-accent) 14%, var(--opf-ui-surface));
894
+ border-color: var(--opf-ui-accent);
895
+ color: var(--opf-ui-accent-strong);
896
+ }
897
+ .opf-lx-node[data-finding="error"] > .opf-lx-label { border-color: var(--opf-ui-danger); }
898
+ .opf-lx-badge { position: absolute; right: 6px; bottom: 4px; display: inline-flex; color: var(--opf-ui-danger); }
899
+ .opf-lx-wire {
900
+ position: absolute;
901
+ inset: 6px 6px 14px;
902
+ display: flex;
903
+ flex-wrap: wrap;
904
+ align-content: stretch;
905
+ gap: 4px;
906
+ overflow: hidden;
907
+ color: var(--opf-ui-muted-fg);
908
+ }
909
+ .opf-lx-wire-block {
910
+ display: flex;
911
+ flex: 1 1 72px;
912
+ align-items: center;
913
+ justify-content: center;
914
+ gap: 6px;
915
+ min-height: 26px;
916
+ background: var(--opf-ui-surface);
917
+ border: 1px dashed var(--opf-ui-border-strong);
918
+ border-radius: var(--opf-ui-radius-sm);
919
+ font: 10.5px var(--opf-ui-mono);
920
+ }
921
+ .opf-lx-wire-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
922
+ .opf-lx-wire-heading { flex-direction: column; justify-content: flex-start; flex-wrap: nowrap; gap: 4px; inset: 5px 8px 14px; }
923
+ .opf-lx-bar { display: block; flex: none; width: 45%; height: 6px; background: var(--opf-ui-border-strong); border-radius: var(--opf-ui-radius-sm); }
924
+ .opf-lx-bar-short { width: 30%; }
925
+ /* A heading row on a very small slide is shorter than the chips of the row under it; its placeholder bars give way. */
926
+ .opf-lx-node[data-heading="true"] { container-type: size; }
927
+ @container (max-height: 44px) { .opf-lx-wire-heading { display: none; } }
928
+ /* Rendered preview: the host's drawing shows through, the boxes become outlines. */
929
+ .opf-lx-canvas[data-rendered="true"] .opf-lx-node { background: transparent; }
930
+ .opf-lx-canvas[data-rendered="true"] .opf-lx-node.is-selected { background: color-mix(in srgb, var(--opf-ui-accent) 8%, transparent); }
931
+ .opf-lx-canvas[data-rendered="true"] .opf-lx-wire { display: none; }
932
+ .opf-lx-canvas[data-rendered="loading"] .opf-lx-frame { opacity: 0.7; }
933
+
934
+ .opf-lx-divider {
935
+ position: absolute;
936
+ z-index: 5;
937
+ pointer-events: auto;
938
+ background: transparent;
939
+ touch-action: none;
940
+ }
941
+ .opf-lx-divider::before { content: ""; position: absolute; }
942
+ .opf-lx-divider[data-orientation="vertical"] { cursor: col-resize; }
943
+ .opf-lx-divider[data-orientation="horizontal"] { cursor: row-resize; }
944
+ .opf-lx-divider[data-orientation="vertical"]::before { inset: 0 -6px; }
945
+ .opf-lx-divider[data-orientation="horizontal"]::before { inset: -6px 0; }
946
+ .opf-lx-divider::after { content: ""; position: absolute; background: transparent; border-radius: 2px; transition: background-color var(--opf-ui-ease); }
947
+ .opf-lx-divider[data-orientation="vertical"]::after { top: 4px; bottom: 4px; left: calc(50% - 1px); width: 2px; }
948
+ .opf-lx-divider[data-orientation="horizontal"]::after { left: 4px; right: 4px; top: calc(50% - 1px); height: 2px; }
949
+ .opf-lx-divider[data-fixed="false"]:hover::after,
950
+ .opf-lx-divider[data-fixed="false"]:focus-visible::after,
951
+ .opf-lx-divider[data-active="true"]::after { background: var(--opf-ui-accent); }
952
+ .opf-lx-divider[data-fixed="true"] { pointer-events: none; cursor: default; }
953
+ .opf-lx-divider:focus-visible { outline: 2px solid var(--opf-ui-ring); outline-offset: 2px; }
954
+ .opf-lx-canvas[data-tool="insert"] .opf-lx-divider,
955
+ .opf-lx-canvas[data-tool="split-row"] .opf-lx-divider,
956
+ .opf-lx-canvas[data-tool="split-column"] .opf-lx-divider,
957
+ .opf-lx-canvas[data-tool="hand"] .opf-lx-divider,
958
+ .opf-lx-canvas[data-dragging="true"] .opf-lx-divider { pointer-events: none; }
959
+ .opf-lx-ratio {
960
+ position: absolute;
961
+ z-index: 14;
962
+ padding: 2px 8px;
963
+ background: var(--opf-ui-accent);
964
+ border-radius: var(--opf-ui-radius-sm);
965
+ color: var(--opf-ui-accent-fg);
966
+ font: 500 11.5px var(--opf-ui-mono);
967
+ white-space: nowrap;
968
+ translate: -50% -50%;
969
+ pointer-events: none;
970
+ }
971
+
972
+ .opf-lx-slot {
973
+ position: absolute;
974
+ z-index: 8;
975
+ display: flex;
976
+ align-items: center;
977
+ justify-content: center;
978
+ padding: 0;
979
+ background: transparent;
980
+ border: 0;
981
+ color: var(--opf-ui-accent-strong);
982
+ cursor: pointer;
983
+ pointer-events: auto;
984
+ }
985
+ .opf-lx-slot::before { content: ""; position: absolute; background: var(--opf-ui-accent); opacity: 0.35; transition: opacity var(--opf-ui-ease); }
986
+ .opf-lx-slot[data-orientation="vertical"]::before { top: 0; bottom: 0; left: calc(50% - 1px); width: 2px; }
987
+ .opf-lx-slot[data-orientation="horizontal"]::before { left: 0; right: 0; top: calc(50% - 1px); height: 2px; }
988
+ .opf-lx-slot .opf-lx-icon {
989
+ position: relative;
990
+ padding: 2px;
991
+ background: var(--opf-ui-surface);
992
+ border: 1px solid var(--opf-ui-accent);
993
+ border-radius: 999px;
994
+ opacity: 0;
995
+ transition: opacity var(--opf-ui-ease);
996
+ }
997
+ .opf-lx-slot:hover::before,
998
+ .opf-lx-slot:focus-visible::before { opacity: 1; }
999
+ .opf-lx-slot:hover .opf-lx-icon,
1000
+ .opf-lx-slot:focus-visible .opf-lx-icon { opacity: 1; }
1001
+ .opf-lx-slot:disabled { cursor: not-allowed; opacity: 0.4; }
1002
+ .opf-lx-slot:focus-visible { outline: 2px solid var(--opf-ui-ring); outline-offset: 2px; }
1003
+
1004
+ .opf-lx-cut { position: absolute; border: 0 dashed var(--opf-ui-accent); pointer-events: none; }
1005
+ .opf-lx-cut[data-axis="row"] { border-left-width: 2px; }
1006
+ .opf-lx-cut[data-axis="column"] { border-top-width: 2px; }
1007
+ .opf-lx-drop { position: absolute; z-index: 13; background: var(--opf-ui-accent); border-radius: 2px; pointer-events: none; }
1008
+ .opf-lx-drop[data-orientation="vertical"] { width: 3px !important; translate: -50% 0; }
1009
+ .opf-lx-drop[data-orientation="horizontal"] { height: 3px !important; translate: 0 -50%; }
1010
+ .opf-lx-drop[data-state="refused"] { background: var(--opf-ui-danger); }
1011
+ .opf-lx-drop[data-state="same"] { background: var(--opf-ui-border-strong); }
1012
+ .opf-lx-ghost {
1013
+ position: absolute;
1014
+ z-index: 40;
1015
+ max-width: 220px;
1016
+ padding: 3px 10px;
1017
+ background: var(--opf-ui-surface);
1018
+ border: 1px solid var(--opf-ui-accent);
1019
+ border-radius: var(--opf-ui-radius);
1020
+ color: var(--opf-ui-accent-strong);
1021
+ font: 500 11.5px var(--opf-ui-mono);
1022
+ white-space: nowrap;
1023
+ overflow: hidden;
1024
+ text-overflow: ellipsis;
1025
+ pointer-events: none;
1026
+ }
1027
+ .opf-lx-rename {
1028
+ position: absolute;
1029
+ z-index: 16;
1030
+ height: 26px;
1031
+ padding: 0 6px;
1032
+ background: var(--opf-ui-surface);
1033
+ border: 2px solid var(--opf-ui-accent);
1034
+ border-radius: var(--opf-ui-radius-sm);
1035
+ color: var(--opf-ui-fg);
1036
+ font: 500 12px var(--opf-ui-mono);
1037
+ }
1038
+ .opf-lx-rename-row { position: static; flex: 1; min-width: 0; height: calc(var(--opf-lx-row) - 6px); }
1039
+
1040
+ .opf-lx-banner {
1041
+ display: flex;
1042
+ align-items: center;
1043
+ gap: 6px;
1044
+ margin: 0;
1045
+ padding: 6px 12px;
1046
+ background: var(--opf-ui-surface);
1047
+ border-bottom: 1px solid var(--opf-ui-danger);
1048
+ color: var(--opf-ui-danger);
1049
+ font-size: 12px;
1050
+ }
1051
+ .opf-lx-footer {
1052
+ display: flex;
1053
+ align-items: center;
1054
+ gap: 12px;
1055
+ flex: none;
1056
+ min-height: calc(var(--opf-lx-h) + 4px);
1057
+ padding: 2px 10px;
1058
+ background: var(--opf-ui-surface);
1059
+ border-top: 1px solid var(--opf-ui-border);
1060
+ }
1061
+ .opf-lx-status,
1062
+ .opf-lx-alert { flex: 1; min-width: 0; margin: 0; font: 11.5px var(--opf-ui-mono); overflow: hidden; text-overflow: ellipsis; }
1063
+ .opf-lx-status { color: var(--opf-ui-muted-fg); }
1064
+ .opf-lx-status[data-live="true"] { color: var(--opf-ui-fg); }
1065
+ .opf-lx-alert { color: var(--opf-ui-danger); }
1066
+ .opf-lx-alert:not([hidden]) + .opf-lx-zoombar { margin-left: 0; }
1067
+ .opf-lx-zoombar { display: inline-flex; align-items: center; gap: 2px; flex: none; }
1068
+ .opf-lx-zoom-label { min-width: 4ch; text-align: center; font: 11.5px var(--opf-ui-mono); color: var(--opf-ui-muted-fg); }
1069
+ .opf-lx-zoom-button {
1070
+ display: inline-flex;
1071
+ align-items: center;
1072
+ justify-content: center;
1073
+ width: calc(var(--opf-lx-h) - 4px);
1074
+ height: calc(var(--opf-lx-h) - 4px);
1075
+ padding: 0;
1076
+ background: transparent;
1077
+ border: 0;
1078
+ border-radius: var(--opf-ui-radius);
1079
+ color: var(--opf-ui-muted-fg);
1080
+ cursor: pointer;
1081
+ transition: color var(--opf-ui-ease), background-color var(--opf-ui-ease);
1082
+ }
1083
+ .opf-lx-zoom-button:hover { color: var(--opf-ui-fg); background: var(--opf-ui-muted); }
1084
+
1085
+ /* Menus: the context menu and the heading tool's menu */
1086
+ .opf-lx-menu {
1087
+ position: absolute;
1088
+ z-index: 60;
1089
+ min-width: 210px;
1090
+ padding: 4px;
1091
+ background: var(--opf-ui-surface);
1092
+ border: 1px solid var(--opf-ui-border);
1093
+ border-radius: var(--opf-ui-radius-lg);
1094
+ box-shadow: var(--opf-ui-shadow-pop);
1095
+ }
1096
+ .opf-lx-menuitem {
1097
+ display: flex;
1098
+ align-items: center;
1099
+ gap: 8px;
1100
+ width: 100%;
1101
+ min-height: var(--opf-lx-h);
1102
+ padding: 0 10px;
1103
+ background: transparent;
1104
+ border: 0;
1105
+ border-radius: var(--opf-ui-radius-sm);
1106
+ color: var(--opf-ui-fg);
1107
+ text-align: left;
1108
+ cursor: pointer;
1109
+ transition: background-color var(--opf-ui-ease), color var(--opf-ui-ease);
1110
+ }
1111
+ .opf-lx-menuitem:hover,
1112
+ .opf-lx-menuitem:focus-visible { background: var(--opf-ui-muted); }
1113
+ .opf-lx-menuitem:focus-visible { outline-offset: -2px; }
1114
+ .opf-lx-menuitem[aria-disabled="true"] { color: var(--opf-ui-muted-fg); opacity: 0.55; cursor: default; }
1115
+ .opf-lx-menu-label { flex: 1; }
1116
+ .opf-lx-menu-hint { font: 11.5px var(--opf-ui-mono); color: var(--opf-ui-muted-fg); }
1117
+ .opf-lx-menuitem[aria-checked="true"] .opf-lx-icon { color: var(--opf-ui-accent-strong); }
1118
+
1119
+ /* Panels (layers and inspector) */
1120
+ .opf-lx-layers,
1121
+ .opf-lx-inspector {
1122
+ display: flex;
1123
+ flex-direction: column;
1124
+ min-width: 0;
1125
+ min-height: 0;
1126
+ background: var(--opf-ui-surface);
1127
+ }
1128
+ .opf-lx-panel-head {
1129
+ display: flex;
1130
+ align-items: center;
1131
+ gap: 8px;
1132
+ flex: none;
1133
+ min-height: calc(var(--opf-lx-h) + 2px);
1134
+ padding: 0 12px;
1135
+ border-bottom: 1px solid var(--opf-ui-border);
1136
+ color: var(--opf-ui-muted-fg);
1137
+ }
1138
+ .opf-lx-panel-title { margin: 0; font: 500 10.5px var(--opf-ui-mono); letter-spacing: 0.08em; text-transform: uppercase; }
1139
+
1140
+ /* Layers */
1141
+ .opf-lx-layers-scroll { position: relative; flex: 1; min-height: 0; overflow: auto; padding: 4px 0; }
1142
+ .opf-lx-tree,
1143
+ .opf-lx-group { margin: 0; padding: 0; list-style: none; }
1144
+ .opf-lx-item { outline: none; }
1145
+ .opf-lx-row {
1146
+ display: flex;
1147
+ align-items: center;
1148
+ gap: 4px;
1149
+ min-height: var(--opf-lx-row);
1150
+ padding-inline-end: 8px;
1151
+ border-radius: var(--opf-ui-radius-sm);
1152
+ color: var(--opf-ui-fg);
1153
+ cursor: default;
1154
+ -webkit-user-select: none;
1155
+ user-select: none;
1156
+ transition: background-color var(--opf-ui-ease), color var(--opf-ui-ease);
1157
+ }
1158
+ .opf-lx-row:hover { background: var(--opf-ui-muted-2); }
1159
+ .opf-lx-row[data-selected="true"] { background: color-mix(in srgb, var(--opf-ui-accent) 10%, transparent); color: var(--opf-ui-accent-strong); }
1160
+ .opf-lx-item:focus-visible > .opf-lx-row { outline: 2px solid var(--opf-ui-ring); outline-offset: -2px; }
1161
+ .opf-lx-item.is-dragging > .opf-lx-row { opacity: 0.45; }
1162
+ .opf-lx-item[data-into="true"] > .opf-lx-row { outline: 2px solid var(--opf-ui-accent); outline-offset: -2px; }
1163
+ .opf-lx-grip { display: inline-flex; width: 14px; flex: none; color: var(--opf-ui-muted-fg); opacity: 0; cursor: grab; touch-action: none; }
1164
+ .opf-lx-row:hover .opf-lx-grip,
1165
+ .opf-lx-item:focus-visible > .opf-lx-row .opf-lx-grip { opacity: 1; }
1166
+ .opf-lx-layers[data-density="touch"] .opf-lx-grip { opacity: 1; width: 24px; justify-content: center; }
1167
+ .opf-lx-caret { display: inline-flex; width: 14px; flex: none; color: var(--opf-ui-muted-fg); }
1168
+ .opf-lx-row .opf-lx-icon { flex: none; color: var(--opf-ui-muted-fg); }
1169
+ .opf-lx-row[data-selected="true"] .opf-lx-icon { color: var(--opf-ui-accent-strong); }
1170
+ .opf-lx-row-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1171
+ .opf-lx-item[data-kind="region"] > .opf-lx-row > .opf-lx-row-name { font-family: var(--opf-ui-mono); font-size: 12px; }
1172
+ .opf-lx-row-size { flex: none; font: 11.5px var(--opf-ui-mono); color: var(--opf-ui-muted-fg); }
1173
+ .opf-lx-row-flag { display: inline-flex; flex: none; color: var(--opf-ui-danger); }
1174
+ .opf-lx-row[data-finding="error"] .opf-lx-row-name { text-decoration: underline wavy var(--opf-ui-danger); text-underline-offset: 3px; }
1175
+ .opf-lx-tree-drop { position: absolute; z-index: 5; border-top: 2px solid var(--opf-ui-accent); pointer-events: none; }
1176
+ .opf-lx-tree-drop[data-mode="into"] { border: 2px solid var(--opf-ui-accent); border-radius: var(--opf-ui-radius-sm); }
1177
+ .opf-lx-tree-drop[data-state="refused"] { border-color: var(--opf-ui-danger); }
1178
+ .opf-lx-tree-drop[data-state="same"] { border-color: var(--opf-ui-border-strong); }
1179
+
1180
+ .opf-lx-findings { flex: none; max-height: 40%; overflow: auto; border-top: 1px solid var(--opf-ui-border); }
1181
+ .opf-lx-findings-head {
1182
+ display: flex;
1183
+ align-items: center;
1184
+ gap: 6px;
1185
+ margin: 0;
1186
+ padding: 6px 12px;
1187
+ font: 11.5px var(--opf-ui-mono);
1188
+ color: var(--opf-ui-success);
1189
+ }
1190
+ .opf-lx-findings-head[data-state="error"] { color: var(--opf-ui-danger); }
1191
+ .opf-lx-findings-head[data-state="warning"] { color: var(--opf-ui-warn); }
1192
+ .opf-lx-findings-list { margin: 0; padding: 0 4px 6px; list-style: none; }
1193
+ .opf-lx-finding {
1194
+ display: flex;
1195
+ flex-direction: column;
1196
+ align-items: flex-start;
1197
+ gap: 2px;
1198
+ width: 100%;
1199
+ min-height: var(--opf-lx-row);
1200
+ padding: 4px 8px;
1201
+ background: transparent;
1202
+ border: 0;
1203
+ border-radius: var(--opf-ui-radius-sm);
1204
+ text-align: left;
1205
+ cursor: pointer;
1206
+ transition: background-color var(--opf-ui-ease);
1207
+ }
1208
+ .opf-lx-finding:hover { background: var(--opf-ui-muted-2); }
1209
+ .opf-lx-finding-message { color: var(--opf-ui-fg); }
1210
+ .opf-lx-finding-where { font: 11px var(--opf-ui-mono); color: var(--opf-ui-muted-fg); }
1211
+
1212
+ /* Inspector */
1213
+ .opf-lx-inspector-body { flex: 1; min-height: 0; padding: 12px; overflow: auto; }
1214
+ .opf-lx-section { display: flex; flex-direction: column; gap: 12px; }
1215
+ .opf-lx-section + .opf-lx-section,
1216
+ .opf-lx-section + .opf-lx-help,
1217
+ .opf-lx-help + .opf-lx-section { margin-top: 14px; }
1218
+ .opf-lx-section-title { margin: 0; font: 500 10.5px var(--opf-ui-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--opf-ui-muted-fg); }
1219
+ .opf-lx-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
1220
+ .opf-lx-label-text { font-size: 12px; font-weight: 500; color: var(--opf-ui-fg); }
1221
+ .opf-lx-help { margin: 0; font-size: 12px; line-height: 1.4; color: var(--opf-ui-muted-fg); }
1222
+ .opf-lx-field-error { display: flex; align-items: flex-start; gap: 6px; margin: 0; font-size: 12px; line-height: 1.4; color: var(--opf-ui-danger); }
1223
+ .opf-lx-field-error .opf-lx-icon { flex: none; margin-top: 2px; }
1224
+ .opf-lx-loose { display: flex; flex-direction: column; gap: 4px; margin: 14px 0 0; padding: 0; list-style: none; }
1225
+ .opf-lx-input,
1226
+ .opf-lx-select {
1227
+ width: 100%;
1228
+ min-width: 0;
1229
+ height: var(--opf-lx-h);
1230
+ padding: 0 8px;
1231
+ background: var(--opf-ui-surface);
1232
+ border: 1px solid var(--opf-ui-border-strong);
1233
+ border-radius: var(--opf-ui-radius);
1234
+ color: var(--opf-ui-fg);
1235
+ font: inherit;
1236
+ transition: border-color var(--opf-ui-ease);
1237
+ }
1238
+ textarea.opf-lx-input { height: auto; min-height: calc(var(--opf-lx-h) * 1.8); padding: 6px 8px; resize: vertical; line-height: 1.4; }
1239
+ .opf-lx-input:hover:not(:disabled),
1240
+ .opf-lx-select:hover { border-color: var(--opf-ui-muted-fg); }
1241
+ .opf-lx-input:disabled { background: var(--opf-ui-muted-2); color: var(--opf-ui-muted-fg); }
1242
+ .opf-lx-input[readonly] { background: var(--opf-ui-muted-2); color: var(--opf-ui-muted-fg); }
1243
+ .opf-lx-input[aria-invalid="true"] { border-color: var(--opf-ui-danger); }
1244
+ input.opf-lx-input[data-field="id"],
1245
+ input.opf-lx-input[data-field="name"],
1246
+ input.opf-lx-input[data-field="size"],
1247
+ input.opf-lx-input[data-field="max"] { font-family: var(--opf-ui-mono); font-size: 12.5px; }
1248
+ .opf-lx-size-row { display: flex; gap: 6px; }
1249
+ .opf-lx-size-input { flex: 1; }
1250
+ .opf-lx-field[data-invalid="true"] .opf-lx-input,
1251
+ .opf-lx-field[data-invalid="true"] .opf-lx-select { border-color: var(--opf-ui-danger); }
1252
+ .opf-lx-field-check { flex-direction: row; flex-wrap: wrap; align-items: center; column-gap: 8px; }
1253
+ .opf-lx-field-check .opf-lx-label-text { order: 2; }
1254
+ .opf-lx-field-check .opf-lx-check { order: 1; }
1255
+ .opf-lx-field-check .opf-lx-help,
1256
+ .opf-lx-field-check .opf-lx-field-error { order: 3; flex-basis: 100%; }
1257
+ .opf-lx-check { width: 16px; height: 16px; margin: 0; accent-color: var(--opf-ui-accent); }
1258
+ .opf-lx-segmented { display: inline-flex; align-self: flex-start; border: 1px solid var(--opf-ui-border-strong); border-radius: var(--opf-ui-radius); overflow: hidden; }
1259
+ .opf-lx-segment {
1260
+ display: inline-flex;
1261
+ align-items: center;
1262
+ gap: 6px;
1263
+ height: calc(var(--opf-lx-h) - 2px);
1264
+ padding: 0 12px;
1265
+ background: transparent;
1266
+ border: 0;
1267
+ border-radius: 0;
1268
+ color: var(--opf-ui-muted-fg);
1269
+ cursor: pointer;
1270
+ transition: color var(--opf-ui-ease), background-color var(--opf-ui-ease);
1271
+ }
1272
+ .opf-lx-segment + .opf-lx-segment { border-left: 1px solid var(--opf-ui-border-strong); }
1273
+ .opf-lx-segment:hover:not(:disabled) { color: var(--opf-ui-fg); background: var(--opf-ui-muted); }
1274
+ .opf-lx-segment[aria-pressed="true"] { color: var(--opf-ui-accent-strong); background: color-mix(in srgb, var(--opf-ui-accent) 10%, transparent); font-weight: 600; }
1275
+ .opf-lx-segment:focus-visible { outline-offset: -2px; }
1276
+ .opf-lx-segment:disabled { opacity: 0.45; cursor: default; }
1277
+ .opf-lx-auto { border: 1px solid var(--opf-ui-border-strong); border-radius: var(--opf-ui-radius); }
1278
+ .opf-lx-chips { display: flex; flex-wrap: wrap; gap: 6px; }
1279
+ .opf-lx-chip {
1280
+ display: inline-flex;
1281
+ align-items: center;
1282
+ gap: 6px;
1283
+ height: var(--opf-lx-chip);
1284
+ padding: 0 10px;
1285
+ background: var(--opf-ui-surface);
1286
+ border: 1px solid var(--opf-ui-border-strong);
1287
+ border-radius: var(--opf-ui-radius);
1288
+ color: var(--opf-ui-muted-fg);
1289
+ font: 11.5px var(--opf-ui-mono);
1290
+ cursor: pointer;
1291
+ transition: color var(--opf-ui-ease), background-color var(--opf-ui-ease), border-color var(--opf-ui-ease);
1292
+ }
1293
+ .opf-lx-chip:hover:not(:disabled) { color: var(--opf-ui-fg); background: var(--opf-ui-muted); }
1294
+ .opf-lx-chip[aria-pressed="true"] {
1295
+ color: var(--opf-ui-accent-strong);
1296
+ background: color-mix(in srgb, var(--opf-ui-accent) 10%, transparent);
1297
+ border-color: var(--opf-ui-accent);
1298
+ }
1299
+ .opf-lx-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
1300
+ .opf-lx-action {
1301
+ display: inline-flex;
1302
+ align-items: center;
1303
+ justify-content: flex-start;
1304
+ gap: 8px;
1305
+ min-width: 0;
1306
+ height: var(--opf-lx-h);
1307
+ padding: 0 10px;
1308
+ background: var(--opf-ui-surface);
1309
+ border: 1px solid var(--opf-ui-border);
1310
+ border-radius: var(--opf-ui-radius);
1311
+ color: var(--opf-ui-fg);
1312
+ cursor: pointer;
1313
+ transition: color var(--opf-ui-ease), background-color var(--opf-ui-ease), border-color var(--opf-ui-ease);
1314
+ }
1315
+ .opf-lx-action:hover:not(:disabled) { background: var(--opf-ui-muted); border-color: var(--opf-ui-border-strong); }
1316
+ .opf-lx-action:disabled { opacity: 0.45; cursor: default; }
1317
+ .opf-lx-action .opf-lx-button-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1318
+ .opf-lx-hints { display: flex; flex-direction: column; gap: 4px; margin: 0; }
1319
+ .opf-lx-hint-row { display: flex; align-items: center; gap: 8px; min-height: var(--opf-lx-row); }
1320
+ .opf-lx-hint-key { flex: none; margin: 0; font: 12px var(--opf-ui-mono); color: var(--opf-ui-accent-strong); }
1321
+ .opf-lx-hint-value { flex: 1; min-width: 0; margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: 12px var(--opf-ui-mono); color: var(--opf-ui-warn); }
1322
+ .opf-lx-hint-remove {
1323
+ display: inline-flex;
1324
+ align-items: center;
1325
+ justify-content: center;
1326
+ width: var(--opf-lx-row);
1327
+ height: var(--opf-lx-row);
1328
+ padding: 0;
1329
+ background: transparent;
1330
+ border: 0;
1331
+ border-radius: var(--opf-ui-radius-sm);
1332
+ color: var(--opf-ui-muted-fg);
1333
+ cursor: pointer;
1334
+ }
1335
+ .opf-lx-hint-remove:hover { color: var(--opf-ui-fg); background: var(--opf-ui-muted); }
1336
+
1337
+ /* Touch density: controls are 40px (the token), dividers and slots get a wider target. */
1338
+ .opf-lx[data-density="touch"] { --opf-lx-slot: 32px; }
1339
+ .opf-lx-canvas[data-density="touch"] { --opf-lx-slot: 32px; }
1340
+ .opf-lx-canvas[data-density="touch"] .opf-lx-divider[data-orientation="vertical"]::before { inset: 0 -14px; }
1341
+ .opf-lx-canvas[data-density="touch"] .opf-lx-divider[data-orientation="horizontal"]::before { inset: -14px 0; }
1342
+ .opf-lx-canvas[data-density="touch"] .opf-lx-divider[data-fixed="false"]::after { background: color-mix(in srgb, var(--opf-ui-accent) 45%, transparent); }
1343
+ .opf-lx-canvas[data-density="touch"] .opf-lx-label { --opf-lx-chip-h: 19px; font-size: 12px; line-height: 18px; }
1344
+ .opf-lx[data-density="touch"] .opf-lx-actions { grid-template-columns: minmax(0, 1fr); }
1345
+
1346
+ @media (prefers-reduced-motion: reduce) {
1347
+ .opf-lx *,
1348
+ .opf-lx-palette *,
1349
+ .opf-lx-canvas *,
1350
+ .opf-lx-layers *,
1351
+ .opf-lx-inspector * { transition: none !important; animation: none !important; }
1352
+ }
1353
+
573
1354
  /* navigator.css */
574
1355
  /* Slide navigator (RR-98). Uses only --opf-ui-* tokens. */
575
1356
  .opf-nav {
@@ -1856,9 +2637,15 @@
1856
2637
  object-fit: contain;
1857
2638
  }
1858
2639
 
1859
- .opf-layout-diagram {
1860
- display: grid;
2640
+ .opf-layout-diagram,
2641
+ .opf-layout-split {
2642
+ display: flex;
1861
2643
  gap: 3px;
2644
+ min-width: 0;
2645
+ min-height: 0;
2646
+ }
2647
+
2648
+ .opf-layout-diagram {
1862
2649
  aspect-ratio: 16 / 9;
1863
2650
  }
1864
2651
 
@@ -1866,6 +2653,7 @@
1866
2653
  display: grid;
1867
2654
  place-items: center;
1868
2655
  min-width: 0;
2656
+ padding: 2px 4px;
1869
2657
  overflow: hidden;
1870
2658
  font: 11px var(--opf-ui-mono);
1871
2659
  color: var(--opf-ui-accent-strong);
@@ -1890,52 +2678,69 @@
1890
2678
 
1891
2679
  .opf-grid-dimensions {
1892
2680
  display: grid;
1893
- grid-template-columns: 90px 90px 1fr;
2681
+ grid-template-columns: minmax(0, 220px);
1894
2682
  gap: 10px;
1895
2683
  }
1896
2684
 
1897
- .opf-custom-layout-grid {
1898
- display: grid;
1899
- gap: 2px;
2685
+ .opf-grid-structure {
1900
2686
  padding: 8px;
1901
2687
  background: var(--opf-ui-muted);
1902
2688
  border-radius: var(--opf-ui-radius);
1903
2689
  }
1904
2690
 
1905
- .opf-grid-cell {
1906
- min-width: 38px;
1907
- min-height: 38px;
1908
- padding: 2px;
1909
- font: 11px var(--opf-ui-mono);
1910
- color: var(--opf-ui-fg);
1911
- background: var(--opf-ui-surface);
1912
- border: 1px solid var(--opf-ui-border-strong);
1913
- border-radius: var(--opf-ui-radius-sm);
1914
- cursor: crosshair;
2691
+ .opf-grid-structure .opf-layout-diagram {
2692
+ max-width: 360px;
2693
+ margin: 0 auto;
1915
2694
  }
1916
2695
 
1917
- .opf-grid-cell[data-area="title"] {
1918
- color: var(--opf-ui-accent-strong);
1919
- background: color-mix(in srgb, var(--opf-ui-accent) 12%, var(--opf-ui-surface));
2696
+ .opf-grid-regions {
2697
+ display: grid;
2698
+ gap: 8px;
1920
2699
  }
1921
2700
 
1922
- .opf-grid-cell[data-area="."] {
1923
- color: var(--opf-ui-muted-fg);
1924
- background: var(--opf-ui-muted-2);
2701
+ .opf-grid-list-wrap {
2702
+ display: grid;
2703
+ gap: 6px;
2704
+ justify-items: start;
1925
2705
  }
1926
2706
 
1927
- .opf-grid-regions {
2707
+ .opf-grid-list {
1928
2708
  display: grid;
1929
- grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
1930
2709
  gap: 8px;
2710
+ width: 100%;
2711
+ margin: 0;
2712
+ padding: 0;
2713
+ list-style: none;
1931
2714
  }
1932
2715
 
1933
- .opf-grid-region {
2716
+ .opf-grid-region,
2717
+ .opf-grid-split {
2718
+ display: grid;
2719
+ gap: 6px;
1934
2720
  min-width: 0;
2721
+ margin: 0;
1935
2722
  border: 1px solid var(--opf-ui-border);
1936
2723
  border-radius: var(--opf-ui-radius);
1937
2724
  }
1938
2725
 
2726
+ .opf-grid-split {
2727
+ border-style: dashed;
2728
+ border-color: var(--opf-ui-border-strong);
2729
+ }
2730
+
2731
+ .opf-grid-controls,
2732
+ .opf-grid-rules {
2733
+ display: grid;
2734
+ grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
2735
+ gap: 8px;
2736
+ }
2737
+
2738
+ .opf-grid-tools {
2739
+ display: flex;
2740
+ flex-wrap: wrap;
2741
+ gap: 6px;
2742
+ }
2743
+
1939
2744
  .opf-grid-kinds {
1940
2745
  display: grid;
1941
2746
  grid-template-columns: repeat(3, 1fr);
@@ -2981,6 +3786,179 @@
2981
3786
  }
2982
3787
  }
2983
3788
 
3789
+ /* presenter.css */
3790
+ /* RR-98: the presenter and the Present button (src/presenter.js). Only --opf-ui-* tokens, no color literals (test/styles.mjs). */
3791
+
3792
+ /* ---- the presenter -------------------------------------------------------------------------------------------------------------------- */
3793
+ .opf-presenter,
3794
+ .opf-presenter *,
3795
+ .opf-presenter *::before,
3796
+ .opf-presenter *::after { box-sizing: border-box; }
3797
+ .opf-presenter[hidden] { display: none !important; }
3798
+
3799
+ .opf-presenter {
3800
+ position: fixed;
3801
+ inset: 0;
3802
+ z-index: 2000;
3803
+ display: flex;
3804
+ align-items: center;
3805
+ justify-content: center;
3806
+ overflow: hidden;
3807
+ /* Slides are letterboxed on black in every theme, so the bars never take a token's light or dark value. */
3808
+ background: black;
3809
+ font-family: var(--opf-ui-font);
3810
+ font-size: 13px;
3811
+ line-height: 1.4;
3812
+ color: var(--opf-ui-fg);
3813
+ user-select: none;
3814
+ -webkit-user-select: none;
3815
+ touch-action: none;
3816
+ outline: none;
3817
+ }
3818
+ .opf-presenter[data-chrome="hidden"] { cursor: none; }
3819
+
3820
+ .opf-presenter .opf-presenter-slide {
3821
+ width: 100%;
3822
+ height: 100%;
3823
+ display: flex;
3824
+ align-items: center;
3825
+ justify-content: center;
3826
+ }
3827
+ /* The slide's own width and height attributes give its shape (viewBox); this makes it as large as the screen allows. */
3828
+ .opf-presenter .opf-presenter-slide svg {
3829
+ display: block;
3830
+ width: 100%;
3831
+ height: 100%;
3832
+ max-width: 100%;
3833
+ max-height: 100%;
3834
+ }
3835
+ .opf-presenter .opf-presenter-message {
3836
+ position: absolute;
3837
+ margin: 0;
3838
+ max-width: 40ch;
3839
+ padding: 12px 16px;
3840
+ border: 1px solid var(--opf-ui-border);
3841
+ border-radius: var(--opf-ui-radius-md);
3842
+ background: var(--opf-ui-surface);
3843
+ color: var(--opf-ui-muted-fg);
3844
+ text-align: center;
3845
+ font: 400 13px/1.5 var(--opf-ui-font);
3846
+ }
3847
+ .opf-presenter .opf-presenter-message[hidden] { display: none; }
3848
+ .opf-presenter .opf-presenter-live {
3849
+ position: absolute;
3850
+ width: 1px;
3851
+ height: 1px;
3852
+ margin: -1px;
3853
+ padding: 0;
3854
+ overflow: hidden;
3855
+ clip-path: inset(50%);
3856
+ white-space: nowrap;
3857
+ border: 0;
3858
+ }
3859
+
3860
+ /* ---- the counter and the exit button (they appear on pointer move) ---------------------------------------------------------------------- */
3861
+ .opf-presenter .opf-presenter-counter,
3862
+ .opf-presenter .opf-presenter-close {
3863
+ position: absolute;
3864
+ background: var(--opf-ui-surface);
3865
+ color: var(--opf-ui-muted-fg);
3866
+ border: 1px solid var(--opf-ui-border);
3867
+ opacity: 0;
3868
+ transition: opacity var(--opf-ui-ease), color var(--opf-ui-ease), border-color var(--opf-ui-ease);
3869
+ }
3870
+ .opf-presenter[data-chrome="visible"] .opf-presenter-counter,
3871
+ .opf-presenter[data-chrome="visible"] .opf-presenter-close,
3872
+ .opf-presenter .opf-presenter-close:focus-visible { opacity: 1; }
3873
+
3874
+ .opf-presenter .opf-presenter-counter {
3875
+ bottom: 16px;
3876
+ left: 0;
3877
+ right: 0;
3878
+ width: max-content;
3879
+ margin: 0 auto;
3880
+ padding: 4px 10px;
3881
+ border-radius: var(--opf-ui-radius);
3882
+ font: 500 11.5px/1.4 var(--opf-ui-mono);
3883
+ letter-spacing: 0.04em;
3884
+ pointer-events: none;
3885
+ }
3886
+ .opf-presenter .opf-presenter-close {
3887
+ top: 16px;
3888
+ right: 16px;
3889
+ display: inline-flex;
3890
+ align-items: center;
3891
+ justify-content: center;
3892
+ width: var(--opf-ui-control-h);
3893
+ height: var(--opf-ui-control-h);
3894
+ padding: 0;
3895
+ margin: 0;
3896
+ border-radius: var(--opf-ui-radius);
3897
+ font: inherit;
3898
+ cursor: pointer;
3899
+ }
3900
+ .opf-presenter .opf-presenter-close:hover { color: var(--opf-ui-fg); background: var(--opf-ui-muted); }
3901
+ .opf-presenter .opf-presenter-close:focus-visible {
3902
+ outline: 2px solid var(--opf-ui-ring);
3903
+ outline-offset: 2px;
3904
+ }
3905
+ .opf-presenter .opf-icon { flex: none; }
3906
+
3907
+ /* ---- the Present button (quiet like the toolbar's undo and redo by default; data-variant="primary" is the Export trigger's look) ------------------------------------------------------------------------------- */
3908
+ .opf-present-button,
3909
+ .opf-present-button *,
3910
+ .opf-present-button *::before,
3911
+ .opf-present-button *::after { box-sizing: border-box; }
3912
+ .opf-present-button {
3913
+ display: inline-flex;
3914
+ align-items: center;
3915
+ justify-content: center;
3916
+ flex: none;
3917
+ width: var(--opf-ui-control-h);
3918
+ height: var(--opf-ui-control-h);
3919
+ margin: 0;
3920
+ padding: 0;
3921
+ border: 1px solid transparent;
3922
+ border-radius: var(--opf-ui-radius);
3923
+ background: transparent;
3924
+ color: var(--opf-ui-muted-fg);
3925
+ font: inherit;
3926
+ cursor: pointer;
3927
+ transition: background-color var(--opf-ui-ease), color var(--opf-ui-ease), opacity var(--opf-ui-ease);
3928
+ }
3929
+ .opf-present-button:hover { background: var(--opf-ui-muted); color: var(--opf-ui-fg); }
3930
+ .opf-present-button[data-variant="primary"] {
3931
+ border-color: var(--opf-ui-accent);
3932
+ background: var(--opf-ui-accent);
3933
+ color: var(--opf-ui-accent-fg);
3934
+ }
3935
+ .opf-present-button[data-variant="primary"]:hover {
3936
+ background: var(--opf-ui-accent);
3937
+ color: var(--opf-ui-accent-fg);
3938
+ opacity: 0.92;
3939
+ }
3940
+ .opf-present-button:focus-visible {
3941
+ outline: 2px solid var(--opf-ui-ring);
3942
+ outline-offset: 2px;
3943
+ }
3944
+ .opf-present-button[aria-disabled="true"] {
3945
+ opacity: 0.5;
3946
+ cursor: not-allowed;
3947
+ }
3948
+ .opf-present-button[aria-disabled="true"]:hover { background: transparent; color: var(--opf-ui-muted-fg); }
3949
+ .opf-present-button[data-variant="primary"][aria-disabled="true"]:hover {
3950
+ background: var(--opf-ui-accent);
3951
+ color: var(--opf-ui-accent-fg);
3952
+ opacity: 0.5;
3953
+ }
3954
+ .opf-present-button .opf-icon { flex: none; }
3955
+
3956
+ @media (prefers-reduced-motion: reduce) {
3957
+ .opf-presenter .opf-presenter-counter,
3958
+ .opf-presenter .opf-presenter-close,
3959
+ .opf-present-button { transition: none; }
3960
+ }
3961
+
2984
3962
  /* source-pane.css */
2985
3963
  /* Source pane (RR-98). Only --opf-ui-* tokens (src/styles/tokens.css). */
2986
3964
  .opf-source {