@necrolab/dashboard 0.5.13 → 0.5.15

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.
@@ -17,6 +17,7 @@
17
17
  ### Task 1.1: Extend Tailwind Color Tokens
18
18
 
19
19
  **Files:**
20
+
20
21
  - Modify: `tailwind.config.js:30-77`
21
22
 
22
23
  **Step 1: Add extended dark scale for rgba replacements**
@@ -98,6 +99,7 @@ git commit -m "feat: extend Tailwind color tokens for theme consolidation
98
99
  ### Task 1.2: Extend Shadow System
99
100
 
100
101
  **Files:**
102
+
101
103
  - Modify: `tailwind.config.js:135-138`
102
104
 
103
105
  **Step 1: Replace boxShadow extend section**
@@ -171,6 +173,7 @@ git commit -m "feat: extend Tailwind design tokens
171
173
  ### Task 2.1: Clean Up App.vue iPhone Landscape Code
172
174
 
173
175
  **Files:**
176
+
174
177
  - Modify: `src/App.vue`
175
178
 
176
179
  **Step 1: Read current App.vue**
@@ -180,6 +183,7 @@ Run: Read `src/App.vue`
180
183
  **Step 2: Remove iPhone landscape lock overlay**
181
184
 
182
185
  Find and remove:
186
+
183
187
  - `.landscape-lock` class styles (lines ~739-796)
184
188
  - `.landscape-lock-content` styles
185
189
  - `LandscapeLockIcon` component
@@ -189,6 +193,7 @@ Find and remove:
189
193
  **Step 3: Remove mobile-landscape breakpoint styles**
190
194
 
191
195
  Search for `@media` queries containing:
196
+
192
197
  - `mobile-landscape`
193
198
  - `(orientation: landscape) and (max-height: 500px)`
194
199
 
@@ -217,6 +222,7 @@ git commit -m "refactor: remove iPhone landscape support
217
222
  ### Task 2.2: Update Tailwind Config - Remove Landscape Breakpoints
218
223
 
219
224
  **Files:**
225
+
220
226
  - Modify: `tailwind.config.js:92-116`
221
227
 
222
228
  **Step 1: Remove mobile-landscape breakpoint**
@@ -261,6 +267,7 @@ git commit -m "refactor: remove mobile-landscape breakpoint
261
267
  ### Task 3.1: Create StatusBadge Component
262
268
 
263
269
  **Files:**
270
+
264
271
  - Create: `src/components/ui/StatusBadge.vue`
265
272
  - Test: Manual testing in Account.vue, Profile.vue
266
273
 
@@ -268,48 +275,47 @@ git commit -m "refactor: remove mobile-landscape breakpoint
268
275
 
269
276
  ```vue
270
277
  <script setup>
271
- import { defineProps } from 'vue'
272
- import CheckmarkIcon from '@/assets/icons/checkmark.svg'
273
- import CloseXIcon from '@/assets/icons/close-x.svg'
278
+ import CheckmarkIcon from "@/assets/icons/checkmark.svg";
279
+ import CloseXIcon from "@/assets/icons/close-x.svg";
274
280
 
275
281
  const props = defineProps({
276
- enabled: {
277
- type: Boolean,
278
- required: true
279
- },
280
- size: {
281
- type: String,
282
- default: 'small',
283
- validator: (value) => ['small', 'large'].includes(value)
284
- }
285
- })
282
+ enabled: {
283
+ type: Boolean,
284
+ required: true
285
+ },
286
+ size: {
287
+ type: String,
288
+ default: "small",
289
+ validator: (value) => ["small", "large"].includes(value)
290
+ }
291
+ });
286
292
 
287
293
  const sizeClasses = {
288
- small: 'w-6 h-6',
289
- large: 'w-[26px] h-[26px]'
290
- }
294
+ small: "w-6 h-6",
295
+ large: "w-[26px] h-[26px]"
296
+ };
291
297
 
292
- const enabledClasses = 'bg-accent-green/20 border-accent-green/30'
293
- const disabledClasses = 'bg-red-500/20 border-red-500/30'
298
+ const enabledClasses = "bg-accent-green/20 border-accent-green/30";
299
+ const disabledClasses = "bg-red-500/20 border-red-500/30";
294
300
  </script>
295
301
 
296
302
  <template>
297
- <div
298
- :class="[
299
- 'flex items-center justify-center rounded-full border-2 transition-all duration-200',
300
- enabled ? enabledClasses : disabledClasses,
301
- sizeClasses[size]
302
- ]"
303
- >
304
- <CheckmarkIcon v-if="enabled" class="w-3 h-3 text-accent-green" />
305
- <CloseXIcon v-else class="w-3 h-3 text-red-500" />
306
- </div>
303
+ <div
304
+ :class="[
305
+ 'flex items-center justify-center rounded-full border-2 transition-all duration-200',
306
+ enabled ? enabledClasses : disabledClasses,
307
+ sizeClasses[size]
308
+ ]">
309
+ <CheckmarkIcon v-if="enabled" class="h-3 w-3 text-accent-green" />
310
+ <CloseXIcon v-else class="h-3 w-3 text-red-500" />
311
+ </div>
307
312
  </template>
308
313
  ```
309
314
 
310
315
  **Step 2: Test component in isolation**
311
316
 
312
317
  Create temporary test in a view to verify rendering:
318
+
313
319
  - Enabled state
314
320
  - Disabled state
315
321
  - Small size
@@ -332,6 +338,7 @@ git commit -m "feat: create StatusBadge component
332
338
  ### Task 3.2: Replace StatusBadge in Account.vue
333
339
 
334
340
  **Files:**
341
+
335
342
  - Modify: `src/components/Editors/Account/Account.vue`
336
343
 
337
344
  **Step 1: Import StatusBadge**
@@ -339,7 +346,7 @@ git commit -m "feat: create StatusBadge component
339
346
  Add to imports:
340
347
 
341
348
  ```javascript
342
- import StatusBadge from '@/components/ui/StatusBadge.vue'
349
+ import StatusBadge from "@/components/ui/StatusBadge.vue";
343
350
  ```
344
351
 
345
352
  **Step 2: Replace enabled badge markup**
@@ -353,6 +360,7 @@ Find lines with class `enabled-badge` or `disabled-badge` and replace with:
353
360
  **Step 3: Remove old badge styles**
354
361
 
355
362
  Remove from `<style scoped>`:
363
+
356
364
  - `.enabled-badge` class (lines ~60-105)
357
365
  - `.disabled-badge` class
358
366
 
@@ -377,6 +385,7 @@ git commit -m "refactor: use StatusBadge component in Account.vue
377
385
  ### Task 3.3: Replace StatusBadge in Profile.vue
378
386
 
379
387
  **Files:**
388
+
380
389
  - Modify: `src/components/Editors/Profile/Profile.vue`
