tramway 3.1.2.8 → 4.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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +76 -16
  3. data/app/assets/builds/tailwind.css +2 -0
  4. data/app/assets/javascripts/tramway/tramway.js +174 -1
  5. data/app/assets/stylesheets/font-awesome.css +2337 -0
  6. data/app/assets/tailwind/application.css +29 -0
  7. data/app/components/tramway/chat_component.html.haml +1 -1
  8. data/app/components/tramway/containers/main_component.rb +1 -3
  9. data/app/components/tramway/containers/narrow_component.rb +5 -4
  10. data/app/components/tramway/form/builder.rb +1 -2
  11. data/app/components/tramway/grid/card_component.html.haml +2 -0
  12. data/app/components/tramway/grid/card_component.rb +37 -0
  13. data/app/components/tramway/grid_component.html.haml +18 -0
  14. data/app/components/tramway/grid_component.rb +76 -0
  15. data/app/components/tramway/native_text_component.rb +1 -2
  16. data/app/components/tramway/nav/item_component.rb +4 -2
  17. data/app/components/tramway/navbar_component.html.haml +104 -110
  18. data/app/components/tramway/navbar_component.rb +84 -2
  19. data/app/components/tramway/table/cell_component.rb +9 -1
  20. data/app/components/tramway/table/header_component.rb +23 -2
  21. data/app/components/tramway/table/row_component.rb +27 -10
  22. data/app/components/tramway/table_component.rb +28 -1
  23. data/app/controllers/tramway/entities_controller.rb +6 -6
  24. data/app/views/tramway/layouts/application.html.haml +8 -6
  25. data/config/routes.rb +1 -2
  26. data/config/tailwind.config.js +57 -0
  27. data/lib/generators/tramway/install/font_awesome_helpers.rb +39 -0
  28. data/lib/generators/tramway/install/install_generator.rb +131 -65
  29. data/lib/generators/tramway/install/layout_helpers.rb +95 -0
  30. data/lib/tramway/engine.rb +12 -0
  31. data/lib/tramway/forms/validations.rb +1 -2
  32. data/lib/tramway/helpers/navbar_helper.rb +3 -1
  33. data/lib/tramway/helpers/table_helper.rb +27 -0
  34. data/lib/tramway/helpers/views_helper.rb +26 -2
  35. data/lib/tramway/version.rb +1 -1
  36. metadata +28 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4734bad656c9c6530213422f8e87e54ce595404ef127010b781e45af3f94967a
4
- data.tar.gz: d9b3ee1e03ccfe40912955fd490ccc88a6b127965696b9956ecf5d5ced27e727
3
+ metadata.gz: 148d9d2e8ff5ee611788d8242c4900f20b80d85b853fd3840b16d0d5e46499a2
4
+ data.tar.gz: 62f5e3d6272692fc77356597957d79a69fa027b1cb13882e9178fea55b466681
5
5
  SHA512:
