@santi020k/lumen-astro 3.0.0 → 4.0.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.
Files changed (103) hide show
  1. package/README.md +403 -7
  2. package/components/AmountField.astro +21 -0
  3. package/components/AnimatedNumber.astro +1 -1
  4. package/components/ApprovalCard.astro +30 -0
  5. package/components/AttachmentList.astro +15 -0
  6. package/components/AttachmentPreview.astro +51 -0
  7. package/components/Avatar.astro +2 -0
  8. package/components/BarChart.astro +95 -31
  9. package/components/BoxPlot.astro +77 -0
  10. package/components/Breadcrumb.astro +2 -1
  11. package/components/BulletChart.astro +64 -0
  12. package/components/Button.astro +1 -1
  13. package/components/Calendar.astro +54 -65
  14. package/components/CalendarHeatmap.astro +76 -0
  15. package/components/Card.astro +4 -0
  16. package/components/ChangeSummary.astro +36 -0
  17. package/components/ChartDatumActions.astro +24 -0
  18. package/components/ChartMotion.astro +11 -0
  19. package/components/Code.astro +18 -3
  20. package/components/CodeTabs.astro +12 -0
  21. package/components/ComboChart.astro +93 -11
  22. package/components/CountryFlag.astro +23 -0
  23. package/components/DataTable.astro +15 -7
  24. package/components/DatePicker.astro +24 -17
  25. package/components/DescriptionDetail.astro +18 -0
  26. package/components/DescriptionItem.astro +18 -0
  27. package/components/DescriptionTerm.astro +18 -0
  28. package/components/DeviceFrame.astro +79 -0
  29. package/components/DialogBody.astro +20 -0
  30. package/components/DialogClose.astro +21 -0
  31. package/components/DialogFooter.astro +20 -0
  32. package/components/DialogHeader.astro +20 -0
  33. package/components/DialogTitle.astro +21 -0
  34. package/components/DumbbellChart.astro +8 -0
  35. package/components/FileUpload.astro +3 -1
  36. package/components/FilterBar.astro +25 -0
  37. package/components/FunnelChart.astro +50 -0
  38. package/components/Grid.astro +2 -2
  39. package/components/Heatmap.astro +61 -12
  40. package/components/Histogram.astro +30 -0
  41. package/components/Icon.astro +7 -3
  42. package/components/ImageComparison.astro +74 -0
  43. package/components/Input.astro +2 -2
  44. package/components/LineChart.astro +127 -67
  45. package/components/LollipopChart.astro +8 -0
  46. package/components/MediaFilmstrip.astro +19 -0
  47. package/components/MediaThumbnail.astro +29 -0
  48. package/components/MediaViewport.astro +38 -0
  49. package/components/Mentions.astro +2 -1
  50. package/components/MessageScroller.astro +6 -0
  51. package/components/MotionGroup.astro +19 -0
  52. package/components/NativeSelect.astro +2 -2
  53. package/components/Pagination.astro +2 -1
  54. package/components/PasswordField.astro +1 -1
  55. package/components/PhoneInput.astro +60 -9
  56. package/components/PhoneNumber.astro +19 -0
  57. package/components/PieChart.astro +26 -3
  58. package/components/PromptComposer.astro +36 -0
  59. package/components/RangeChart.astro +38 -8
  60. package/components/ScatterChart.astro +62 -14
  61. package/components/Segmented.astro +5 -5
  62. package/components/Select.astro +8 -8
  63. package/components/SourceCitation.astro +18 -0
  64. package/components/Sparkline.astro +9 -10
  65. package/components/Stack.astro +2 -2
  66. package/components/StreamMessage.astro +26 -0
  67. package/components/Tabs.astro +3 -0
  68. package/components/ToolActivity.astro +17 -0
  69. package/components/TreeSelect.astro +1 -0
  70. package/components/VirtualList.astro +5 -2
  71. package/components/VisualEffect.astro +21 -0
  72. package/components/WaterfallChart.astro +27 -0
  73. package/components/WorldMap.astro +213 -0
  74. package/forms.ts +17 -4
  75. package/index.ts +37 -0
  76. package/internal/ChartInspection.astro +27 -0
  77. package/internal/ComparisonChart.astro +69 -0
  78. package/internal/IntervalChart.astro +66 -0
  79. package/package.json +6 -4
  80. package/runtime/UIPrimitives.astro +670 -647
  81. package/runtime/chart-actions.ts +19 -0
  82. package/runtime/controllers/amount-field.ts +12 -0
  83. package/runtime/controllers/attachments.ts +13 -0
  84. package/runtime/controllers/chart-activation.ts +33 -0
  85. package/runtime/controllers/charts.ts +33 -0
  86. package/runtime/controllers/combobox.ts +39 -0
  87. package/runtime/controllers/comparison-reset.ts +20 -0
  88. package/runtime/controllers/data-table.ts +142 -0
  89. package/runtime/controllers/dialogs.ts +32 -32
  90. package/runtime/controllers/document-navigation.ts +54 -22
  91. package/runtime/controllers/file-upload.ts +89 -0
  92. package/runtime/controllers/image-comparison.ts +53 -0
  93. package/runtime/controllers/media-selection.ts +20 -0
  94. package/runtime/controllers/media-viewport.ts +54 -0
  95. package/runtime/controllers/media-workspace.ts +8 -0
  96. package/runtime/controllers/message-scroller.ts +13 -0
  97. package/runtime/controllers/motion.ts +15 -16
  98. package/runtime/controllers/optional-media.ts +29 -0
  99. package/runtime/controllers/phone-input.ts +128 -39
  100. package/runtime/controllers/visual-interactions.ts +75 -0
  101. package/runtime/controllers/world-map.ts +154 -0
  102. package/styles/critical.css +634 -61
  103. package/styles/lumen.css +101 -0