381
390
 
382
391
  **Step 1: Import StatusBadge**
@@ -399,6 +408,7 @@ git commit -m "refactor: use StatusBadge component in Profile.vue"
399
408
  ### Task 3.4: Replace StatusBadge in CreateAccount.vue
400
409
 
401
410
  **Files:**
411
+
402
412
  - Modify: `src/components/Editors/Account/CreateAccount.vue`
403
413
 
404
414
  **Step 1-5:** Same as Task 3.3
@@ -415,6 +425,7 @@ git commit -m "refactor: use StatusBadge component in CreateAccount.vue"
415
425
  ### Task 3.5: Replace StatusBadge in CreateProfile.vue
416
426
 
417
427
  **Files:**
428
+
418
429
  - Modify: `src/components/Editors/Profile/CreateProfile.vue`
419
430
 
420
431
  **Step 1-5:** Same as Task 3.3
@@ -431,6 +442,7 @@ git commit -m "refactor: use StatusBadge component in CreateProfile.vue"
431
442
  ### Task 3.6: Create useRowSelection Composable
432
443
 
433
444
  **Files:**
445
+
434
446
  - Create: `src/composables/useRowSelection.js`
435
447
 
436
448
  **Step 1: Create composable file**
@@ -446,43 +458,43 @@ git commit -m "refactor: use StatusBadge component in CreateProfile.vue"
446
458
  * @returns {Object} Event handlers for @dblclick, @touchstart, @touchend
447
459
  */
448
460
  export function useRowSelection(toggleCallback) {
449
- let lastTapTime = 0
450
- const DOUBLE_TAP_DELAY = 300
451
-
452
- const handleDoubleClick = (event) => {
453
- // Don't trigger on button or checkbox clicks
454
- if (event.target.closest('button') || event.target.closest('.checkbox')) {
455
- return
456
- }
457
- toggleCallback()
458
- }
459
-
460
- const handleTouchStart = (event) => {
461
- const currentTime = Date.now()
462
- const tapGap = currentTime - lastTapTime
463
-
464
- if (tapGap < DOUBLE_TAP_DELAY && tapGap > 0) {
465
- // Don't trigger on button or checkbox taps
466
- if (!event.target.closest('button') && !event.target.closest('.checkbox')) {
467
- event.preventDefault()
468
- toggleCallback()
469
- }
470
- }
471
- lastTapTime = currentTime
472
- }
473
-
474
- const handleTouchEnd = (event) => {
475
- // Prevent default touch behavior on buttons/checkboxes
476
- if (event.target.closest('button') || event.target.closest('.checkbox')) {
477
- return
478
- }
479
- }
480
-
481
- return {
482
- handleDoubleClick,
483
- handleTouchStart,
484
- handleTouchEnd
485
- }
461
+ let lastTapTime = 0;
462
+ const DOUBLE_TAP_DELAY = 300;
463
+
464
+ const handleDoubleClick = (event) => {
465
+ // Don't trigger on button or checkbox clicks
466
+ if (event.target.closest("button") || event.target.closest(".checkbox")) {
467
+ return;
468
+ }
469
+ toggleCallback();
470
+ };
471
+
472
+ const handleTouchStart = (event) => {
473
+ const currentTime = Date.now();
474
+ const tapGap = currentTime - lastTapTime;
475
+
476
+ if (tapGap < DOUBLE_TAP_DELAY && tapGap > 0) {
477
+ // Don't trigger on button or checkbox taps
478
+ if (!event.target.closest("button") && !event.target.closest(".checkbox")) {
479
+ event.preventDefault();
480
+ toggleCallback();
481
+ }
482
+ }
483
+ lastTapTime = currentTime;
484
+ };
485
+
486
+ const handleTouchEnd = (event) => {
487
+ // Prevent default touch behavior on buttons/checkboxes
488
+ if (event.target.closest("button") || event.target.closest(".checkbox")) {
489
+ return;
490
+ }
491
+ };
492
+
493
+ return {
494
+ handleDoubleClick,
495
+ handleTouchStart,
496
+ handleTouchEnd
497
+ };
486
498
  }
487
499
  ```
488
500
 
@@ -502,12 +514,13 @@ git commit -m "feat: create useRowSelection composable
502
514
  ### Task 3.7: Use useRowSelection in Task.vue
503
515
 
504
516
  **Files:**
517
+
505
518
  - Modify: `src/components/Tasks/Task.vue`
506
519
 
507
520
  **Step 1: Import composable**
508
521
 
509
522
  ```javascript
510
- import { useRowSelection } from '@/composables/useRowSelection'
523
+ import { useRowSelection } from "@/composables/useRowSelection";
511
524
  ```
512
525
 
513
526
  **Step 2: Use composable in setup**
@@ -516,8 +529,8 @@ Replace manual event handler logic with:
516
529
 
517
530
  ```javascript
518
531
  const { handleDoubleClick, handleTouchStart, handleTouchEnd } = useRowSelection(() => {
519
- emit('toggle', props.task)
520
- })
532
+ emit("toggle", props.task);
533
+ });
521
534
  ```
522
535
 
523
536
  **Step 3: Update template event handlers**
@@ -525,11 +538,7 @@ const { handleDoubleClick, handleTouchStart, handleTouchEnd } = useRowSelection(
525
538
  Replace existing `@dblclick`, `@touchstart`, `@touchend` with:
526
539
 
527
540
  ```vue
528
- <tr
529
- @dblclick="handleDoubleClick"
530
- @touchstart="handleTouchStart"
531
- @touchend="handleTouchEnd"
532
- >
541
+ <tr @dblclick="handleDoubleClick" @touchstart="handleTouchStart" @touchend="handleTouchEnd"></tr>
533
542
  ```
534
543
 
535
544
  **Step 4: Remove old event handler code**
@@ -558,6 +567,7 @@ git commit -m "refactor: use useRowSelection composable in Task.vue
558
567
  ### Task 3.8: Use useRowSelection in Account.vue
559
568
 
560
569
  **Files:**
570
+
561
571
  - Modify: `src/components/Editors/Account/Account.vue`
562
572
 
563
573
  **Step 1-6:** Same as Task 3.7, adapted for Account component
@@ -574,6 +584,7 @@ git commit -m "refactor: use useRowSelection composable in Account.vue"
574
584
  ### Task 3.9: Use useRowSelection in Profile.vue
575
585
 
576
586
  **Files:**
587
+
577
588
  - Modify: `src/components/Editors/Profile/Profile.vue`
578
589
 
579
590
  **Step 1-6:** Same as Task 3.7, adapted for Profile component
@@ -590,12 +601,13 @@ git commit -m "refactor: use useRowSelection composable in Profile.vue"
590
601
  ### Task 3.10: Create useCopyToClipboard Composable
591
602
 
592
603
  **Files:**
604
+
593
605
  - Create: `src/composables/useCopyToClipboard.js`
594
606
 
595
607
  **Step 1: Create composable**
596
608
 
597
609
  ```javascript
