style.css 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029
  1. :root {
  2. --background-primary: #f9f9f9;
  3. --background-secondary: #fff;
  4. --background-tertiary: #ddd;
  5. --background-accent: rgba(74, 144, 226, 0.75);
  6. --background-info: var(--background-accent);
  7. --background-success: rgba(76, 175, 80, 0.8);
  8. --background-warning: rgba(255, 152, 0, 0.8);
  9. --background-error: rgba(229, 57, 53, 0.8);
  10. --theme-primary: #6A9AD9;
  11. --theme-primary-hover: #A0CCF2;
  12. --theme-secondary: #C4B4A0;
  13. --theme-secondary-hover: #4E453F;
  14. --color-info: var(--theme-primary);
  15. --color-success: #4CAF50CC;
  16. --color-warning: #FF9800CC;
  17. --color-error: #E53935CC;
  18. --text-primary: #333;
  19. --text-secondary: #fff;
  20. --border-primary: var(--background-tertiary);
  21. --border-secondary: grey;
  22. --border-accent: var(--theme-primary);
  23. --border-hover: var(--theme-primary-hover);
  24. --shadow-primary: 0 0 20px var(--border-secondary);
  25. --transition-fast: 0.1s ease-in-out;
  26. --transition-medium: 0.250s ease;
  27. --transition-slow: 1s ease;
  28. }
  29. /* General
  30. /* General Styling */
  31. body {
  32. margin: 0;
  33. font-family: 'Roboto', sans-serif;
  34. background: var(--background-primary);
  35. display: flex;
  36. flex-direction: column;
  37. position: relative;
  38. }
  39. body * {
  40. box-sizing: border-box;
  41. }
  42. h1, h2 {
  43. margin: 0;
  44. }
  45. header {
  46. position: sticky;
  47. height: 50px;
  48. top: 0;
  49. z-index: 10;
  50. background: var(--background-primary);
  51. display: flex;
  52. justify-content: center;
  53. align-items: center;
  54. }
  55. h1, h2 {
  56. color: var(--theme-secondary-hover);
  57. transition: var(--transition-slow) color;
  58. }
  59. h3 {
  60. margin: 10px 0;
  61. }
  62. /* Inputs */
  63. input, select {
  64. display: block;
  65. width: 100%;
  66. padding: 10px;
  67. margin-bottom: 10px;
  68. border: 1px solid var(--border-primary);
  69. border-radius: 5px;
  70. font-size: 1rem;
  71. }
  72. /* Custom Input Wrapper */
  73. .custom-input {
  74. display: flex;
  75. align-items: center;
  76. gap: 10px;
  77. font-size: 1rem;
  78. color: var(--text-primary);
  79. cursor: pointer;
  80. flex: 1 1 auto;
  81. }
  82. /* Hide the Native Input */
  83. .custom-input input {
  84. display: none;
  85. }
  86. /* Checkbox and Radio Styles */
  87. .custom-checkbox,
  88. .custom-radio {
  89. display: inline-block;
  90. width: 20px;
  91. height: 20px;
  92. border: 2px solid var(--theme-primary);
  93. background-color: var(--background-secondary);
  94. position: relative;
  95. transition: background-color 0.3s ease, border-color 0.3s ease;
  96. }
  97. /* Checkbox Specific */
  98. .custom-checkbox {
  99. border-radius: 4px;
  100. }
  101. .custom-checkbox::after {
  102. content: '';
  103. width: 10px;
  104. height: 10px;
  105. background-color: var(--theme-primary);
  106. position: absolute;
  107. top: 50%;
  108. left: 50%;
  109. transform: translate(-50%, -50%) scale(0);
  110. transition: transform 0.2s ease-in-out;
  111. }
  112. /* Radio Specific */
  113. .custom-radio {
  114. border-radius: 50%;
  115. }
  116. .custom-radio::after {
  117. content: '';
  118. width: 10px;
  119. height: 10px;
  120. background-color: var(--theme-primary);
  121. position: absolute;
  122. top: 50%;
  123. left: 50%;
  124. transform: translate(-50%, -50%) scale(0);
  125. border-radius: 50%;
  126. transition: transform 0.2s ease-in-out;
  127. }
  128. /* Checked State */
  129. .custom-input input:checked + .custom-checkbox::after,
  130. .custom-input input:checked + .custom-radio::after {
  131. transform: translate(-50%, -50%) scale(1);
  132. }
  133. .custom-input input:checked + .custom-checkbox,
  134. .custom-input input:checked + .custom-radio {
  135. background-color: var(--theme-primary);
  136. border-color: var(--theme-primary-hover);
  137. }
  138. /* Focus State */
  139. .custom-input input:focus-visible + .custom-checkbox,
  140. .custom-input input:focus-visible + .custom-radio {
  141. outline: 2px dashed var(--theme-primary);
  142. outline-offset: 2px;
  143. }
  144. /* Hover Effects */
  145. .custom-checkbox:hover,
  146. .custom-radio:hover {
  147. border-color: var(--theme-primary-hover);
  148. }
  149. .dropdown {
  150. position: relative;
  151. display: inline-block;
  152. min-width: 200px;
  153. }
  154. .dropdown-button {
  155. border: none;
  156. cursor: pointer;
  157. display: inline-flex;
  158. align-items: center;
  159. justify-content: space-between;
  160. position: relative;
  161. width: 100%;
  162. height: 100%;
  163. padding: 0;
  164. }
  165. .dropdown-button > span {
  166. padding: 10px;
  167. }
  168. .dropdown-toggle {
  169. margin-left: 10px;
  170. cursor: pointer;
  171. user-select: none;
  172. height: 100%;
  173. aspect-ratio: 1 / 1;
  174. display: flex;
  175. justify-content: center;
  176. align-items: center;
  177. }
  178. .dropdown-toggle:hover {
  179. background: var(--text-secondary);
  180. color: var(--theme-primary);
  181. border-radius: 5px;
  182. }
  183. .dropdown-content {
  184. position: absolute;
  185. color: var(--theme-primary);
  186. background: var(--text-secondary);
  187. min-width: 120px;
  188. box-shadow: 0px 8px 16px rgba(0, 0, 0, 0.2);
  189. z-index: 1;
  190. display: none;
  191. border-radius: 5px
  192. }
  193. .dropdown-content button {
  194. width: 100%;
  195. color: var(--theme-primary);
  196. background: none;
  197. border: none;
  198. text-align: left;
  199. padding: 10px;
  200. cursor: pointer;
  201. }
  202. .dropdown-content button:hover {
  203. background-color: var(--background-tertiary);
  204. }
  205. /* Buttons */
  206. button {
  207. background: var(--theme-primary);
  208. color: var(--text-secondary);
  209. padding: 10px 15px;
  210. border: none;
  211. font-weight: bold;
  212. border-radius: 5px;
  213. cursor: pointer;
  214. font-size: 1rem;
  215. transition: background 0.3s ease,color 0.3s ease;
  216. }
  217. button:not(.no-bg):hover{
  218. background: var(--background-info);
  219. }
  220. button.cancel {
  221. flex-grow: 0;
  222. }
  223. button.cancel:hover {
  224. background: var(--color-error);
  225. }
  226. button.cta:hover {
  227. background: var(--color-success);
  228. }
  229. button.warn:hover {
  230. background: var(--color-warning);
  231. }
  232. button.warning:hover{}
  233. /* App Layout */
  234. .app {
  235. min-height: calc(100vh - 110px);
  236. display: flex;
  237. flex-direction: column;
  238. }
  239. .hidden:not(.sticky) {
  240. display: none !important;
  241. }
  242. /* Tabs */
  243. .tab-content {
  244. display: none;
  245. flex: 1;
  246. overflow-y: auto;
  247. background: var(--background-secondary);
  248. }
  249. .tab-content.active {
  250. display: flex;
  251. position: relative;
  252. flex-direction: column;
  253. }
  254. section {
  255. padding: 15px;
  256. display: flex;
  257. flex-direction: column;
  258. }
  259. section.main {
  260. flex-grow: 1;
  261. }
  262. section.debug {
  263. flex-direction: row;
  264. align-items: center;
  265. justify-content: space-between;
  266. }
  267. section.version {
  268. flex-direction: row;
  269. justify-content: space-between;
  270. flex-wrap: wrap;
  271. }
  272. .version .header {
  273. width: 100%;
  274. }
  275. .version #motor_selection h3 {
  276. width: 100%;
  277. flex-grow: 1;
  278. }
  279. .version #motor_selection {
  280. display: flex;
  281. flex-direction: row;
  282. flex-wrap: wrap;
  283. width: 100%;
  284. }
  285. .version select#manual_motor_type {
  286. margin: 0 20px 0 0;
  287. flex: 1;
  288. }
  289. section.sticky {
  290. position: fixed;
  291. background-color: rgba(255, 255, 255, 0.5);
  292. backdrop-filter: blur(10px);
  293. bottom: 60px;
  294. border-top: 1px solid var(--border-primary);
  295. box-shadow: var(--shadow-primary);
  296. transform: translateY(0);
  297. transition: 250ms transform, 250ms height;
  298. visibility: visible;
  299. max-height: 70vh;
  300. width: 100%;
  301. z-index: 10;
  302. }
  303. section.sticky.fullscreen {
  304. position: fixed;
  305. top: 0;
  306. left: 0;
  307. width: 100vw;
  308. max-height: none;
  309. }
  310. section.sticky.hidden {
  311. transform: translateY(100%);
  312. visibility: hidden;
  313. width: 100%;
  314. position: absolute;
  315. overflow:hidden;
  316. height: 0;
  317. padding: 0;
  318. }
  319. section .header {
  320. position: relative;
  321. display: flex;
  322. justify-content: space-between;
  323. align-items: center;
  324. margin-bottom: 10px;
  325. width: 100%;
  326. }
  327. section .header h2 {
  328. flex-grow: 1;
  329. }
  330. /* Close Button Styling */
  331. .close-button,
  332. .fullscreen-button {
  333. background: none;
  334. border: none;
  335. font-size: 1.5rem;
  336. font-weight: bold;
  337. color: var(--text-primary);
  338. cursor: pointer;
  339. line-height: 1;
  340. padding: 0;
  341. height: 100%;
  342. width: auto;
  343. aspect-ratio: 1 / 1;
  344. display: flex;
  345. justify-content: center;
  346. align-items: center;
  347. margin-left: 10px;
  348. }
  349. .close-button:hover {
  350. color: var(--color-error);
  351. }
  352. .fullscreen-button:hover {
  353. color: var(--color-warning);
  354. }
  355. section .header .add-button {
  356. height: 35px;
  357. width: 35px;
  358. font-size: 1.5rem;
  359. padding: 0;
  360. }
  361. /* Playlist */
  362. .add-to-playlist {
  363. margin-top: 15px;
  364. }
  365. .add-to-playlist button {
  366. margin-bottom: 10px;
  367. }
  368. .add-to-container {
  369. display: flex;
  370. flex-wrap: wrap;
  371. margin-bottom: 20px;
  372. }
  373. #add-to-playlist-container select,
  374. #add-to-playlist-container button {
  375. margin-top: 10px;
  376. display: block;
  377. width: 100%;
  378. }
  379. .playlist-parameters {
  380. display: flex;
  381. flex-direction: column;
  382. gap: 10px;
  383. }
  384. .playlist-parameters .control-group button.small.cancel {
  385. align-self: flex-end;
  386. margin-bottom: 4px;
  387. }
  388. #clear_pattern {
  389. margin: 0;
  390. }
  391. .playlist-parameters .input-group input,
  392. .playlist-parameters .input-group select {
  393. width: 100%; /* Ensure inputs/selects stretch to full width */
  394. padding: 10px;
  395. border: 1px solid var(--border-primary);
  396. border-radius: 5px;
  397. font-size: 1rem;
  398. }
  399. .empty-placeholder {
  400. color: gray;
  401. font-style: italic;
  402. text-align: center;
  403. padding: 10px;
  404. }
  405. /* Style for the filename span */
  406. .filename {
  407. flex-grow: 1; /* Use available space */
  408. font-size: 1rem;
  409. color: var(--text-primary);
  410. margin-right: 10px; /* Space between filename and buttons */
  411. word-wrap: break-word;
  412. width: 100%;
  413. display: flex;
  414. align-items: center;
  415. }
  416. /* File List */
  417. .file-list {
  418. list-style: none;
  419. padding: 0;
  420. margin: 0;
  421. border: 1px solid var(--border-primary);
  422. border-radius: 5px;
  423. overflow-y: auto;
  424. background: var(--background-primary);
  425. flex-grow: 1;
  426. }
  427. .file-list li {
  428. display: flex;
  429. padding: 10px;
  430. border-bottom: 1px solid var(--border-primary);
  431. cursor: pointer;
  432. transition: background-color 0.3s ease;
  433. }
  434. .file-list li:hover {
  435. background-color: var(--background-tertiary);
  436. }
  437. .file-list li.selected {
  438. background: var(--theme-primary);
  439. color: var(--text-secondary);
  440. font-weight: bold;
  441. }
  442. .file-list li.selected .filename {
  443. font-weight: bold;
  444. color: var(--text-secondary);
  445. }
  446. .file-list button {
  447. margin-left: 5px;
  448. background: none;
  449. color: black;
  450. font-weight: bold;
  451. height: 40px;
  452. width: 40px;
  453. flex: 0 0 auto;
  454. display: flex;
  455. justify-content: center;
  456. align-items: center;
  457. }
  458. .file-list button:hover:not(:focus) {
  459. background: var(--background-primary);
  460. box-shadow: inset 0 0 4px var(--border-secondary);
  461. }
  462. .file-list button.remove-button {
  463. color: var(--color-error);
  464. }
  465. .title-container {
  466. display: flex;
  467. justify-content: space-between;
  468. align-items: center;
  469. }
  470. .rename-button {
  471. margin-left: 10px;
  472. background: var(--theme-primary-hover);
  473. color: var(--text-secondary);
  474. border: none;
  475. border-radius: 5px;
  476. padding: 5px 10px;
  477. cursor: pointer;
  478. transition: background 0.3s ease;
  479. }
  480. /* Bottom Navigation */
  481. .bottom-nav {
  482. display: flex;
  483. position: sticky;
  484. justify-content: space-around;
  485. bottom: 0;
  486. height: 60px;
  487. width: 100%;
  488. border-top: 1px solid var(--theme-primary);
  489. flex-wrap: wrap;
  490. z-index: 10;
  491. }
  492. .tab-button {
  493. flex: 1;
  494. padding: 20px 10px;
  495. text-align: center;
  496. font-size: 1rem;
  497. font-weight: bold;
  498. color: var(--text-secondary);
  499. background: none;
  500. border: none;
  501. cursor: pointer;
  502. transition: background 0.3s ease;
  503. background: var(--background-info);
  504. backdrop-filter: blur(2px);
  505. border-radius: 0;
  506. }
  507. .bottom-nav .tab-button.active {
  508. background: rgba(255, 255, 255, 0.75);
  509. color: var(--theme-primary);
  510. }
  511. /* Quick Action Buttons */
  512. .action-buttons {
  513. display: flex;
  514. gap: 10px;
  515. flex-wrap: wrap;
  516. width: 100%;
  517. justify-content: flex-end;
  518. }
  519. .action-buttons button {
  520. flex: 1;
  521. }
  522. .action-buttons button.small {
  523. flex: 0;
  524. flex-basis: calc(25% - 10px);
  525. }
  526. .action-buttons button.cta {
  527. flex-grow: 1;
  528. }
  529. button#debug_button {
  530. width: 40px;
  531. padding: 0;
  532. height: 40px;
  533. background: transparent;
  534. font-size: 1.5rem;
  535. margin-left: 40px;
  536. flex: 0 0 auto;
  537. transition: 250ms all;
  538. }
  539. button#debug_button:hover,
  540. button#debug_button.active {
  541. box-shadow: inset 0 0 4px var(--border-secondary);
  542. }
  543. #settings-tab button.cancel {
  544. flex-basis: 100%;
  545. }
  546. #settings-tab .dropdown {
  547. min-width: 66.66%;
  548. }
  549. /* Preview Canvas */
  550. #patternPreviewCanvas {
  551. width: 100%;
  552. max-width: 300px;
  553. aspect-ratio: 1/1;
  554. border: 1px solid var(--border-primary);
  555. background: var(--theme-secondary);
  556. border-radius: 100%;
  557. padding: 30px;
  558. }
  559. #pattern-preview {
  560. display: flex;
  561. flex-direction: column;
  562. align-items: center;
  563. margin-bottom: 20px;
  564. }
  565. #pattern-preview-container.fullscreen #patternPreviewCanvas {
  566. width: initial;
  567. max-width: calc(100vw - 30px);
  568. }
  569. /* Currently Playing Section Styling */
  570. #currently-playing-container {
  571. align-items: center;
  572. }
  573. #currentlyPlayingCanvas {
  574. width: 100%;
  575. max-width: 300px;
  576. aspect-ratio: 1/1;
  577. border: 1px solid var(--border-primary);
  578. background: var(--theme-secondary);
  579. border-radius: 100%;
  580. padding: 20px;
  581. }
  582. #currently-playing-details {
  583. display: flex;
  584. flex-direction: column;
  585. align-items: center;
  586. margin-bottom: 15px;
  587. }
  588. #currently-playing-details p {
  589. margin: 5px 0;
  590. color: var(--text-primary);
  591. font-size: 1rem;
  592. }
  593. #progress-container {
  594. display: flex;
  595. align-items: center;
  596. justify-content: center;
  597. width: 100%;
  598. margin-bottom: 10px;
  599. flex-wrap: wrap;
  600. }
  601. #play_progress {
  602. width: 100%;
  603. height: 8px;
  604. appearance: none;
  605. background-color: var(--border-primary);
  606. border-radius: 4px;
  607. overflow: hidden;
  608. }
  609. #play_progress::-webkit-progress-bar {
  610. background-color: var(--border-primary);
  611. }
  612. #play_progress::-webkit-progress-value {
  613. background-color: var(--theme-primary);
  614. transition: width 0.25s ease;
  615. }
  616. #play_progress_text {
  617. font-size: 0.9rem;
  618. margin-left: 10px;
  619. color: var(--text-primary);
  620. }
  621. .play-buttons {
  622. display: flex;
  623. gap: 30px;
  624. }
  625. .play-buttons button {
  626. width: 75px;
  627. height: 75px;
  628. aspect-ratio: 1/1;
  629. font-size: 3rem;
  630. border: none;
  631. cursor: pointer;
  632. display: flex;
  633. justify-content: center;
  634. }
  635. #pausePlayCurrent {
  636. border-radius: 50%;
  637. }
  638. /* Debug Log */
  639. #status_log {
  640. background: #000;
  641. color: var(--text-secondary);
  642. font-family: monospace;
  643. font-size: 0.9rem;
  644. border-top: 1px solid var(--border-primary);
  645. padding: 10px;
  646. max-height: 200px;
  647. overflow-y: scroll;
  648. display: none;
  649. width: 100%;
  650. }
  651. #status_log p {
  652. margin: 0;
  653. }
  654. .control-group {
  655. display: flex;
  656. margin-bottom: 10px;
  657. flex-wrap: wrap;
  658. width: 100%;
  659. align-items: center;
  660. justify-content: space-between;
  661. gap: 0 10px;
  662. }
  663. .control-group input {
  664. margin-bottom: 0;
  665. }
  666. .control-group h3 {
  667. width: 100%;
  668. }
  669. .control-group .item {
  670. display: flex;
  671. align-items: center;
  672. flex: 1;
  673. }
  674. .control-group .item.cta {
  675. justify-content: flex-end;
  676. }
  677. .control-group .item.column {
  678. flex-direction: column;
  679. text-align: center;
  680. }
  681. .control-group .item label {
  682. padding: 5px;
  683. }
  684. #serial_ports_container > * {
  685. display: inline-block;
  686. }
  687. #serial_ports_container select {
  688. margin: 10px;
  689. flex-basis: 100px;
  690. flex-grow: 0;
  691. }
  692. #serial_ports {
  693. width: auto;
  694. min-width: 200px;
  695. }
  696. #serial_status_container {
  697. margin-bottom: 10px;
  698. }
  699. #serial_status_header::before {
  700. content: '';
  701. width: 20px;
  702. height: 20px;
  703. border-radius: 50%;
  704. margin-right: 8px;
  705. background-color: var(--text-primary);
  706. display: inline-block;
  707. transition: var(--transition-slow) background-color;
  708. }
  709. #serial_status_header.connected::before {
  710. background-color: var(--color-success);
  711. }
  712. #serial_status_header.not-connected::before {
  713. background-color: var(--color-error);
  714. }
  715. #serial_ports_buttons {
  716. display: inline-block;
  717. }
  718. .status.connected {
  719. color: var(--color-success);
  720. font-weight: bold;
  721. }
  722. .status.not-connected {
  723. color: var(--color-error);
  724. font-weight: bold;
  725. }
  726. /* Speed Control Section */
  727. .speed-control {
  728. display: flex;
  729. }
  730. .speed-control label {
  731. font-weight: bold;
  732. font-size: 1rem;
  733. color: var(--text-primary);
  734. flex-shrink: 0;
  735. }
  736. .speed-control input[type="number"] {
  737. width: 100px; /* Consistent input width */
  738. padding: 8px;
  739. font-size: 1rem;
  740. border: 1px solid var(--border-primary);
  741. border-radius: 5px;
  742. outline: none;
  743. transition: all 0.3s ease;
  744. }
  745. input[type="number"]:focus {
  746. border-color: var(--theme-primary);
  747. box-shadow: 0 0 4px var(--background-info);
  748. }
  749. #speed_status {
  750. margin-top: 10px;
  751. font-size: 0.9rem;
  752. }
  753. #serial_ports_container > * {
  754. display: inline-block;
  755. }
  756. #serial_ports_container select {
  757. margin: 10px;
  758. flex-basis: 100px;
  759. flex-grow: 0;
  760. }
  761. #serial_ports {
  762. width: auto;
  763. min-width: 200px;
  764. }
  765. #serial_status_container,
  766. #serial_ports_buttons {
  767. display: inline-block;
  768. }
  769. /* Notification Styles */
  770. .notification {
  771. display: flex;
  772. position: absolute;
  773. top: 0;
  774. left: 0;
  775. font-weight: bold;
  776. z-index: 1000;
  777. color: var(--text-secondary);
  778. width: 100%;
  779. height: 100%;
  780. justify-content: center;
  781. align-items: center;
  782. backdrop-filter: blur(2px);
  783. opacity: 0;
  784. transition: opacity 250ms ease-in-out;
  785. }
  786. .notification.show {
  787. opacity: 1; /* Fully visible */
  788. }
  789. .notification .close-button {
  790. color: var(--text-secondary);
  791. font-size: 2rem;
  792. top: 0;
  793. right: 0;
  794. position: absolute;
  795. }
  796. /* Notification Types */
  797. .notification.success { background-color: var(--background-success); }
  798. .notification.warning { background-color: var(--background-warning); }
  799. .notification.error { background-color: var(--background-error); }
  800. .notification.info { background-color: var(--background-info); }
  801. .footer {
  802. align-items: center;
  803. display: flex;
  804. flex-wrap: wrap;
  805. justify-content: space-between;
  806. margin-bottom: 20px;
  807. width: 100%;
  808. }
  809. #github {
  810. align-content: center;
  811. display: flex;
  812. font-size: 0.8em;
  813. }
  814. #github img {
  815. margin: 0 5px
  816. }
  817. /* Responsive Design */
  818. @media (max-width: 1023px) {
  819. body {
  820. font-size: 0.9rem;
  821. }
  822. .tab-button {
  823. font-size: 0.9rem;
  824. }
  825. .footer {
  826. display: none;
  827. }
  828. button.cancel {
  829. background: var(--color-error);
  830. }
  831. button.cta {
  832. background: var(--color-success);
  833. }
  834. button.warn {
  835. background: var(--color-warning);
  836. }
  837. button.cancel:hover,
  838. button.warn:hover,
  839. button.cta:hover {
  840. background: var(--theme-primary);
  841. }
  842. }
  843. /* On larger screens, display all tabs in a 3-column grid */
  844. @media screen and (min-width: 1024px) {
  845. .app {
  846. display: grid;
  847. grid-template-columns: repeat(3, 1fr);
  848. gap: 0 16px;
  849. height: calc(100vh - 60px);
  850. }
  851. .bottom-nav {
  852. display: none;
  853. }
  854. #status_log {
  855. grid-column: span 3;
  856. align-self: flex-end;
  857. height: 100%;
  858. }
  859. section.sticky {
  860. position: sticky;
  861. bottom: 0;
  862. }
  863. /* Show all tabs in grid layout */
  864. .tab-content {
  865. display: flex !important; /* Always display tab-content */
  866. flex-direction: column;
  867. border: 1px solid var(--border-primary);
  868. background-color: var(--background-primary);
  869. border-radius: 8px;
  870. overflow-y: auto;
  871. overflow-x: hidden;
  872. position: relative;
  873. }
  874. }