6
- metadata.gz: 54ade07629589d86733af1c559579cae2d1dab1d35f21616bd3e01ddcd3e964f027ce8fa71a44dede44061382b5637887151c680236b22ca2eb5abba5af82346
7
- data.tar.gz: 9c37d9d2b6e868e34c533034e3f40e4953c21120986c0d68aaadf351f21732e7ef31955a354048a2bae669e624711691e743778507cd6107de57fd66211dc04c
6
+ metadata.gz: d70a7f1a483a8633c3c479d5fc9fd089f185f23b6c4e554113fdb8461f8ca09586bebf2765e7a35b0e52985fe63e020db0185b9ce9e82f5721b3944715c3d1e7
7
+ data.tar.gz: e117993ffe8ad1c3448975ee7944aab1b1138ab0132ca3cec0c2f56eee999f27f1e90f4d86a4b20401e02e9281def6d9fa35e9b351fb510e32e58647a0db9e75
data/README.md CHANGED
@@ -20,6 +20,7 @@ Codex instruction that points agents to the Tramway skill for Tramway-native cod
20
20
  * [Tramway Tooltip](https://github.com/Purple-Magic/tramway#tramway-tooltip)
21
21
  * [Tramway Chat](https://github.com/Purple-Magic/tramway#tramway-chat)
22
22
  * [Tramway Table Component](https://github.com/Purple-Magic/tramway#tramway-table-component)
23
+ * [Tramway Grid](https://github.com/Purple-Magic/tramway#tramway-grid)
23
24
  * [Tailwind-styled forms](https://github.com/Purple-Magic/tramway#tailwind-styled-forms)
24
25
  * [Stimulus-based inputs](https://github.com/Purple-Magic/tramway#stimulus-based-inputs)
25
26
  * [Tailwind-styled pagination](https://github.com/Purple-Magic/tramway?tab=readme-ov-file#tailwind-styled-pagination-for-kaminari)
@@ -29,14 +30,14 @@ Codex instruction that points agents to the Tramway skill for Tramway-native cod
29
30
 
30
31
  Tramway is actively verified against the following Ruby and Rails versions.
31
32
 
32
- | Ruby \ Rails | 7.1* | 7.2 | 8.0 | 8.1 |
33
- | ------------- | ---- | --- | --- | --- |
34
- | 3.2 | ✅ | ✅ | ✅ | ✅ |
35
- | 3.3 | ✅ | ✅ | ✅ | ✅ |
36
- | 3.4 | ✅ | ✅ | ✅ | ✅ |
37
- | 4.0 | ✅ | ✅ | ✅ | ✅ |
33
+ | Ruby \ Rails | 8.0 | 8.1 |
34
+ | ------------- | --- | --- |
35
+ | 3.2 | ✅ | ✅ |
36
+ | 3.3 | ✅ | ✅ |
37
+ | 3.4 | ✅ | ✅ |
38
+ | 4.0 | ✅ | ✅ |
38
39
 
39
- \* Rails 7.1 receives only residual support because it no longer receives updates from the Rails core team. See the [announcement](https://rubyonrails.org/2025/10/29/new-rails-releases-and-end-of-support-announcement) for details.
40
+ Rails 7 is no longer supported. See the [announcement](https://rubyonrails.org/2025/10/29/new-rails-releases-and-end-of-support-announcement) for details.
40
41
 
41
42
  ## Installation
42
43
  Add this line to your application's Gemfile:
@@ -920,10 +921,37 @@ background:
920
921
  with_entities: Show Tramway CRUD index page links to navbar. Default: true
921
922
  ```
922
923
 
924
+ When you use the default vertical navbar layout, it renders as a fixed left sidebar on desktop. The icon-only
925
+ sidebar toggle collapses the whole sidebar and keeps the main content offset in sync, so the page shifts between
926
+ `md:pl-72` and `md:pl-24` as the sidebar changes width.
927
+
928
+ The collapse/expand motion is tuned per element rather than a blanket `transition-all`: the sidebar width and the
929
+ main content's `padding-left` each transition only that one property (`transition-[width]` /
930
+ `transition-[padding-left]`) over 300ms on the `ease-in-out-strong` curve (`cubic-bezier(0.77, 0, 0.175, 1)`,
931
+ registered in `config/tailwind.config.js`), since both are on-screen movement. The header and nav-item list fade
932
+ with `transition-opacity` on the `ease-out-strong` curve (`cubic-bezier(0.23, 1, 0.32, 1)`), matching that they're
933
+ entering/exiting rather than moving. The toggle chevron no longer swaps between `fa-chevron-left` and
934
+ `fa-chevron-right` — it stays a single `fa-chevron-left` icon that rotates 180° (`transition-transform duration-200
935
+ ease-in-out-strong`) to indicate state instead of snapping instantly. All of the above respect
936
+ `prefers-reduced-motion` via `motion-reduce:duration-0` on the movement/rotation transitions; the opacity fade is
937
+ left intact since it aids comprehension without moving anything.
938
+
939
+ Tramway now ships with Font Awesome loaded through the engine, and the vertical navbar collapse control uses a
940
+ single `fa-chevron-left` icon for both states (rotated when collapsed).
941
+ Tramway ships a plain `font-awesome.css` asset for Propshaft compatibility and adds Font Awesome's font
942
+ directory to the host app asset load path, so `stylesheet_link_tag "font-awesome"` resolves without extra
943
+ app-side asset configuration.
944
+ On mobile, `tramway_navbar` always renders the same top navbar regardless of `direction:`. Desktop `:horizontal`
945
+ renders the classic top navbar, and desktop `:vertical` renders the collapsible sidebar.
946
+ When `tramway_navbar` renders before `tramway_main_container`, the main container helper keeps the vertical
947
+ sidebar offset in sync automatically and removes it for horizontal pages.
948
+
923
949
  **NOTE:** `tramway_navbar` method called without arguments and block of code will render only [Tramway CRUD](https://github.com/Purple-Magic/tramway#tramway-crud) links on the left.
924
950
 
925
951
  In case you want to hide entity links you can pass `with_entities: false`.
926
952
 
953
+ The default `:vertical` navbar now renders as a fixed left sidebar on desktop screens. If your page content uses a full-width layout, wrap it with `tramway_main_container class: 'md:pl-72'` so the sidebar has room.
954
+
927
955
  ```erb
928
956
  <% if current_user.present? %>
929
957
  <%= tramway_navbar title: 'WaiWai' do |nav| %>
@@ -1134,17 +1162,23 @@ implementations.
1134
1162
  <% end %>
1135
1163
  ```
1136
1164
 
1137
- `tramway_table` accepts the same optional `options` hash as `Tramway::TableComponent`. The hash is forwarded as HTML
1138
- attributes, so you can pass things like `id`, `data` attributes, or additional classes. If you do not supply your own width
1139
- utility (e.g. a class that starts with `w-`), the component automatically appends `w-full` to keep the table responsive. This
1140
- allows you to extend the default styling without losing the sensible defaults provided by the component.
1165
+ `tramway_table` accepts an optional `size:` argument plus the same `options` hash as `Tramway::TableComponent`. Supported
1166
+ sizes are `:small`, `:medium`, and `:large`. The default is `:medium`, and it renders exactly like the current table
1167
+ implementation. The `options` hash is forwarded as HTML attributes, so you can pass things like `id`, `data` attributes, or
1168
+ additional classes. The table itself carries the default dark background (`bg-zinc-950`), so you can override it directly
1169
+ with a utility like `class: '!bg-red-500'`. If you do not supply your own width utility (e.g. a class that starts with `w-`),
1170
+ the component automatically appends `w-full` to keep the table responsive.
1141
1171
 
1142
- Use the optional `href:` argument on `tramway_row` to turn an entire row into a link. Linked rows gain pointer and hover styles
1143
- (`cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700`) to indicate interactivity.
1172
+ `tramway_row`, `tramway_header`, and `tramway_cell` automatically follow the active table size, so a single `size:` on
1173
+ `tramway_table` controls the whole table.
1174
+
1175
+ Use the optional `href:` argument on `tramway_row` to turn an entire row into a link. Linked rows keep their transparent
1176
+ background and gain pointer and hover styles (`cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700`) to indicate
1177
+ interactivity.
1144
1178
 
1145
1179
  ```erb
1146
- <%= tramway_table class: 'max-w-3xl border border-gray-200', data: { controller: 'table' } do %>
1147
- <%= tramway_header', headers: ['Name', 'Email'] %>
1180
+ <%= tramway_table size: :large, class: 'max-w-3xl border border-gray-200', data: { controller: 'table' } do %>
1181
+ <%= tramway_header headers: ['Name', 'Email'] %>
1148
1182
 
1149
1183
  <%= tramway_row href: user_path(user) do %>
1150
1184
  <%= tramway_cell do %>
@@ -1171,6 +1205,32 @@ details panel. Pass `preview: false` when you want a row without the preview pan
1171
1205
  <% end %>
1172
1206
  ```
1173
1207
 
1208
+ ### Tramway Grid
1209
+
1210
+ Use `tramway_grid` when you want dashboard-style layouts with cards that span multiple rows and columns while keeping the
1211
+ existing Tramway dark zinc styling. The grid accepts `rows:` and `columns:`, and it also accepts `outline: true` when you
1212
+ want to show separators between cells. Those separators are drawn in the gap between grid cells, so they stay centered
1213
+ when cards have content. Cards use `size: [rows, columns]`, with responsive spans on desktop and stacked cards on smaller
1214
+ screens. Each grid cell is rendered as a real `20em x 20em` box, and the grid always builds the exact `rows x columns`
1215
+ matrix even when the slot is empty. Cards participate in the same grid, so `size: [1, 1]` occupies exactly one cell.
1216
+
1217
+ ```haml
1218
+ = tramway_grid rows: 8, columns: 8, outline: true do
1219
+ = tramway_card size: [1, 2] do
1220
+ .text-sm.font-medium.text-zinc-400 Revenue
1221
+ .mt-2.text-3xl.font-semibold.text-zinc-50 $128,240
1222
+
1223
+ = tramway_card size: [2, 3] do
1224
+ .text-sm.font-medium.text-zinc-400 Activity
1225
+ .mt-4.space-y-2
1226
+ .flex.items-center.justify-between
1227
+ %span.text-zinc-300 Orders
1228
+ %span.text-zinc-50 48
1229
+ .flex.items-center.justify-between
1230
+ %span.text-zinc-300 Refunds
1231
+ %span.text-zinc-50 3
1232
+ ```
1233
+
1174
1234
  `tramway_cell` also forwards any HTML options to the underlying cell wrapper. Use this when you need per-cell classes,
1175
1235
  data attributes, ids, or other attributes:
1176
1236
 
@@ -1598,7 +1658,7 @@ end
1598
1658
 
1599
1659
  ## Contributing
1600
1660
 
1601
- Install [lefthook](https://github.com/evilmartians/lefthook)
1661
+ `lefthook` is pinned in [.tool-versions](/home/kalashnikovisme/projects/tramway/.tool-versions) so `mise` can resolve the shim used by `make install`.
1602
1662
 
1603
1663
  ```
1604
1664
  make install
@@ -0,0 +1,2 @@
1
+ /*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-800:oklch(44.4% .177 26.899);--color-red-900:oklch(39.6% .141 25.723);--color-orange-200:oklch(90.1% .076 70.697);--color-orange-400:oklch(75% .183 55.934);--color-orange-800:oklch(47% .157 37.304);--color-orange-900:oklch(40.8% .123 38.172);--color-yellow-400:oklch(85.2% .199 91.936);--color-yellow-800:oklch(47.6% .114 61.907);--color-yellow-900:oklch(42.1% .095 57.708);--color-green-400:oklch(79.2% .209 151.711);--color-green-600:oklch(62.7% .194 149.214);--color-green-800:oklch(44.8% .119 151.328);--color-green-900:oklch(39.3% .095 152.535);--color-teal-100:oklch(95.3% .051 180.801);--color-teal-200:oklch(91% .096 180.426);--color-teal-700:oklch(51.1% .096 186.391);--color-teal-800:oklch(43.7% .078 188.216);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-800:oklch(42.4% .199 265.638);--color-blue-900:oklch(37.9% .146 265.522);--color-indigo-400:oklch(67.3% .182 276.935);--color-indigo-800:oklch(39.8% .195 277.366);--color-indigo-900:oklch(35.9% .144 278.697);--color-violet-400:oklch(70.2% .183 293.541);--color-violet-800:oklch(43.2% .232 292.759);--color-violet-900:oklch(38% .189 293.745);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-zinc-50:oklch(98.5% 0 none);--color-zinc-100:oklch(96.7% .001 286.375);--color-zinc-200:oklch(92% .004 286.32);--color-zinc-300:oklch(87.1% .006 286.286);--color-zinc-400:oklch(70.5% .015 286.067);--color-zinc-500:oklch(55.2% .016 285.938);--color-zinc-700:oklch(37% .013 285.805);--color-zinc-800:oklch(27.4% .006 286.033);--color-zinc-900:oklch(21% .006 285.885);--color-zinc-950:oklch(14.1% .005 285.823);--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-lg:32rem;--container-3xl:48rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--leading-tight:1.25;--leading-snug:1.375;--radius-sm:.25rem;--radius-md:.375rem;--radius-xl:.75rem;--radius-2xl:1rem;--ease-out:cubic-bezier(0, 0, .2, 1);--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:0}.inset-x-0{inset-inline:0}.inset-y-0{inset-block:0}.top-0{top:0}.top-4{top:calc(var(--spacing) * 4)}.right-0{right:0}.right-4{right:calc(var(--spacing) * 4)}.right-6{right:calc(var(--spacing) * 6)}.bottom-0{bottom:0}.bottom-full{bottom:100%}.left-0{left:0}.left-1\/2{left:50%}.z-10{z-index:10}.z-40{z-index:40}.z-50{z-index:50}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-1{margin:var(--spacing)}.mx-auto{margin-inline:auto}.my-1{margin-block:var(--spacing)}.my-2{margin-block:calc(var(--spacing) * 2)}.my-4{margin-block:calc(var(--spacing) * 4)}.mt-1{margin-top:var(--spacing)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mt-10{margin-top:calc(var(--spacing) * 10)}.mt-auto{margin-top:auto}.mb-0{margin-bottom:0}.mb-1{margin-bottom:var(--spacing)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-8{margin-bottom:calc(var(--spacing) * 8)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-4{margin-left:calc(var(--spacing) * 4)}.box-border{box-sizing:border-box}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.h-1\/2{height:50%}.h-3{height:calc(var(--spacing) * 3)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-8{height:calc(var(--spacing) * 8)}.h-10{height:calc(var(--spacing) * 10)}.h-12{height:calc(var(--spacing) * 12)}.h-15{height:calc(var(--spacing) * 15)}.h-dvh{height:100dvh}.h-fit{height:fit-content}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-full{max-height:100%}.min-h-0{min-height:0}.min-h-2{min-height:calc(var(--spacing) * 2)}.min-h-4{min-height:calc(var(--spacing) * 4)}.min-h-6{min-height:calc(var(--spacing) * 6)}.min-h-8{min-height:calc(var(--spacing) * 8)}.min-h-10{min-height:calc(var(--spacing) * 10)}.min-h-12{min-height:calc(var(--spacing) * 12)}.min-h-15{min-height:calc(var(--spacing) * 15)}.min-h-40{min-height:calc(var(--spacing) * 40)}.min-h-60{min-height:calc(var(--spacing) * 60)}.min-h-dvh{min-height:100dvh}.w-3{width:calc(var(--spacing) * 3)}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-8{width:calc(var(--spacing) * 8)}.w-72{width:calc(var(--spacing) * 72)}.w-fit{width:fit-content}.w-full{width:100%}.w-max{width:max-content}.w-px{width:1px}.w-screen{width:100vw}.max-w-3xl{max-width:var(--container-3xl)}.max-w-full{max-width:100%}.max-w-lg{max-width:var(--container-lg)}.max-w-none{max-width:none}.max-w-sm{max-width:var(--container-sm)}.min-w-0{min-width:0}.min-w-2{min-width:calc(var(--spacing) * 2)}.min-w-4{min-width:calc(var(--spacing) * 4)}.min-w-6{min-width:calc(var(--spacing) * 6)}.min-w-40{min-width:calc(var(--spacing) * 40)}.min-w-96{min-width:calc(var(--spacing) * 96)}.flex-1{flex:1}.flex-auto{flex:auto}.flex-initial{flex:0 auto}.flex-none{flex:none}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-x-full{--tw-translate-x:-100%;translate:var(--tw-translate-x) var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-spin{animation:var(--animate-spin)}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-inside{list-style-position:inside}.list-disc{list-style-type:disc}.list-none{list-style-type:none}.appearance-none{appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.grid-cols-8{grid-template-columns:repeat(8,minmax(0,1fr))}.grid-cols-9{grid-template-columns:repeat(9,minmax(0,1fr))}.grid-cols-10{grid-template-columns:repeat(10,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-nowrap{flex-wrap:nowrap}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:var(--spacing)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(var(--spacing) * var(--tw-space-y-reverse));margin-block-end:calc(var(--spacing) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-1{column-gap:var(--spacing)}:where(.space-x-1>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(var(--spacing) * var(--tw-space-x-reverse));margin-inline-end:calc(var(--spacing) * calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-2>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 2) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-4>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 4) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-x-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-t-xl{border-top-left-radius:var(--radius-xl);border-top-right-radius:var(--radius-xl)}.rounded-tl-md{border-top-left-radius:var(--radius-md)}.rounded-tr-md{border-top-right-radius:var(--radius-md)}.rounded-b-none{border-bottom-right-radius:0;border-bottom-left-radius:0}.rounded-b-xl{border-bottom-right-radius:var(--radius-xl);border-bottom-left-radius:var(--radius-xl)}.rounded-bl-2xl{border-bottom-left-radius:var(--radius-2xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-dotted{--tw-border-style:dotted;border-style:dotted}.border-blue-800{border-color:var(--color-blue-800)}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-300{border-color:var(--color-gray-300)}.border-gray-600{border-color:var(--color-gray-600)}.border-gray-700{border-color:var(--color-gray-700)}.border-gray-800{border-color:var(--color-gray-800)}.border-green-800{border-color:var(--color-green-800)}.border-indigo-800{border-color:var(--color-indigo-800)}.border-orange-800{border-color:var(--color-orange-800)}.border-red-600{border-color:var(--color-red-600)}.border-red-800{border-color:var(--color-red-800)}.border-teal-200{border-color:var(--color-teal-200)}.border-teal-700{border-color:var(--color-teal-700)}.border-transparent{border-color:#0000}.border-violet-800{border-color:var(--color-violet-800)}.border-white{border-color:var(--color-white)}.border-yellow-800{border-color:var(--color-yellow-800)}.border-zinc-50{border-color:var(--color-zinc-50)}.border-zinc-100\/60{border-color:#f4f4f599}@supports (color:color-mix(in lab, red, red)){.border-zinc-100\/60{border-color:color-mix(in oklab, var(--color-zinc-100) 60%, transparent)}}.border-zinc-700{border-color:var(--color-zinc-700)}.border-zinc-700\/50{border-color:#3f3f4680}@supports (color:color-mix(in lab, red, red)){.border-zinc-700\/50{border-color:color-mix(in oklab, var(--color-zinc-700) 50%, transparent)}}.border-zinc-800{border-color:var(--color-zinc-800)}.\!bg-red-500{background-color:var(--color-red-500)!important}.\!bg-zinc-950{background-color:var(--color-zinc-950)!important}.bg-blue-500{background-color:var(--color-blue-500)}.bg-blue-600{background-color:var(--color-blue-600)}.bg-blue-900\/30{background-color:#1c398e4d}@supports (color:color-mix(in lab, red, red)){.bg-blue-900\/30{background-color:color-mix(in oklab, var(--color-blue-900) 30%, transparent)}}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-gray-200{background-color:var(--color-gray-200)}.bg-gray-700{background-color:var(--color-gray-700)}.bg-gray-800{background-color:var(--color-gray-800)}.bg-gray-800\/60{background-color:#1e293999}@supports (color:color-mix(in lab, red, red)){.bg-gray-800\/60{background-color:color-mix(in oklab, var(--color-gray-800) 60%, transparent)}}.bg-gray-900{background-color:var(--color-gray-900)}.bg-gray-900\/30{background-color:#1018284d}@supports (color:color-mix(in lab, red, red)){.bg-gray-900\/30{background-color:color-mix(in oklab, var(--color-gray-900) 30%, transparent)}}.bg-green-600{background-color:var(--color-green-600)}.bg-green-900\/30{background-color:#0d542b4d}@supports (color:color-mix(in lab, red, red)){.bg-green-900\/30{background-color:color-mix(in oklab, var(--color-green-900) 30%, transparent)}}.bg-indigo-900\/30{background-color:#312c854d}@supports (color:color-mix(in lab, red, red)){.bg-indigo-900\/30{background-color:color-mix(in oklab, var(--color-indigo-900) 30%, transparent)}}.bg-orange-400{background-color:var(--color-orange-400)}.bg-orange-900\/30{background-color:#7e2a0c4d}@supports (color:color-mix(in lab, red, red)){.bg-orange-900\/30{background-color:color-mix(in oklab, var(--color-orange-900) 30%, transparent)}}.bg-red-100{background-color:var(--color-red-100)}.bg-red-900\/30{background-color:#82181a4d}@supports (color:color-mix(in lab, red, red)){.bg-red-900\/30{background-color:color-mix(in oklab, var(--color-red-900) 30%, transparent)}}.bg-teal-100{background-color:var(--color-teal-100)}.bg-transparent{background-color:#0000}.bg-violet-900\/30{background-color:#4d179a4d}@supports (color:color-mix(in lab, red, red)){.bg-violet-900\/30{background-color:color-mix(in oklab, var(--color-violet-900) 30%, transparent)}}.bg-white{background-color:var(--color-white)}.bg-yellow-900\/30{background-color:#733e0a4d}@supports (color:color-mix(in lab, red, red)){.bg-yellow-900\/30{background-color:color-mix(in oklab, var(--color-yellow-900) 30%, transparent)}}.bg-zinc-50{background-color:var(--color-zinc-50)}.bg-zinc-800{background-color:var(--color-zinc-800)}.bg-zinc-900{background-color:var(--color-zinc-900)}.bg-zinc-900\/30{background-color:#18181b4d}@supports (color:color-mix(in lab, red, red)){.bg-zinc-900\/30{background-color:color-mix(in oklab, var(--color-zinc-900) 30%, transparent)}}.bg-zinc-900\/80{background-color:#18181bcc}@supports (color:color-mix(in lab, red, red)){.bg-zinc-900\/80{background-color:color-mix(in oklab, var(--color-zinc-900) 80%, transparent)}}.bg-zinc-950{background-color:var(--color-zinc-950)}.bg-zinc-950\/80{background-color:#09090bcc}@supports (color:color-mix(in lab, red, red)){.bg-zinc-950\/80{background-color:color-mix(in oklab, var(--color-zinc-950) 80%, transparent)}}.bg-zinc-950\/95{background-color:#09090bf2}@supports (color:color-mix(in lab, red, red)){.bg-zinc-950\/95{background-color:color-mix(in oklab, var(--color-zinc-950) 95%, transparent)}}.p-1{padding:var(--spacing)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-6{padding-block:calc(var(--spacing) * 6)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pt-16{padding-top:calc(var(--spacing) * 16)}.pb-1{padding-bottom:var(--spacing)}.pb-8{padding-bottom:calc(var(--spacing) * 8)}.pl-5{padding-left:calc(var(--spacing) * 5)}.pl-6{padding-left:calc(var(--spacing) * 6)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-6{--tw-leading:calc(var(--spacing) * 6);line-height:calc(var(--spacing) * 6)}.leading-7{--tw-leading:calc(var(--spacing) * 7);line-height:calc(var(--spacing) * 7)}.leading-none{--tw-leading:1;line-height:1}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.\!text-zinc-50{color:var(--color-zinc-50)!important}.text-blue-100\/90{color:#dbeafee6}@supports (color:color-mix(in lab, red, red)){.text-blue-100\/90{color:color-mix(in oklab, var(--color-blue-100) 90%, transparent)}}.text-blue-400{color:var(--color-blue-400)}.text-blue-800{color:var(--color-blue-800)}.text-current{color:currentColor}.text-gray-100{color:var(--color-gray-100)}.text-gray-200{color:var(--color-gray-200)}.text-gray-300{color:var(--color-gray-300)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-gray-800{color:var(--color-gray-800)}.text-gray-900{color:var(--color-gray-900)}.text-green-400{color:var(--color-green-400)}.text-green-800{color:var(--color-green-800)}.text-indigo-400{color:var(--color-indigo-400)}.text-indigo-800{color:var(--color-indigo-800)}.text-orange-400{color:var(--color-orange-400)}.text-orange-800{color:var(--color-orange-800)}.text-red-200{color:var(--color-red-200)}.text-red-400{color:var(--color-red-400)}.text-red-800{color:var(--color-red-800)}.text-teal-800{color:var(--color-teal-800)}.text-violet-400{color:var(--color-violet-400)}.text-violet-800{color:var(--color-violet-800)}.text-white{color:var(--color-white)}.text-yellow-400{color:var(--color-yellow-400)}.text-yellow-800{color:var(--color-yellow-800)}.text-zinc-50{color:var(--color-zinc-50)}.text-zinc-100{color:var(--color-zinc-100)}.text-zinc-200{color:var(--color-zinc-200)}.text-zinc-300{color:var(--color-zinc-300)}.text-zinc-400{color:var(--color-zinc-400)}.text-zinc-500{color:var(--color-zinc-500)}.text-zinc-800{color:var(--color-zinc-800)}.text-zinc-950{color:var(--color-zinc-950)}.capitalize{text-transform:capitalize}.italic{font-style:italic}.underline{text-decoration-line:underline}.placeholder-gray-400::placeholder{color:var(--color-gray-400)}.placeholder-gray-500::placeholder{color:var(--color-gray-500)}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring,.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-gray-200{--tw-ring-color:var(--color-gray-200)}.ring-gray-700{--tw-ring-color:var(--color-gray-700)}.ring-zinc-800{--tw-ring-color:var(--color-zinc-800)}.ring-offset-zinc-950{--tw-ring-offset-color:var(--color-zinc-950)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}@media (hover:hover){.group-hover\:visible:is(:where(.group):hover *){visibility:visible}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}.peer-hover\:visible:is(:where(.peer):hover~*){visibility:visible}.peer-hover\:opacity-100:is(:where(.peer):hover~*){opacity:1}}.peer-disabled\:cursor-not-allowed:is(:where(.peer):disabled~*){cursor:not-allowed}.peer-disabled\:opacity-70:is(:where(.peer):disabled~*){opacity:.7}.marker\:hidden ::marker{display:none}.marker\:hidden::marker{display:none}.marker\:hidden ::-webkit-details-marker{display:none}.marker\:hidden::-webkit-details-marker{display:none}.placeholder\:text-gray-400::placeholder{color:var(--color-gray-400)}.placeholder\:text-zinc-500::placeholder{color:var(--color-zinc-500)}.first\:block:first-child{display:block}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.open\:block:is([open],:popover-open,:open){display:block}@media (hover:hover){.hover\:border-gray-300:hover{border-color:var(--color-gray-300)}.hover\:bg-blue-400:hover{background-color:var(--color-blue-400)}.hover\:bg-blue-500:hover{background-color:var(--color-blue-500)}.hover\:bg-blue-900:hover{background-color:var(--color-blue-900)}.hover\:bg-gray-100:hover{background-color:var(--color-gray-100)}.hover\:bg-gray-300:hover{background-color:var(--color-gray-300)}.hover\:bg-gray-800:hover{background-color:var(--color-gray-800)}.hover\:bg-gray-900:hover{background-color:var(--color-gray-900)}.hover\:bg-green-400:hover{background-color:var(--color-green-400)}.hover\:bg-green-900:hover{background-color:var(--color-green-900)}.hover\:bg-indigo-900:hover{background-color:var(--color-indigo-900)}.hover\:bg-orange-200:hover{background-color:var(--color-orange-200)}.hover\:bg-orange-900:hover{background-color:var(--color-orange-900)}.hover\:bg-red-300:hover{background-color:var(--color-red-300)}.hover\:bg-red-900:hover{background-color:var(--color-red-900)}.hover\:bg-violet-900:hover{background-color:var(--color-violet-900)}.hover\:bg-yellow-900:hover{background-color:var(--color-yellow-900)}.hover\:bg-zinc-200:hover{background-color:var(--color-zinc-200)}.hover\:bg-zinc-800:hover{background-color:var(--color-zinc-800)}.hover\:bg-zinc-800\/80:hover{background-color:#27272acc}@supports (color:color-mix(in lab, red, red)){.hover\:bg-zinc-800\/80:hover{background-color:color-mix(in oklab, var(--color-zinc-800) 80%, transparent)}}.hover\:bg-zinc-900:hover{background-color:var(--color-zinc-900)}.hover\:text-gray-600:hover{color:var(--color-gray-600)}.hover\:text-gray-700:hover{color:var(--color-gray-700)}.hover\:text-zinc-50:hover{color:var(--color-zinc-50)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:border-blue-400:focus{border-color:var(--color-blue-400)}.focus\:border-blue-500:focus{border-color:var(--color-blue-500)}.focus\:border-gray-300:focus{border-color:var(--color-gray-300)}.focus\:ring-0:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-blue-200:focus{--tw-ring-color:var(--color-blue-200)}.focus\:ring-blue-500:focus{--tw-ring-color:var(--color-blue-500)}.focus\:ring-blue-500\/30:focus{--tw-ring-color:#3080ff4d}@supports (color:color-mix(in lab, red, red)){.focus\:ring-blue-500\/30:focus{--tw-ring-color:color-mix(in oklab, var(--color-blue-500) 30%, transparent)}}.focus\:ring-gray-300:focus{--tw-ring-color:var(--color-gray-300)}.focus\:ring-gray-600:focus{--tw-ring-color:var(--color-gray-600)}.focus\:ring-zinc-400:focus{--tw-ring-color:var(--color-zinc-400)}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus\:ring-offset-zinc-950:focus{--tw-ring-offset-color:var(--color-zinc-950)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:ring-0:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-zinc-300:focus-visible{--tw-ring-color:var(--color-zinc-300)}.focus-visible\:ring-zinc-400:focus-visible{--tw-ring-color:var(--color-zinc-400)}.focus-visible\:ring-offset-0:focus-visible{--tw-ring-offset-width:0px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.focus-visible\:ring-offset-zinc-950:focus-visible{--tw-ring-offset-color:var(--color-zinc-950)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-gray-100:disabled{background-color:var(--color-gray-100)}.disabled\:bg-gray-200:disabled{background-color:var(--color-gray-200)}.disabled\:text-gray-400:disabled{color:var(--color-gray-400)}.disabled\:text-gray-500:disabled{color:var(--color-gray-500)}.disabled\:opacity-50:disabled{opacity:.5}.data-\[state\=checked\]\:border-zinc-50[data-state=checked]{border-color:var(--color-zinc-50)}.data-\[state\=checked\]\:bg-zinc-50[data-state=checked]{background-color:var(--color-zinc-50)}.data-\[state\=checked\]\:text-zinc-950[data-state=checked]{color:var(--color-zinc-950)}@supports ((-webkit-backdrop-filter:var(--tw)) or (backdrop-filter:var(--tw))){.supports-\[backdrop-filter\]\:bg-zinc-950\/80{background-color:#09090bcc}@supports (color:color-mix(in lab, red, red)){.supports-\[backdrop-filter\]\:bg-zinc-950\/80{background-color:color-mix(in oklab, var(--color-zinc-950) 80%, transparent)}}}@media (min-width:40rem){.sm\:flex{display:flex}.sm\:hidden{display:none}.sm\:px-3{padding-inline:calc(var(--spacing) * 3)}.sm\:px-6{padding-inline:calc(var(--spacing) * 6)}.sm\:py-2{padding-block:calc(var(--spacing) * 2)}.sm\:text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.sm\:text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}@media (min-width:48rem){.md\:fixed{position:fixed}.md\:top-0{top:0}.md\:left-0{left:0}.md\:left-1\/2{left:50%}.md\:left-auto{left:auto}.md\:z-40{z-index:40}.md\:mt-8{margin-top:calc(var(--spacing) * 8)}.md\:block{display:block}.md\:flex{display:flex}.md\:hidden{display:none}.md\:h-dvh{height:100dvh}.md\:w-24{width:calc(var(--spacing) * 24)}.md\:w-72{width:calc(var(--spacing) * 72)}.md\:-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.md\:translate-x-0{--tw-translate-x:0px;translate:var(--tw-translate-x) var(--tw-translate-y)}.md\:grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.md\:grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.md\:grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.md\:grid-cols-8{grid-template-columns:repeat(8,minmax(0,1fr))}.md\:grid-cols-9{grid-template-columns:repeat(9,minmax(0,1fr))}.md\:grid-cols-10{grid-template-columns:repeat(10,minmax(0,1fr))}.md\:flex-col{flex-direction:column}.md\:justify-between{justify-content:space-between}.md\:gap-1{gap:var(--spacing)}:where(.md\:space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}.md\:overflow-hidden{overflow:hidden}.md\:rounded-full{border-radius:3.40282e38px}.md\:rounded-xl{border-radius:var(--radius-xl)}.md\:border{border-style:var(--tw-border-style);border-width:1px}.md\:border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.md\:border-zinc-800{border-color:var(--color-zinc-800)}.md\:bg-zinc-950{background-color:var(--color-zinc-950)}.md\:p-4{padding:calc(var(--spacing) * 4)}.md\:p-6{padding:calc(var(--spacing) * 6)}.md\:px-4{padding-inline:calc(var(--spacing) * 4)}.md\:py-3{padding-block:calc(var(--spacing) * 3)}.md\:pt-2{padding-top:calc(var(--spacing) * 2)}.md\:pr-72{padding-right:calc(var(--spacing) * 72)}.md\:pl-24{padding-left:calc(var(--spacing) * 24)}.md\:pl-72{padding-left:calc(var(--spacing) * 72)}.md\:text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.md\:text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.md\:shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.md\:backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.md\:transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.md\:duration-300{--tw-duration:.3s;transition-duration:.3s}.md\:ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}}@media (min-width:64rem){.lg\:text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}}.rtl\:text-right:where(:dir(rtl),[dir=rtl],[dir=rtl] *){text-align:right}@media (prefers-color-scheme:dark){@media (hover:hover){.dark\:hover\:bg-gray-700:hover{background-color:var(--color-gray-700)}}}.tramway-scrollbar{scrollbar-width:thin;scrollbar-color:#52525be6 #09090beb}.tramway-scrollbar::-webkit-scrollbar{width:.5rem}.tramway-scrollbar::-webkit-scrollbar-track{background:#09090beb}.tramway-scrollbar::-webkit-scrollbar-thumb{background:#52525be6;border-radius:9999px}.tramway-scrollbar::-webkit-scrollbar-thumb:hover{background:#71717af2}.tramway-scrollbar::-webkit-scrollbar-corner{background:0 0}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}
@@ -455,4 +455,177 @@ class Tooltip extends Controller {
455
455
  }
456
456
  }
457
457
 
458
- export { TramwaySelect, TableRowPreview, UiCheckbox, Tooltip }
458
+ class Navbar extends Controller {
459
+ connect() {
460
+ this.root = document.documentElement
461
+ this.desktopBreakpoint = 768
462
+ this.menuHiddenClass = 'hidden'
463
+ this.menuOffscreenClass = '-translate-x-full'
464
+ this.rootLockClass = 'overflow-hidden'
465
+ this.desktopNavbarExpandedWidthClass = 'md:w-72'
466
+ this.desktopNavbarCollapsedWidthClass = 'md:w-24'
467
+ this.desktopMainExpandedPaddingClass = 'md:pl-72'
468
+ this.desktopMainCollapsedPaddingClass = 'md:pl-24'
469
+ this.hiddenInteractionClasses = ['opacity-0', 'pointer-events-none']
470
+
471
+ this.desktopNavbar = this.element
472
+ this.desktopHeader = document.getElementById('desktop-navbar-header')
473
+ this.desktopMenu = document.getElementById('desktop-navbar-content')
474
+ this.desktopMainContainer = document.getElementById('tramway-main-container')
475
+ this.desktopToggleButton = document.getElementById('desktop-navbar-toggle-button')
476
+ this.desktopToggleIcon = document.getElementById('desktop-navbar-toggle-icon')
477
+ this.desktopToggleWrapper = document.getElementById('desktop-navbar-toggle-wrapper')
478
+ this.mobileButton = document.getElementById('mobile-menu-button')
479
+ this.mobileCloseButton = document.getElementById('mobile-menu-close-button')
480
+ this.mobileMenu = document.getElementById('mobile-menu')
481
+
482
+ this.handleMobileToggle = this.toggleMobileMenu.bind(this)
483
+ this.handleMobileClose = this.closeMobileMenu.bind(this)
484
+ this.handleBeforeCache = this.handleBeforeCache.bind(this)
485
+ this.handleResize = this.handleResize.bind(this)
486
+ this.handleDesktopToggle = this.toggleDesktopExpanded.bind(this)
487
+
488
+ this.bindMobileControls()
489
+ this.bindDesktopControls()
490
+ document.addEventListener('turbo:before-cache', this.handleBeforeCache)
491
+ window.addEventListener('resize', this.handleResize)
492
+
493
+ if (this.isDesktopViewport()) {
494
+ this.syncDesktopExpandedState()
495
+ }
496
+ }
497
+
498
+ disconnect() {
499
+ document.removeEventListener('turbo:before-cache', this.handleBeforeCache)
500
+ window.removeEventListener('resize', this.handleResize)
501
+ }
502
+
503
+ bindMobileControls() {
504
+ if (this.mobileButton) {
505
+ this.mobileButton.addEventListener('click', this.handleMobileToggle)
506
+ }
507
+
508
+ if (this.mobileCloseButton) {
509
+ this.mobileCloseButton.addEventListener('click', this.handleMobileClose)
510
+ }
511
+
512
+ if (this.mobileMenu) {
513
+ this.mobileMenu.querySelectorAll('a').forEach((link) => {
514
+ link.addEventListener('click', () => this.closeMobileMenu())
515
+ })
516
+ }
517
+ }
518
+
519
+ bindDesktopControls() {
520
+ if (this.isVertical() && this.desktopToggleButton) {
521
+ this.desktopToggleButton.addEventListener('click', this.handleDesktopToggle)
522
+ }
523
+ }
524
+
525
+ handleBeforeCache() {
526
+ this.closeMobileMenu({ hideImmediately: true })
527
+ }
528
+
529
+ handleResize() {
530
+ if (window.innerWidth >= 640) {
531
+ this.closeMobileMenu({ hideImmediately: true })
532
+ }
533
+
534
+ if (this.isDesktopViewport()) {
535
+ this.syncDesktopExpandedState()
536
+ }
537
+ }
538
+
539
+ toggleMobileMenu() {
540
+ if (!this.mobileMenu) return
541
+
542
+ if (this.mobileMenu.classList.contains(this.menuHiddenClass)) {
543
+ this.openMobileMenu()
544
+ return
545
+ }
546
+
547
+ this.closeMobileMenu()
548
+ }
549
+
550
+ openMobileMenu() {
551
+ if (!this.mobileMenu) return
552
+
553
+ this.mobileMenu.classList.remove(this.menuHiddenClass)
554
+ window.requestAnimationFrame(() => {
555
+ this.mobileMenu.classList.remove(this.menuOffscreenClass)
556
+ this.root.classList.add(this.rootLockClass)
557
+ })
558
+ }
559
+
560
+ closeMobileMenu({ hideImmediately = false } = {}) {
561
+ if (!this.mobileMenu) {
562
+ this.root.classList.remove(this.rootLockClass)
563
+ return
564
+ }
565
+
566
+ this.mobileMenu.classList.add(this.menuOffscreenClass)
567
+ this.root.classList.remove(this.rootLockClass)
568
+
569
+ if (hideImmediately) {
570
+ this.mobileMenu.classList.add(this.menuHiddenClass)
571
+ return
572
+ }
573
+
574
+ this.mobileMenu.addEventListener(
575
+ 'transitionend',
576
+ () => this.mobileMenu.classList.add(this.menuHiddenClass),
577
+ { once: true }
578
+ )
579
+ }
580
+
581
+ toggleDesktopExpanded() {
582
+ this.setDesktopExpanded(this.desktopNavbar.dataset.expanded === 'false')
583
+ }
584
+
585
+ syncDesktopExpandedState() {
586
+ this.setDesktopExpanded(this.desktopNavbar.dataset.expanded !== 'false')
587
+ }
588
+
589
+ setDesktopExpanded(expanded) {
590
+ if (!this.isVertical() || !this.desktopNavbar || !this.desktopHeader || !this.desktopMenu || !this.desktopMainContainer || !this.desktopToggleButton || !this.desktopToggleWrapper) {
591
+ return
592
+ }
593
+
594
+ this.desktopNavbar.classList.toggle(this.desktopNavbarExpandedWidthClass, expanded)
595
+ this.desktopNavbar.classList.toggle(this.desktopNavbarCollapsedWidthClass, !expanded)
596
+ this.desktopNavbar.dataset.expanded = expanded ? 'true' : 'false'
597
+
598
+ this.desktopMainContainer.classList.toggle(this.desktopMainExpandedPaddingClass, expanded)
599
+ this.desktopMainContainer.classList.toggle(this.desktopMainCollapsedPaddingClass, !expanded)
600
+
601
+ this.hiddenInteractionClasses.forEach((className) => {
602
+ this.desktopHeader.classList.toggle(className, !expanded)
603
+ this.desktopMenu.classList.toggle(className, !expanded)
604
+ })
605
+
606
+ this.desktopHeader.toggleAttribute('inert', !expanded)
607
+ this.desktopMenu.toggleAttribute('inert', !expanded)
608
+ this.desktopHeader.setAttribute('aria-hidden', expanded ? 'false' : 'true')
609
+ this.desktopMenu.setAttribute('aria-hidden', expanded ? 'false' : 'true')
610
+
611
+ this.desktopToggleWrapper.classList.toggle('justify-end', expanded)
612
+ this.desktopToggleWrapper.classList.toggle('justify-center', !expanded)
613
+ if (this.desktopToggleIcon) {
614
+ this.desktopToggleIcon.classList.toggle('rotate-180', !expanded)
615
+ }
616
+
617
+ this.desktopToggleButton.setAttribute('aria-label', expanded ? 'Collapse sidebar' : 'Expand sidebar')
618
+
619
+ this.desktopToggleButton.setAttribute('aria-expanded', expanded ? 'true' : 'false')
620
+ }
621
+
622
+ isVertical() {
623
+ return this.element.dataset.direction === 'vertical'
624
+ }
625
+
626
+ isDesktopViewport() {
627
+ return this.isVertical() && window.innerWidth >= this.desktopBreakpoint
628
+ }
629
+ }
630
+
631
+ export { TramwaySelect, TableRowPreview, UiCheckbox, Tooltip, Navbar }