598
- import { useUIStore } from '@/stores/ui'
610
+ import { useUIStore } from "@/stores/ui";
599
611
 
600
612
  /**
601
613
  * useCopyToClipboard - Composable for copying text with user feedback
@@ -603,22 +615,23 @@ import { useUIStore } from '@/stores/ui'
603
615
  * @returns {Object} Copy function with success notification
604
616
  */
605
617
  export function useCopyToClipboard() {
606
- const ui = useUIStore()
607
-
608
- const copy = (text, message = 'Copied to clipboard') => {
609
- if (!text) return
610
-
611
- navigator.clipboard.writeText(text)
612
- .then(() => {
613
- ui.showSuccess(message)
614
- })
615
- .catch((err) => {
616
- ui.showError('Failed to copy')
617
- console.error('Copy failed:', err)
618
- })
619
- }
620
-
621
- return { copy }
618
+ const ui = useUIStore();
619
+
620
+ const copy = (text, message = "Copied to clipboard") => {
621
+ if (!text) return;
622
+
623
+ navigator.clipboard
624
+ .writeText(text)
625
+ .then(() => {
626
+ ui.showSuccess(message);
627
+ })
628
+ .catch((err) => {
629
+ ui.showError("Failed to copy");
630
+ console.error("Copy failed:", err);
631
+ });
632
+ };
633
+
634
+ return { copy };
622
635
  }
623
636
  ```
624
637
 
@@ -638,14 +651,15 @@ git commit -m "feat: create useCopyToClipboard composable
638
651
  ### Task 3.11: Use useCopyToClipboard in Task.vue
639
652
 
640
653
  **Files:**
654
+
641
655
  - Modify: `src/components/Tasks/Task.vue`
642
656
 
643
657
  **Step 1: Import and use composable**
644
658
 
645
659
  ```javascript
646
- import { useCopyToClipboard } from '@/composables/useCopyToClipboard'
660
+ import { useCopyToClipboard } from "@/composables/useCopyToClipboard";
647
661
 
648
- const { copy } = useCopyToClipboard()
662
+ const { copy } = useCopyToClipboard();
649
663
  ```
650
664
 
651
665
  **Step 2: Replace manual copy logic**
@@ -653,7 +667,7 @@ const { copy } = useCopyToClipboard()
653
667
  Replace `navigator.clipboard.writeText()` calls with:
654
668
 
655
669
  ```javascript
656
- copy(task.id, 'Copied task ID')
670
+ copy(task.id, "Copied task ID");
657
671
  ```
658
672
 
659
673
  **Step 3: Remove old copy code**
@@ -674,6 +688,7 @@ git commit -m "refactor: use useCopyToClipboard composable in Task.vue"
674
688
  ### Task 3.12: Use useCopyToClipboard in ViewTask.vue
675
689
 
676
690
  **Files:**
691
+
677
692
  - Modify: `src/components/Tasks/ViewTask.vue`
678
693
 
679
694
  **Step 1-5:** Same as Task 3.11
@@ -690,6 +705,7 @@ git commit -m "refactor: use useCopyToClipboard composable in ViewTask.vue"
690
705
  ### Task 3.13: Use useCopyToClipboard in Account.vue
691
706
 
692
707
  **Files:**
708
+
693
709
  - Modify: `src/components/Editors/Account/Account.vue`
694
710
 
695
711
  **Step 1-5:** Same as Task 3.11
@@ -708,6 +724,7 @@ git commit -m "refactor: use useCopyToClipboard composable in Account.vue"
708
724
  ### Task 4.1: Clean Up App.vue Global Styles
709
725
 
710
726
  **Files:**
727
+
711
728
  - Modify: `src/App.vue`
712
729
 
713
730
  **Step 1: Read current App.vue styles**
@@ -717,10 +734,11 @@ Run: Read `src/App.vue` focusing on `<style>` section
717
734
  **Step 2: Remove global !important overrides**
718
735
 
719
736
  Find and remove/replace:
737
+
720
738
  - `html, body` with !important on overflow, width, height, touch-action (lines ~679-688)
721
- - Replace with proper overflow utilities on specific elements
739
+ - Replace with proper overflow utilities on specific elements
722
740
  - Global `* { touch-action: manipulation !important }` (lines ~699-702)
723
- - Remove entirely, use `touch-manipulation` class where needed
741
+ - Remove entirely, use `touch-manipulation` class where needed
724
742
 
725
743
  **Step 3: Convert .layout to Tailwind**
726
744
 
@@ -728,15 +746,15 @@ Replace:
728
746
 
729
747
  ```css
730
748
  .layout {
731
- min-height: 90vh;
732
- height: 100vh !important;
749
+ min-height: 90vh;
750
+ height: 100vh !important;
733
751
  }
734
752
  ```
735
753
 
736
754
  With template classes:
737
755
 
738
756
  ```vue
739
- <div class="layout min-h-screen h-screen">
757
+ <div class="layout h-screen min-h-screen"></div>
740
758
  ```
741
759
 
742
760
  Remove CSS block.
@@ -747,14 +765,14 @@ Replace:
747
765
 
748
766
  ```css
749
767
  .component-container {
750
- padding-left: 1rem;
751
- padding-right: 1rem;
752
- }
753
- @media (min-width: 480px) {
754
- .component-container {
755
768
  padding-left: 1rem;
756
769
  padding-right: 1rem;
757
- }
770
+ }
771
+ @media (min-width: 480px) {
772
+ .component-container {
773
+ padding-left: 1rem;
774
+ padding-right: 1rem;
775
+ }
758
776
  }
759
777
  /* etc */
760
778
  ```
@@ -762,7 +780,7 @@ Replace:
762
780
  With template classes:
763
781
 
764
782
  ```vue
765
- <div class="component-container px-4 xs:px-4 md:px-2 lg:px-6 xl:px-10">
783
+ <div class="component-container px-4 xs:px-4 md:px-2 lg:px-6 xl:px-10"></div>
766
784
  ```
767
785
 
768
786
  Remove CSS block.
@@ -795,6 +813,7 @@ git commit -m "refactor: clean up App.vue global styles
795
813
  ### Task 4.2: Clean Up Navbar.vue
796
814
 
797
815
  **Files:**
816
+
798
817
  - Modify: `src/components/ui/Navbar.vue`
799
818
 
800
819
  **Step 1: Read Navbar.vue styles**
@@ -822,15 +841,15 @@ Replace:
822
841
 
823
842
  ```css
824
843
  svg {
825
- width: 20px !important;
826
- height: 20px !important;
844
+ width: 20px !important;
845
+ height: 20px !important;
827
846
  }