package/styles/lumen.css CHANGED
@@ -3,3 +3,104 @@
3
3
  * New applications should import "@santi020k/lumen/styles.css".
4
4
  */
5
5
  @import "@santi020k/lumen/styles.css";
6
+
7
+ /* Exact amount controls keep their visible input inside the available width. */
8
+ [data-ui-amount-field], lumen-amount-field { display: inline-block; min-width: 0; max-width: 100%; }
9
+
10
+ /* Device hardware is decorative; live screens retain their own viewport and colors. */
11
+ .ui-device-frame { display: block; position: relative; container-type: inline-size; width: 100%; max-width: 64rem; margin-inline: auto; --ui-device-tone: #242424; --ui-device-body: var(--ui-device-color, var(--ui-device-tone)); --ui-device-shell: color-mix(in srgb, var(--ui-device-body) 96%, white); --ui-device-edge: color-mix(in srgb, var(--ui-device-body) 76%, black); --ui-device-rim: color-mix(in srgb, var(--ui-device-body) 89%, black); --ui-device-highlight: color-mix(in srgb, var(--ui-device-body) 40%, white); --ui-device-recess: color-mix(in srgb, var(--ui-device-body) 88%, black); --ui-device-lens: color-mix(in srgb, var(--ui-device-body) 38%, black); --ui-device-shadow: rgb(0 0 0 / 15%); }
12
+ .ui-device-frame[data-tone="light"] { --ui-device-tone: #f7f7f7; }
13
+ .ui-device-frame__shell { position: relative; border: 1px solid var(--ui-device-rim); background: var(--ui-device-shell); }
14
+ .ui-device-frame__glass { position: relative; background: var(--ui-device-shell); }
15
+ .ui-device-frame__screen { display: block; position: relative; width: 100%; overflow: auto; background: hsl(var(--canvas)); isolation: isolate; }
16
+ .ui-device-frame__screen[data-scroll="false"], .ui-device-frame__screen:has(> iframe) { overflow: hidden; }
17
+ .ui-device-frame__screen > img { display: block; width: 100%; height: 100%; object-fit: contain; }
18
+ .ui-device-frame__screen > iframe { display: block; width: 100%; height: 100%; border: 0; }
19
+ .ui-device-frame__screen[style*="--ui-device-frame-scale"] > iframe { position: absolute; inset: 0 auto auto 0; width: var(--ui-device-frame-width); height: var(--ui-device-frame-height); transform: scale(var(--ui-device-frame-scale)); transform-origin: top left; }
20
+ .ui-device-frame__camera { position: absolute; z-index: 3; left: 50%; width: 0.42cqi; height: 0.42cqi; border-radius: 50%; background: var(--ui-device-lens); box-shadow: inset 0 1px 1px rgb(0 0 0 / 25%), 0 0 0 0.12cqi var(--ui-device-recess), 0 0.1cqi 0 0.18cqi var(--ui-device-highlight); transform: translateX(-50%); pointer-events: none; }
21
+ .ui-device-frame__hardware { display: none; position: absolute; inset: 0; z-index: 4; pointer-events: none; }
22
+ .ui-device-frame__base { position: relative; display: block; pointer-events: none; }
23
+
24
+ /* A thin display lid, recessed hinge and a separate tapered keyboard deck. */
25
+ .ui-device-frame:is([data-device="laptop"], [data-device="macbook-air"], [data-device="macbook-pro"]) .ui-device-frame__shell { margin-inline: 6%; padding: 0.38%; border-radius: 2.6cqi 2.6cqi 0.55cqi 0.55cqi; background: linear-gradient(110deg, var(--ui-device-highlight), var(--ui-device-shell) 8%, var(--ui-device-shell) 92%, var(--ui-device-recess)); box-shadow: inset 0 0 0 0.15cqi var(--ui-device-highlight), 0 0 0 0.13cqi var(--ui-device-recess); }
26
+ .ui-device-frame:is([data-device="laptop"], [data-device="macbook-air"], [data-device="macbook-pro"]) .ui-device-frame__glass { padding: 3.6% 2.6% 3.1%; border-radius: 2.05cqi 2.05cqi 0.2cqi 0.2cqi; border: 1px solid var(--ui-device-rim); }
27
+ .ui-device-frame:is([data-device="laptop"], [data-device="macbook-air"], [data-device="macbook-pro"]) .ui-device-frame__screen { border: 0; border-radius: 0.15cqi; box-shadow: 0 0 0 1px var(--ui-device-recess); }
28
+ .ui-device-frame:is([data-device="laptop"], [data-device="macbook-air"], [data-device="macbook-pro"]) .ui-device-frame__camera { top: 1.2cqi; }
29
+ .ui-device-frame:is([data-device="laptop"], [data-device="macbook-air"], [data-device="macbook-pro"]) .ui-device-frame__shell::after { content: ''; position: absolute; bottom: -0.1cqi; left: 4%; right: 4%; height: 0.55cqi; border-radius: 0.3cqi 0.3cqi 0 0; background: linear-gradient(var(--ui-device-recess), var(--ui-device-edge)); }
30
+ .ui-device-frame:is([data-device="laptop"], [data-device="macbook-air"], [data-device="macbook-pro"]) .ui-device-frame__base { height: 2.4cqi; border-radius: 0.2cqi 0.2cqi 50% 50% / 0.15cqi 0.15cqi 90% 90%; background: linear-gradient(var(--ui-device-highlight) 0 12%, var(--ui-device-shell) 15% 42%, var(--ui-device-recess) 68%, var(--ui-device-edge) 86%, var(--ui-device-rim) 95%); box-shadow: 0 0.35cqi 0.35cqi -0.2cqi rgb(0 0 0 / 35%), 0 1.05cqi 1.1cqi -0.65cqi var(--ui-device-shadow); }
31
+ .ui-device-frame:is([data-device="laptop"], [data-device="macbook-air"], [data-device="macbook-pro"]) .ui-device-frame__base::before { content: ''; position: absolute; left: 41%; top: 0; width: 18%; height: 42%; border-radius: 0 0 1.1cqi 1.1cqi; background: linear-gradient(var(--ui-device-recess), var(--ui-device-shell)); box-shadow: inset 0 -0.12cqi 0.1cqi var(--ui-device-highlight); }
32
+ .ui-device-frame:is([data-device="laptop"], [data-device="macbook-air"], [data-device="macbook-pro"]) .ui-device-frame__base::after { content: ''; position: absolute; left: 5%; right: 5%; bottom: 0.15cqi; height: 0.16cqi; border-radius: 50%; background: var(--ui-device-edge); opacity: 0.5; }
33
+
34
+ /* MacBook Pro has a full-height front edge, compact display bezel, and camera notch. */
35
+ .ui-device-frame[data-device="macbook-pro"] .ui-device-frame__shell { margin-inline: 3.8%; border-radius: 2.1cqi 2.1cqi 0.65cqi 0.65cqi; }
36
+ .ui-device-frame[data-device="macbook-pro"] .ui-device-frame__glass { padding: 3.15% 1.35% 2.1%; border-radius: 1.7cqi 1.7cqi 0.45cqi 0.45cqi; background: var(--ui-device-shell); }
37
+ .ui-device-frame[data-device="macbook-pro"] .ui-device-frame__screen { border-radius: 0.7cqi 0.7cqi 0.15cqi 0.15cqi; }
38
+ .ui-device-frame[data-device="macbook-pro"] .ui-device-frame__camera { top: 0; width: 13%; height: 2.5cqi; border-radius: 0 0 0.65cqi 0.65cqi; background: var(--ui-device-edge); box-shadow: 0 0.1cqi 0 var(--ui-device-highlight); }
39
+ .ui-device-frame[data-device="macbook-pro"] .ui-device-frame__camera::after { content: ''; position: absolute; left: calc(50% - 0.28cqi); top: 0.75cqi; width: 0.56cqi; height: 0.56cqi; border-radius: 50%; background: var(--ui-device-lens); box-shadow: 0 0 0 0.12cqi var(--ui-device-recess); }
40
+ .ui-device-frame[data-device="macbook-pro"] .ui-device-frame__shell::after { left: 1%; right: 1%; height: 0.7cqi; }
41
+ .ui-device-frame[data-device="macbook-pro"] .ui-device-frame__base { height: 3.2cqi; border-radius: 0.25cqi 0.25cqi 1.5cqi 1.5cqi; background: linear-gradient(var(--ui-device-highlight) 0 8%, var(--ui-device-shell) 12% 60%, var(--ui-device-recess) 90%, var(--ui-device-edge)); }
42
+ .ui-device-frame[data-device="macbook-pro"] .ui-device-frame__base::before { left: 43%; width: 14%; height: 35%; border-radius: 0 0 0.8cqi 0.8cqi; }
43
+ .ui-device-frame[data-device="macbook-pro"] .ui-device-frame__base::after { left: 7%; right: 7%; bottom: -0.35cqi; height: 0.45cqi; border-radius: 0.25cqi; background: linear-gradient(to right, var(--ui-device-edge) 0 7%, transparent 7% 93%, var(--ui-device-edge) 93%); opacity: 1; }
44
+
45
+ /* The display and chin form one enclosure; the curved neck rolls into a broad foot. */
46
+ .ui-device-frame:is([data-device="desktop"], [data-device="imac"]) .ui-device-frame__shell { padding: 0.45%; border-radius: 2.9cqi; background: linear-gradient(120deg, var(--ui-device-highlight), var(--ui-device-shell) 20%); box-shadow: inset 0 0 0 0.15cqi var(--ui-device-highlight), 0 0.4cqi 0.5cqi -0.2cqi var(--ui-device-shadow); }
47
+ .ui-device-frame:is([data-device="desktop"], [data-device="imac"]) .ui-device-frame__glass { padding: 3.3% 3.3% 12.3%; border-radius: 2.45cqi; background: linear-gradient(to bottom, var(--ui-device-shell) 0 82%, color-mix(in srgb, var(--ui-device-shell) 94%, white) 82%); }
48
+ .ui-device-frame:is([data-device="desktop"], [data-device="imac"]) .ui-device-frame__screen { border: 0; border-radius: 0.15cqi; box-shadow: 0 0 0 1px var(--ui-device-rim), 0 0 0 0.2cqi var(--ui-device-highlight); }
49
+ .ui-device-frame:is([data-device="desktop"], [data-device="imac"]) .ui-device-frame__camera { top: 1.15cqi; }
50
+ .ui-device-frame:is([data-device="desktop"], [data-device="imac"]) .ui-device-frame__base { width: 36%; height: 13cqi; margin: -0.1cqi auto 0; isolation: isolate; }
51
+ .ui-device-frame:is([data-device="desktop"], [data-device="imac"]) .ui-device-frame__base::before { content: ''; position: absolute; inset: 0 0 0.65cqi; background: linear-gradient(var(--ui-device-recess) 0, var(--ui-device-shell) 52%, var(--ui-device-highlight) 88%, var(--ui-device-shell)); mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 360 130' preserveAspectRatio='none'%3E%3Cpath d='M78 0H282L291 72C294 95 313 111 351 122Q359 124 360 130H0Q1 124 9 122C47 111 66 95 69 72Z'/%3E%3C/svg%3E") center / 100% 100% no-repeat; }
52
+ .ui-device-frame:is([data-device="desktop"], [data-device="imac"]) .ui-device-frame__base::after { content: ''; position: absolute; inset: auto -0.1cqi 0; height: 1cqi; border: 1px solid var(--ui-device-rim); border-top-color: var(--ui-device-highlight); border-radius: 18% 18% 12% 12% / 45% 45% 60% 60%; background: linear-gradient(var(--ui-device-highlight), var(--ui-device-shell) 60%, var(--ui-device-edge)); box-shadow: 0 0.35cqi 0.4cqi -0.2cqi rgb(0 0 0 / 25%), 0 1.2cqi 1.8cqi -0.5cqi var(--ui-device-shadow); }
53
+
54
+ /* Rounded cover glass sits inside a layered metal rail, with separate side controls. */
55
+ .ui-device-frame:is([data-device="iphone"], [data-device="android"], [data-device="pixel"], [data-device="tablet"], [data-device="ipad-pro"]) { max-width: 24rem; }
56
+ .ui-device-frame:is([data-device="iphone"], [data-device="android"], [data-device="pixel"], [data-device="tablet"], [data-device="ipad-pro"]) .ui-device-frame__shell { padding: 2.05%; border-radius: 14cqi; border: 0.25cqi solid var(--ui-device-edge); background: linear-gradient(100deg, var(--ui-device-recess), var(--ui-device-highlight) 1.1%, var(--ui-device-shell) 2.5% 97.5%, var(--ui-device-highlight) 98.9%, var(--ui-device-recess)); box-shadow: inset 0 0 0 0.38cqi var(--ui-device-highlight), inset 0 0 0 0.65cqi var(--ui-device-rim), 0 0.35cqi 0.4cqi var(--ui-device-shadow), 0 1.4cqi 2.2cqi -0.8cqi var(--ui-device-shadow); }
57
+ .ui-device-frame:is([data-device="iphone"], [data-device="android"], [data-device="pixel"], [data-device="tablet"], [data-device="ipad-pro"]) .ui-device-frame__glass { padding: 9% 0 4%; border: 0.22cqi solid var(--ui-device-rim); border-radius: 11.6cqi; overflow: hidden; background: hsl(var(--canvas)); box-shadow: 0 0 0 0.35cqi var(--ui-device-shell); }
58
+ .ui-device-frame:is([data-device="iphone"], [data-device="android"], [data-device="pixel"], [data-device="tablet"], [data-device="ipad-pro"]) .ui-device-frame__screen { border: 0; border-radius: 0; }
59
+ .ui-device-frame:is([data-device="iphone"], [data-device="android"], [data-device="pixel"]) .ui-device-frame__glass:has(> .ui-device-frame__screen > img) { padding: 0; }
60
+ .ui-device-frame:is([data-device="iphone"], [data-device="android"], [data-device="pixel"]) .ui-device-frame__glass::after { content: ''; position: absolute; z-index: 3; bottom: 1.7cqi; left: 37%; width: 26%; height: 0.85cqi; border-radius: 1cqi; background: var(--ui-device-lens); pointer-events: none; }
61
+ .ui-device-frame:is([data-device="iphone"], [data-device="android"], [data-device="pixel"]) .ui-device-frame__hardware { display: block; }
62
+ .ui-device-frame__hardware > span { position: absolute; }
63
+ .ui-device-frame__action, .ui-device-frame__volume-up, .ui-device-frame__volume-down, .ui-device-frame__power { width: 1cqi; border: 0.18cqi solid var(--ui-device-rim); border-radius: 0.65cqi; background: linear-gradient(90deg, var(--ui-device-recess), var(--ui-device-highlight), var(--ui-device-shell)); box-shadow: 0 0.15cqi 0.2cqi var(--ui-device-shadow); }
64
+ .ui-device-frame__action { left: -1.1cqi; top: 15%; height: 3.5%; }
65
+ .ui-device-frame__volume-up { left: -1.1cqi; top: 23%; height: 7%; }
66
+ .ui-device-frame__volume-down { left: -1.1cqi; top: 33%; height: 7%; }
67
+ .ui-device-frame__power { right: -1.1cqi; top: 25%; height: 11%; }
68
+ .ui-device-frame__rail-left, .ui-device-frame__rail-right { inset-block: 0; width: 1.2cqi; background: linear-gradient(transparent 12%, var(--ui-device-recess) 12% 12.3%, transparent 12.3% 86%, var(--ui-device-recess) 86% 86.3%, transparent 86.3%); }
69
+ .ui-device-frame__rail-left { left: 0; }
70
+ .ui-device-frame__rail-right { right: 0; }
71
+ .ui-device-frame:is([data-device="iphone"], [data-device="android"], [data-device="pixel"]) .ui-device-frame__base { display: none; }
72
+ .ui-device-frame[data-device="iphone"] .ui-device-frame__glass::before { content: ''; position: absolute; z-index: 2; top: -0.1cqi; left: 50%; width: 49.5%; height: 8cqi; transform: translateX(-50%); background: var(--ui-device-rim); mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 40' preserveAspectRatio='none'%3E%3Cpath d='M0 0C11 0 12 4 13 10L15 18C17 32 26 40 42 40H158C174 40 183 32 185 18L187 10C188 4 189 0 200 0Z'/%3E%3C/svg%3E") center / 100% 100% no-repeat; pointer-events: none; }
73
+ .ui-device-frame[data-device="iphone"] .ui-device-frame__camera { top: -0.1cqi; width: 49%; height: 7.8cqi; border-radius: 0; background: var(--ui-device-shell); box-shadow: none; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 40' preserveAspectRatio='none'%3E%3Cpath d='M0 0C11 0 12 4 13 10L15 18C17 32 26 40 42 40H158C174 40 183 32 185 18L187 10C188 4 189 0 200 0Z'/%3E%3C/svg%3E") center / 100% 100% no-repeat; }
74
+ .ui-device-frame[data-device="iphone"] .ui-device-frame__camera::before { content: ''; position: absolute; top: 2.5cqi; left: 32%; width: 25%; height: 1.25cqi; border: 0.15cqi solid var(--ui-device-recess); border-radius: 1cqi; background: repeating-linear-gradient(90deg, var(--ui-device-lens) 0 0.15cqi, var(--ui-device-rim) 0.15cqi 0.35cqi); box-shadow: 0 0.2cqi 0 var(--ui-device-highlight); }
75
+ .ui-device-frame[data-device="iphone"] .ui-device-frame__camera::after { content: ''; position: absolute; top: 2.1cqi; right: 25%; width: 2cqi; height: 2cqi; border: 0.3cqi solid var(--ui-device-recess); border-radius: 50%; background: var(--ui-device-lens); box-shadow: inset 0.15cqi 0.15cqi 0.15cqi var(--ui-device-edge), 0 0 0 0.2cqi var(--ui-device-highlight); }
76
+ .ui-device-frame:is([data-device="android"], [data-device="pixel"]) .ui-device-frame__shell { border-radius: 11cqi; padding: 1.65%; }
77
+ .ui-device-frame:is([data-device="android"], [data-device="pixel"]) .ui-device-frame__glass { border-radius: 9.25cqi; padding-top: 7%; }
78
+ .ui-device-frame:is([data-device="android"], [data-device="pixel"]) .ui-device-frame__camera { top: 1.8cqi; width: 2.7cqi; height: 2.7cqi; background: var(--ui-device-lens); box-shadow: inset 0 0 0 0.45cqi var(--ui-device-edge), 0 0 0 0.25cqi var(--ui-device-recess); }
79
+ .ui-device-frame:is([data-device="android"], [data-device="pixel"]) .ui-device-frame__action, .ui-device-frame:is([data-device="android"], [data-device="pixel"]) .ui-device-frame__volume-down { display: none; }
80
+ .ui-device-frame:is([data-device="android"], [data-device="pixel"]) .ui-device-frame__power { top: 19%; height: 6%; }
81
+ .ui-device-frame:is([data-device="android"], [data-device="pixel"]) .ui-device-frame__volume-up { top: 29%; height: 12%; left: auto; right: -1.1cqi; }
82
+
83
+ /* A classic tablet enclosure has a separate home recess and a side camera in landscape. */
84
+ .ui-device-frame[data-device="tablet"] { max-width: 40rem; }
85
+ .ui-device-frame[data-device="tablet"] .ui-device-frame__shell { padding: 0.6%; border-radius: 4.5cqi; }
86
+ .ui-device-frame[data-device="tablet"] .ui-device-frame__glass { padding: 7% 3.5% 9%; border-radius: 3.8cqi; background: var(--ui-device-shell); }
87
+ .ui-device-frame[data-device="tablet"] .ui-device-frame__screen { border: 0; box-shadow: 0 0 0 1px var(--ui-device-rim), 0 0 0 0.25cqi var(--ui-device-highlight); }
88
+ .ui-device-frame[data-device="tablet"] .ui-device-frame__camera { top: 2.8cqi; width: 0.7cqi; height: 0.7cqi; }
89
+ .ui-device-frame[data-device="tablet"] .ui-device-frame__base { position: absolute; bottom: 2.5cqi; left: 50%; width: 3.8cqi; height: 3.8cqi; border: 0.15cqi solid var(--ui-device-rim); border-radius: 50%; background: var(--ui-device-shell); transform: translateX(-50%); box-shadow: inset 0 0.25cqi 0.4cqi var(--ui-device-recess), 0 0.1cqi 0 var(--ui-device-highlight); }
90
+ .ui-device-frame[data-device="tablet"][data-orientation="landscape"] .ui-device-frame__glass { padding: 3.5% 7%; }
91
+ .ui-device-frame[data-device="tablet"][data-orientation="landscape"] .ui-device-frame__camera { left: 2.8cqi; top: 50%; transform: translateY(-50%); }
92
+ .ui-device-frame[data-device="tablet"][data-orientation="landscape"] .ui-device-frame__base { left: auto; right: 2.8cqi; top: 50%; bottom: auto; transform: translateY(-50%); }
93
+
94
+ /* iPad Pro keeps an even bezel and flat rail; the landscape camera stays outside the screen. */
95
+ .ui-device-frame[data-device="ipad-pro"] { max-width: 44rem; }
96
+ .ui-device-frame[data-device="ipad-pro"] .ui-device-frame__shell { padding: 0.55%; border-radius: 4.1cqi; }
97
+ .ui-device-frame[data-device="ipad-pro"] .ui-device-frame__glass { padding: 3%; border-radius: 3.55cqi; background: var(--ui-device-shell); }
98
+ .ui-device-frame[data-device="ipad-pro"] .ui-device-frame__screen { border-radius: 1.9cqi; box-shadow: 0 0 0 0.12cqi var(--ui-device-rim); }
99
+ .ui-device-frame[data-device="ipad-pro"] .ui-device-frame__camera { left: auto; right: 1.15cqi; top: 50%; width: 0.65cqi; height: 0.65cqi; transform: translateY(-50%); }
100
+ .ui-device-frame[data-device="ipad-pro"][data-orientation="landscape"] .ui-device-frame__camera { left: 50%; right: auto; top: 1.15cqi; transform: translateX(-50%); }
101
+ .ui-device-frame[data-device="ipad-pro"] .ui-device-frame__base { display: none; }
102
+ .ui-device-frame[data-device="ipad-pro"] .ui-device-frame__hardware { display: block; }
103
+ .ui-device-frame[data-device="ipad-pro"] .ui-device-frame__hardware > span { display: none; }
104
+ .ui-device-frame[data-device="ipad-pro"] .ui-device-frame__hardware .ui-device-frame__power { display: block; width: 6%; height: 0.6cqi; right: 10%; top: -0.85cqi; }
105
+ .ui-device-frame[data-device="ipad-pro"] .ui-device-frame__hardware .ui-device-frame__volume-up { display: block; width: 0.6cqi; height: 5%; right: -0.85cqi; left: auto; top: 10%; }
106
+ .ui-device-frame[data-device="ipad-pro"] .ui-device-frame__hardware .ui-device-frame__volume-down { display: block; width: 0.6cqi; height: 5%; right: -0.85cqi; left: auto; top: 17%; }