828
847
  ```
829
848
 
830
849
  With template classes on SVG components:
831
850
 
832
851
  ```vue
833
- <SomeIcon class="w-5 h-5" />
852
+ <SomeIcon class="h-5 w-5" />
834
853
  ```
835
854
 
836
855
  **Step 4: Convert .navbar-link height**
@@ -839,8 +858,8 @@ Replace:
839
858
 
840
859
  ```css
841
860
  .navbar-link {
842
- height: 40px;
843
- border-bottom: 2px solid transparent;
861
+ height: 40px;
862
+ border-bottom: 2px solid transparent;
844
863
  }
845
864
  ```
846
865
 
@@ -873,7 +892,7 @@ Replace:
873
892
 
874
893
  ```css
875
894
  .force-z {
876
- z-index: 20000;
895
+ z-index: 20000;
877
896
  }
878
897
  ```
879
898
 
@@ -915,6 +934,7 @@ git commit -m "refactor: clean up Navbar.vue styles
915
934
  ### Task 4.3: Clean Up Modal.vue
916
935
 
917
936
  **Files:**
937
+
918
938
  - Modify: `src/components/ui/Modal.vue`
919
939
 
920
940
  **Step 1: Read Modal.vue styles**
@@ -927,23 +947,23 @@ Replace:
927
947
 
928
948
  ```css
929
949
  .modal-mask {
930
- position: fixed;
931
- z-index: 25000;
932
- top: 0;
933
- left: 0;
934
- width: 100%;
935
- height: 100%;
936
- background-color: rgba(17, 17, 17, 0.85);
937
- backdrop-filter: blur(4px);
938
- display: flex;
939
- padding-top: 3.5rem;
950
+ position: fixed;
951
+ z-index: 25000;
952
+ top: 0;
953
+ left: 0;
954
+ width: 100%;
955
+ height: 100%;
956
+ background-color: rgba(17, 17, 17, 0.85);
957
+ backdrop-filter: blur(4px);
958
+ display: flex;
959
+ padding-top: 3.5rem;
940
960
  }
941
961
  ```
942
962
 
943
963
  With template classes:
944
964
 
945
965
  ```vue
946
- <div class="modal-mask fixed inset-0 z-modal bg-overlay-dark backdrop-blur-xs flex pt-14">
966
+ <div class="modal-mask bg-overlay-dark backdrop-blur-xs fixed inset-0 z-modal flex pt-14"></div>
947
967
  ```
948
968
 
949
969
  **Step 3: Simplify .component-modal bottom margin**
@@ -953,7 +973,7 @@ Replace:
953
973
  ```css
954
974
  margin-bottom: 20rem;
955
975
  @media (max-width: 480px) {
956
- margin-bottom: 25rem;
976
+ margin-bottom: 25rem;
957
977
  }
958
978
  ```
959
979
 
@@ -981,6 +1001,7 @@ class="pb-60 md:pb-12"
981
1001
  **Step 5: Test modal**
982
1002
 
983
1003
  Open any modal, test:
1004
+
984
1005
  - Overlay appearance
985
1006
  - Modal positioning
986
1007
  - Scroll behavior
@@ -1005,6 +1026,7 @@ git commit -m "refactor: clean up Modal.vue styles
1005
1026
  ### Task 4.4: Clean Up Task.vue
1006
1027
 
1007
1028
  **Files:**
1029
+
1008
1030
  - Modify: `src/components/Tasks/Task.vue`
1009
1031
 
1010
1032
  **Step 1: Read Task.vue styles**
@@ -1017,7 +1039,7 @@ Replace:
1017
1039
 
1018
1040
  ```css
1019
1041
  min-width: 10px !important;
1020
- stroke: oklch(0.60 0 0) !important;
1042
+ stroke: oklch(0.6 0 0) !important;
1021
1043
  ```
1022
1044
 
1023
1045
  With proper component props or Tailwind classes:
@@ -1048,9 +1070,9 @@ Replace:
1048
1070
 
1049
1071
  ```css
1050
1072
  @media (max-width: 480px) {
1051
- left: 4rem !important;
1052
- top: 0.25rem !important;
1053
- z-index: 1 !important;
1073
+ left: 4rem !important;
1074
+ top: 0.25rem !important;
1075
+ z-index: 1 !important;
1054
1076
  }
1055
1077
  ```
1056
1078
 
@@ -1112,6 +1134,7 @@ git commit -m "refactor: clean up Task.vue styles
1112
1134
  ### Task 4.5: Clean Up Dropdown.vue
1113
1135
 
1114
1136
  **Files:**
1137
+
1115
1138
  - Modify: `src/components/ui/controls/atomic/Dropdown.vue`
1116
1139
 
1117
1140
  **Step 1: Read Dropdown.vue styles**
@@ -1201,109 +1224,97 @@ git commit -m "refactor: clean up Dropdown.vue styles
1201
1224
  ### Task 5.1: Create FormField Component
1202
1225
 
1203
1226
  **Files:**
1227
+
1204
1228
  - Create: `src/components/ui/FormField.vue`
1205
1229
 
1206
1230
  **Step 1: Create component**
1207
1231
 
1208
1232
  ```vue
1209
1233
  <script setup>
1210
- import { defineProps, defineEmits, useAttrs } from 'vue'
1211
- import UpIcon from '@/assets/icons/up.svg'
1212
- import DownIcon from '@/assets/icons/down.svg'
1234
+ import { defineEmits, useAttrs } from "vue";
1235
+ import UpIcon from "@/assets/icons/up.svg";
1236
+ import DownIcon from "@/assets/icons/down.svg";
1213
1237
 
1214
1238
  const props = defineProps({
1215
- label: {
1216
- type: String,
1217
- required: true
1218
- },
1219
- icon: {
1220
- type: Object,
1221
- default: null
1222
- },
1223
- modelValue: {
1224
- type: [String, Number],
1225
- default: ''
1226
- },
1227
- type: {
1228
- type: String,
1229
- default: 'text'
1230
- },
1231
- placeholder: {
1232
- type: String,
1233
- default: ''
1234
- },
1235
- required: {
1236
- type: Boolean,
1237
- default: false
1238
- },
1239
- hasError: {
1240
- type: Boolean,
1241
- default: false
1242
- },
1243
- incrementer: {
1244
- type: Boolean,
1245
- default: false
1246
- },
1247
- zIndex: {
1248
- type: String,
1249
- default: '0',
1250
- validator: (value) => ['dropdown', 'tooltip', '0', '1', '2'].includes(value)
1251
- }
1252
- })
1253
-
1254
- const emit = defineEmits(['update:modelValue', 'increment', 'decrement'])
1255
- const attrs = useAttrs()
1239
+ label: {
1240
+ type: String,
1241
+ required: true
1242
+ },
1243
+ icon: {
1244
+ type: Object,
1245
+ default: null
1246
+ },
1247
+ modelValue: {
1248
+ type: [String, Number],
1249
+ default: ""
1250
+ },
1251
+ type: {
1252
+ type: String,
1253
+ default: "text"
1254
+ },
1255
+ placeholder: {
1256
+ type: String,
1257
+ default: ""
1258
+ },
1259
+ required: {
1260
+ type: Boolean,
1261
+ default: false
1262
+ },
1263
+ hasError: {
1264
+ type: Boolean,
1265
+ default: false
1266
+ },
1267
+ incrementer: {
1268
+ type: Boolean,
1269
+ default: false
1270
+ },
1271
+ zIndex: {
1272
+ type: String,
1273
+ default: "0",
1274
+ validator: (value) => ["dropdown", "tooltip", "0", "1", "2"].includes(value)
1275
+ }
1276
+ });
1277
+
1278
+ const emit = defineEmits(["update:modelValue", "increment", "decrement"]);
1279
+ const attrs = useAttrs();
1256
1280
 
1257
1281
  const zIndexClasses = {
1258
- dropdown: 'z-dropdown',
1259
- tooltip: 'z-tooltip',
1260
- '0': 'z-0',
1261
- '1': 'z-10',
1262
- '2': 'z-20'
1263
- }
1282
+ dropdown: "z-dropdown",
1283
+ tooltip: "z-tooltip",
1284
+ 0: "z-0",
1285
+ 1: "z-10",
1286
+ 2: "z-20"
1287
+ };
1264
1288
  </script>
1265
1289
 
1266
1290
  <template>
1267
- <div class="flex flex-col" :class="zIndexClasses[zIndex]">
1268
- <label class="mb-2 text-sm font-medium text-light-400 flex items-center gap-2">
1269
- {{ label }}
1270
- <component :is="icon" v-if="icon" class="w-4 h-4" />
1271
- </label>
1272
- <div
1273
- class="relative flex items-center bg-dark-500 border rounded-md transition-colors"
1274
- :class="[
1275
- hasError ? 'border-error-500' : 'border-dark-600',
1276
- required ? 'ring-2 ring-primary/20' : ''
1277
- ]"
1278
- >
1279
- <slot>
1280
- <input
1281
- :type="type"
1282
- :placeholder="placeholder"
1283
- :value="modelValue"
1284
- @input="emit('update:modelValue', $event.target.value)"
1285
- v-bind="attrs"
1286
- class="w-full px-3 py-2 bg-transparent text-light-300 outline-none"
1287
- />
1288
- </slot>
1289
- <div v-if="incrementer" class="flex flex-col border-l border-dark-600">
1290
- <button
1291
- @click="emit('increment')"
1292
- type="button"
1293
- class="px-2 py-1 hover:bg-dark-650 transition-colors"
1294
- >
1295
- <UpIcon class="w-3 h-3 text-light-400" />
1296
- </button>
1297
- <button
1298
- @click="emit('decrement')"
1299
- type="button"
1300
- class="px-2 py-1 hover:bg-dark-650 transition-colors"
1301
- >
1302
- <DownIcon class="w-3 h-3 text-light-400" />
1303
- </button>
1304
- </div>
1291
+ <div class="flex flex-col" :class="zIndexClasses[zIndex]">
1292
+ <label class="mb-2 flex items-center gap-2 text-sm font-medium text-light-400">
1293
+ {{ label }}
1294
+ <component :is="icon" v-if="icon" class="h-4 w-4" />
1295
+ </label>
1296
+ <div
1297
+ class="relative flex items-center rounded-md border bg-dark-500 transition-colors"
1298
+ :class="[hasError ? 'border-error-500' : 'border-dark-600', required ? 'ring-primary/20 ring-2' : '']">
1299
+ <slot>
1300
+ <input
1301
+ :type="type"
1302
+ :placeholder="placeholder"
1303
+ :value="modelValue"
1304
+ @input="emit('update:modelValue', $event.target.value)"
1305
+ v-bind="attrs"
1306
+ class="w-full bg-transparent px-3 py-2 text-light-300 outline-none" />
1307
+ </slot>
1308
+ <div v-if="incrementer" class="flex flex-col border-l border-dark-600">
1309
+ <button @click="emit('increment')" type="button" class="px-2 py-1 transition-colors hover:bg-dark-650">
1310
+ <UpIcon class="h-3 w-3 text-light-400" />
1311
+ </button>
1312
+ <button @click="emit('decrement')" type="button" class="px-2 py-1 transition-colors hover:bg-dark-650">
1313
+ <DownIcon class="h-3 w-3 text-light-400" />
1314
+ </button>
1315
+ </div>
1316
+ </div>
1305
1317
  </div>
1306
- </div>
1307
1318
  </template>
1308
1319
  ```
1309
1320
 
@@ -1324,12 +1335,13 @@ git commit -m "feat: create FormField component
1324
1335
  ### Task 5.2: Replace FormField in CreateTaskAXS.vue
1325
1336
 
1326
1337
  **Files:**
1338
+
1327
1339
  - Modify: `src/components/Tasks/CreateTaskAXS.vue`
1328
1340
 
1329
1341
  **Step 1: Import FormField**
1330
1342
 
1331
1343
  ```javascript
1332
- import FormField from '@/components/ui/FormField.vue'
1344
+ import FormField from "@/components/ui/FormField.vue";
1333
1345
  ```
1334
1346
 
1335
1347
  **Step 2: Replace input wrapper markup**
@@ -1351,12 +1363,7 @@ Find all instances of:
1351
1363
  Replace with:
1352
1364
 
1353
1365
  ```vue
1354
- <FormField
1355
- label="Name"
1356
- :icon="NameIcon"
1357
- v-model="name"
1358
- type="text"
1359
- />
1366
+ <FormField label="Name" :icon="NameIcon" v-model="name" type="text" />
1360
1367
  ```
1361
1368
 
1362
1369
  **Step 3: Remove old input-wrapper styles**
@@ -1380,6 +1387,7 @@ git commit -m "refactor: use FormField component in CreateTaskAXS.vue
1380
1387
  ### Task 5.3: Replace FormField in CreateTaskTM.vue
1381
1388
 
1382
1389
  **Files:**
1390
+
1383
1391
  - Modify: `src/components/Tasks/CreateTaskTM.vue`
1384
1392
 
1385
1393
  **Step 1-5:** Same as Task 5.2
@@ -1396,6 +1404,7 @@ git commit -m "refactor: use FormField component in CreateTaskTM.vue"
1396
1404
  ### Task 5.4: Replace FormField in CreateAccount.vue
1397
1405
 
1398
1406
  **Files:**
1407
+
1399
1408
  - Modify: `src/components/Editors/Account/CreateAccount.vue`
1400
1409
 
1401
1410
  **Step 1-5:** Same as Task 5.2
@@ -1412,6 +1421,7 @@ git commit -m "refactor: use FormField component in CreateAccount.vue"
1412
1421
  ### Task 5.5: Replace FormField in CreateProfile.vue
1413
1422
 
1414
1423
  **Files:**
1424
+
1415
1425
  - Modify: `src/components/Editors/Profile/CreateProfile.vue`
1416
1426
 
1417
1427
  **Step 1-5:** Same as Task 5.2
@@ -1428,71 +1438,63 @@ git commit -m "refactor: use FormField component in CreateProfile.vue"
1428
1438
  ### Task 5.6: Create InfoRow Component
1429
1439
 
1430
1440
  **Files:**
1441
+
1431
1442
  - Create: `src/components/ui/InfoRow.vue`
1432
1443
 
1433
1444
  **Step 1: Create component**
1434
1445
 
1435
1446
  ```vue
1436
1447
  <script setup>
1437
- import { defineProps } from 'vue'
1438
- import { useCopyToClipboard } from '@/composables/useCopyToClipboard'
1448
+ import { useCopyToClipboard } from "@/composables/useCopyToClipboard";
1439
1449
 
1440
1450
  const props = defineProps({
1441
- icon: {
1442
- type: Object,
1443
- default: null
1444
- },
1445
- label: {
1446
- type: String,
1447
- required: true
1448
- },
1449
- value: {
1450
- type: [String, Number],
1451
- default: ''
1452
- },
1453
- valueClass: {
1454
- type: String,
1455
- default: ''
1456
- },
1457
- copyable: {
1458
- type: Boolean,
1459
- default: false
1460
- },
1461
- copyText: {
1462
- type: String,
1463
- default: ''
1464
- }
1465
- })
1466
-
1467
- const { copy } = useCopyToClipboard()
1451
+ icon: {
1452
+ type: Object,
1453
+ default: null
1454
+ },
1455
+ label: {
1456
+ type: String,
1457
+ required: true
1458
+ },
1459
+ value: {
1460
+ type: [String, Number],
1461
+ default: ""
1462
+ },
1463
+ valueClass: {
1464
+ type: String,
1465
+ default: ""
1466
+ },
1467
+ copyable: {
1468
+ type: Boolean,
1469
+ default: false
1470
+ },
1471
+ copyText: {
1472
+ type: String,
1473
+ default: ""
1474
+ }
1475
+ });
1476
+
1477
+ const { copy } = useCopyToClipboard();
1468
1478
 
1469
1479
  const handleCopy = () => {
1470
- if (props.copyable) {
1471
- copy(props.copyText || props.value, 'Copied')
1472
- }
1473
- }
1480
+ if (props.copyable) {
1481
+ copy(props.copyText || props.value, "Copied");
1482
+ }
1483
+ };
1474
1484
  </script>
1475
1485
 
1476
1486
  <template>
1477
- <div
1478
- class="flex items-center gap-3 py-2 px-3 rounded-md hover:bg-dark-400/50 transition-colors"
1479
- :class="{ 'cursor-pointer': copyable }"
1480
- @click="handleCopy"
1481
- >
1482
- <component
1483
- :is="icon"
1484
- v-if="icon"
1485
- class="w-5 h-5 text-light-500 flex-shrink-0"
1486
- />
1487
- <span class="text-sm text-light-500 min-w-[100px]">{{ label }}</span>
1488
- <span
1489
- class="text-sm text-light-300 flex-1 text-right"
1490
- :class="valueClass"
1491
- >
1492
- <slot>{{ value }}</slot>
1493
- </span>
1494
- <slot name="actions" />
1495
- </div>
1487
+ <div
1488
+ class="flex items-center gap-3 rounded-md px-3 py-2 transition-colors hover:bg-dark-400/50"
1489
+ :class="{ 'cursor-pointer': copyable }"
1490
+ @click="handleCopy">
1491
+ <component :is="icon" v-if="icon" class="h-5 w-5 flex-shrink-0 text-light-500" />
1492
+ <span class="min-w-[100px] text-sm text-light-500">{{ label }}</span>
1493
+ <span class="flex-1 text-right text-sm text-light-300" :class="valueClass">
1494
+ <slot>{{ value }}</slot>
1495
+ </span>
1496
+ <slot name="actions" />
1497
+ </div>
1496
1498
  </template>
1497
1499
  ```
1498
1500
 
@@ -1514,12 +1516,13 @@ git commit -m "feat: create InfoRow component
1514
1516
  ### Task 5.7: Replace InfoRow in ViewTask.vue
1515
1517
 
1516
1518
  **Files:**
1519
+
1517
1520
  - Modify: `src/components/Tasks/ViewTask.vue`
1518
1521
 
1519
1522
  **Step 1: Import InfoRow**
1520
1523
 
1521
1524
  ```javascript
1522
- import InfoRow from '@/components/ui/InfoRow.vue'
1525
+ import InfoRow from "@/components/ui/InfoRow.vue";
1523
1526
  ```
1524
1527
 
1525
1528
  **Step 2: Replace info row markup**
@@ -1537,13 +1540,7 @@ Find instances like:
1537
1540
  Replace with:
1538
1541
 
1539
1542
  ```vue
1540
- <InfoRow
1541
- :icon="IdIcon"
1542
- label="ID"
1543
- :value="task.id"
1544
- copyable
1545
- :copy-text="task.id"
1546
- />
1543
+ <InfoRow :icon="IdIcon" label="ID" :value="task.id" copyable :copy-text="task.id" />
1547
1544
  ```
1548
1545
 
1549
1546
  **Step 3: Test**
@@ -1566,32 +1563,28 @@ git commit -m "refactor: use InfoRow component in ViewTask.vue
1566
1563
  ### Task 5.8: Create SectionCard Component
1567
1564
 
1568
1565
  **Files:**
1566
+
1569
1567
  - Create: `src/components/ui/SectionCard.vue`
1570
1568
 
1571
1569
  **Step 1: Create component**
1572
1570
 
1573
1571
  ```vue
1574
1572
  <script setup>
1575
- import { defineProps } from 'vue'
1576
-
1577
1573
  const props = defineProps({
1578
- title: {
1579
- type: String,
1580
- default: ''
1581
- }
1582
- })
1574
+ title: {
1575
+ type: String,
1576
+ default: ""
1577
+ }
1578
+ });
1583
1579
  </script>
1584
1580
 
1585
1581
  <template>
1586
- <div class="bg-dark-400 rounded-lg p-4 border border-dark-600">
1587
- <h3
1588
- v-if="title"
1589
- class="text-lg font-semibold text-light-300 mb-4 pb-2 border-b border-dark-600"
1590
- >
1591
- {{ title }}
1592
- </h3>
1593
- <slot />
1594
- </div>
1582
+ <div class="rounded-lg border border-dark-600 bg-dark-400 p-4">
1583
+ <h3 v-if="title" class="mb-4 border-b border-dark-600 pb-2 text-lg font-semibold text-light-300">
1584
+ {{ title }}
1585
+ </h3>
1586
+ <slot />
1587
+ </div>
1595
1588
  </template>
1596
1589
  ```
1597
1590
 
@@ -1611,6 +1604,7 @@ git commit -m "feat: create SectionCard component
1611
1604
  ### Task 5.9: Use SectionCard in ViewTask.vue
1612
1605
 
1613
1606
  **Files:**
1607
+
1614
1608
  - Modify: `src/components/Tasks/ViewTask.vue`
1615
1609
 
1616
1610
  **Step 1: Import SectionCard**
@@ -1650,15 +1644,16 @@ git commit -m "refactor: use SectionCard component in ViewTask.vue"
1650
1644
  ### Task 5.10: Create ActionButtonGroup Component
1651
1645
 
1652
1646
  **Files:**
1647
+
1653
1648
  - Create: `src/components/ui/ActionButtonGroup.vue`
1654
1649
 
1655
1650
  **Step 1: Create component**
1656
1651
 
1657
1652
  ```vue
1658
1653
  <template>
1659
- <ul class="flex items-center gap-1 mobile-portrait:gap-0.5">
1660
- <slot />
1661
- </ul>
1654
+ <ul class="flex items-center gap-1 mobile-portrait:gap-0.5">
1655
+ <slot />
1656
+ </ul>
1662
1657
  </template>
1663
1658
 
1664
1659
  <style scoped>
@@ -1682,6 +1677,7 @@ git commit -m "feat: create ActionButtonGroup component
1682
1677
  ### Task 5.11: Use ActionButtonGroup in Task.vue
1683
1678
 
1684
1679
  **Files:**
1680
+
1685
1681
  - Modify: `src/components/Tasks/Task.vue`
1686
1682
 
1687
1683
  **Step 1: Import ActionButtonGroup**
@@ -1725,6 +1721,7 @@ git commit -m "refactor: use ActionButtonGroup in Task.vue
1725
1721
  ### Task 5.12: Use ActionButtonGroup in Account.vue
1726
1722
 
1727
1723
  **Files:**
1724
+
1728
1725
  - Modify: `src/components/Editors/Account/Account.vue`
1729
1726
 
1730
1727
  **Step 1-5:** Same as Task 5.11
@@ -1741,6 +1738,7 @@ git commit -m "refactor: use ActionButtonGroup in Account.vue"
1741
1738
  ### Task 5.13: Use ActionButtonGroup in Profile.vue
1742
1739
 
1743
1740
  **Files:**
1741
+
1744
1742
  - Modify: `src/components/Editors/Profile/Profile.vue`
1745
1743
 
1746
1744
  **Step 1-5:** Same as Task 5.11
@@ -1759,6 +1757,7 @@ git commit -m "refactor: use ActionButtonGroup in Profile.vue"
1759
1757
  ### Task 6.1: Replace Hardcoded Gray Colors
1760
1758
 
1761
1759
  **Files:**
1760
+
1762
1761
  - Modify: `src/components/Editors/Account/AccountView.vue`
1763
1762
  - Modify: `src/components/Editors/Profile/ProfileView.vue`
1764
1763
  - Modify: `src/components/Tasks/TaskView.vue`
@@ -1792,6 +1791,7 @@ git commit -m "refactor: replace hardcoded gray text colors with theme tokens
1792
1791
  ### Task 6.2: Replace rgba Gray Backgrounds in Filter.vue
1793
1792
 
1794
1793
  **Files:**
1794
+
1795
1795
  - Modify: `src/components/Filter/Filter.vue`
1796
1796
 
1797
1797
  **Step 1: Replace rgba(61, 62, 68, X)**
@@ -1836,6 +1836,7 @@ git commit -m "refactor: replace rgba gray backgrounds with dark scale tokens
1836
1836
  ### Task 6.3: Replace Error Color Variations
1837
1837
 
1838
1838
  **Files:**
1839
+
1839
1840
  - Modify: `src/components/Filter/Filter.vue`
1840
1841
  - Modify: `src/components/Editors/Profile/CreateProfile.vue`
1841
1842
  - Modify: `src/components/Editors/Account/CreateAccount.vue`
@@ -1870,6 +1871,7 @@ git commit -m "refactor: standardize error colors
1870
1871
  ### Task 6.4: Replace Modal Overlay Color
1871
1872
 
1872
1873
  **Files:**
1874
+
1873
1875
  - Modify: `src/components/ui/Modal.vue` (if not done in Task 4.3)
1874
1876
 
1875
1877
  **Step 1: Replace rgba(17, 17, 17, 0.85)**
@@ -1893,6 +1895,7 @@ git commit -m "refactor: use overlay-dark token for modal background"
1893
1895
  ### Task 6.5: Replace Accent Color Variations in ReconnectIndicator
1894
1896
 
1895
1897
  **Files:**
1898
+
1896
1899
  - Modify: `src/components/ui/ReconnectIndicator.vue`
1897
1900
 
1898
1901
  **Step 1: Replace rgba(136, 201, 153, X)**
@@ -1929,6 +1932,7 @@ git commit -m "refactor: use accent-green token for reconnect indicator
1929
1932
  ### Task 7.1: Clean Up CountryChooser.vue
1930
1933
 
1931
1934
  **Files:**
1935
+
1932
1936
  - Modify: `src/components/ui/controls/CountryChooser.vue`
1933
1937
 
1934
1938
  **Step 1: Replace circular button hack**
@@ -1988,6 +1992,7 @@ git commit -m "refactor: clean up CountryChooser.vue
1988
1992
  ### Task 7.2: Clean Up Table.vue
1989
1993
 
1990
1994
  **Files:**
1995
+
1991
1996
  - Modify: `src/components/Table/Table.vue`
1992
1997
 
1993
1998
  **Step 1: Remove scroll !important**
@@ -2016,8 +2021,8 @@ Remove:
2016
2021
 
2017
2022
  ```css
2018
2023
  @media (orientation: landscape) {
2019
- max-height: calc(100vh - 160px) !important;
2020
- margin-bottom: 2rem !important;
2024
+ max-height: calc(100vh - 160px) !important;
2025
+ margin-bottom: 2rem !important;
2021
2026
  }
2022
2027
  ```
2023
2028
 
@@ -2044,6 +2049,7 @@ git commit -m "refactor: clean up Table.vue
2044
2049
  ### Task 7.3: Clean Up Console.vue
2045
2050
 
2046
2051
  **Files:**
2052
+
2047
2053
  - Modify: `src/views/Console.vue`
2048
2054
 
2049
2055
  **Step 1: Optimize responsive padding**
@@ -2053,7 +2059,7 @@ Replace:
2053
2059
  ```css
2054
2060
  padding-bottom: 4rem;
2055
2061
  @media (max-width: 480px) {
2056
- padding-bottom: 6rem;
2062
+ padding-bottom: 6rem;
2057
2063
  }
2058
2064
  ```
2059
2065
 
@@ -2081,6 +2087,7 @@ git commit -m "refactor: clean up Console.vue responsive padding"
2081
2087
  ### Task 7.4: Clean Up Tasks.vue
2082
2088
 
2083
2089
  **Files:**
2090
+
2084
2091
  - Modify: `src/views/Tasks.vue`
2085
2092
 
2086
2093
  **Step 1: Remove PWA padding hack**
@@ -2089,7 +2096,7 @@ Find:
2089
2096
 
2090
2097
  ```css
2091
2098
  @media (display-mode: standalone) {
2092
- padding-bottom: X !important;
2099
+ padding-bottom: X !important;
2093
2100
  }
2094
2101
  ```
2095
2102
 
@@ -2113,6 +2120,7 @@ git commit -m "refactor: clean up Tasks.vue PWA hacks"
2113
2120
  ### Task 7.5: Clean Up Switch.vue
2114
2121
 
2115
2122
  **Files:**
2123
+
2116
2124
  - Modify: `src/components/ui/controls/atomic/Switch.vue`
2117
2125
 
2118
2126
  **Step 1: Convert hardcoded px to Tailwind**
@@ -2135,6 +2143,7 @@ git commit -m "refactor: optimize Switch.vue with Tailwind where applicable"
2135
2143
  ### Task 7.6: Clean Up Splash.vue
2136
2144
 
2137
2145
  **Files:**
2146
+
2138
2147
  - Modify: `src/components/ui/Splash.vue`
2139
2148
 
2140
2149
  **Step 1: Replace background-color**
@@ -2160,6 +2169,7 @@ git commit -m "refactor: use theme color in Splash.vue"
2160
2169
  ### Task 8.1: Run Automated Verification Plan
2161
2170
 
2162
2171
  **Files:**
2172
+
2163
2173
  - Reference: `/Users/luca/Documents/GitHub/Necro/Dashboard/VERIFICATION_PLAN.md`
2164
2174
 
2165
2175
  **Step 1: Start both dev servers**
@@ -2170,6 +2180,7 @@ Expected: Servers on 5173 and 8081
2170
2180
  **Step 2: Manual quick check**
2171
2181
 
2172
2182
  Test critical paths:
2183
+
2173
2184
  - Login flow
2174
2185
  - Navigate to each route
2175
2186
  - Open/close modals
@@ -2180,6 +2191,7 @@ Test critical paths:
2180
2191
  **Step 3: Responsive testing**
2181
2192
 
2182
2193
  Test at breakpoints:
2194
+
2183
2195
  - Mobile portrait (375px)
2184
2196
  - iPad Pro (1024px)
2185
2197
  - Desktop (1920px)
@@ -2207,6 +2219,7 @@ git commit -m "docs: verification results for Tailwind consolidation"
2207
2219
  ### Task 8.2: Count Remaining CSS Lines
2208
2220
 
2209
2221
  **Files:**
2222
+
2210
2223
  - All Vue files
2211
2224
 
2212
2225
  **Step 1: Count <style> blocks**
@@ -2220,10 +2233,12 @@ Run: `grep -r "!important" src/components src/views | wc -l`
2220
2233
  **Step 3: Compare with baseline**
2221
2234
 
2222
2235
  Baseline:
2236
+
2223
2237
  - 53 files with `<style>` blocks
2224
2238
  - 378 `!important` declarations
2225
2239
 
2226
2240
  Target:
2241
+
2227
2242
  - < 20 files with `<style>` blocks (animations only)
2228
2243
  - < 50 `!important` declarations
2229
2244
 
@@ -2236,6 +2251,7 @@ Create summary in docs/plans/2026-02-08-tailwind-consolidation-results.md
2236
2251
  ### Task 8.3: Create Final Summary Report
2237
2252
 
2238
2253
  **Files:**
2254
+
2239
2255
  - Create: `docs/plans/2026-02-08-tailwind-consolidation-results.md`
2240
2256
 
2241
2257
  **Step 1: Document changes**
@@ -2246,12 +2262,14 @@ Create summary in docs/plans/2026-02-08-tailwind-consolidation-results.md
2246
2262
  ## Metrics
2247
2263
 
2248
2264
  **Before:**
2265
+
2249
2266
  - Files with <style> blocks: 53
2250
2267
  - !important declarations: 378
2251
2268
  - Lines of CSS: ~2000
2252
2269
  - Duplicate components: 7 patterns identified
2253
2270
 
2254
2271
  **After:**
2272
+
2255
2273
  - Files with <style> blocks: X
2256
2274
  - !important declarations: X
2257
2275
  - Lines of CSS: ~X
@@ -2275,7 +2293,7 @@ Create summary in docs/plans/2026-02-08-tailwind-consolidation-results.md
2275
2293
  - Dark scale extensions: 350, 450, 475, 625, 675
2276
2294
  - Error colors: 300, 400, 500
2277
2295
  - Overlay colors: dark, darker
2278
- - Semantic tokens: text-*, bg-*, border-focus, primary
2296
+ - Semantic tokens: text-_, bg-_, border-focus, primary
2279
2297
  - Shadow system: 7 new shadows
2280
2298
  - Font sizes: xxs, xxxs
2281
2299
 
@@ -2310,6 +2328,7 @@ git commit -m "docs: Tailwind consolidation completion report"
2310
2328
  ### Task 9.1: Update README (if exists)
2311
2329
 
2312
2330
  **Files:**
2331
+
2313
2332
  - Modify: `README.md` (if exists)
2314
2333
 
2315
2334
  **Step 1: Document new components**
@@ -2393,6 +2412,7 @@ All functionality verified, no regressions."
2393
2412
  **Estimated time:** 8-12 hours (depending on file complexity)
2394
2413
 
2395
2414
  **Recommended approach:**
2415
+
2396
2416
  1. Execute phases sequentially
2397
2417
  2. Test after each phase before moving to next
2398
2418
  3. Commit frequently (after each task)
@@ -2400,12 +2420,14 @@ All functionality verified, no regressions."
2400
2420
 
2401
2421
  **Rollback strategy:**
2402
2422
  If any phase causes issues, rollback to previous phase commit:
2423
+
2403
2424
  ```bash
2404
2425
  git log --oneline
2405
2426
  git reset --hard <commit-hash>
2406
2427
  ```
2407
2428
 
2408
2429
  **Testing checklist per phase:**
2430
+
2409
2431
  - [ ] Phase 1: Dev server starts, no config errors
2410
2432
  - [ ] Phase 2: App loads without landscape lock
2411
2433
  - [ ] Phase 3: Components render correctly