youssefreda9 commited on
Commit
078df28
·
1 Parent(s): 0475556

chore: revert frontend UI changes to 7aa0d90 to fix layout blowout

Browse files
src/css/base.css CHANGED
@@ -12,7 +12,6 @@ html {
12
  }
13
 
14
  body {
15
- overflow-x: hidden;
16
  font-family: var(--font-family-primary);
17
  font-size: var(--font-size-body);
18
  font-weight: var(--font-weight-regular);
 
12
  }
13
 
14
  body {
 
15
  font-family: var(--font-family-primary);
16
  font-size: var(--font-size-body);
17
  font-weight: var(--font-weight-regular);
src/css/components.css CHANGED
@@ -299,11 +299,11 @@
299
  position: relative;
300
  }
301
 
302
- .editor-shell>*:first-child {
303
  border-radius: var(--radius-card) var(--radius-card) 0 0;
304
  }
305
 
306
- .editor-shell>*:last-child {
307
  border-radius: 0 0 var(--radius-card) var(--radius-card);
308
  }
309
 
@@ -317,11 +317,11 @@
317
  background: var(--color-surface);
318
  }
319
 
320
- .editor-toolbar>*:first-child {
321
  justify-self: start;
322
  }
323
 
324
- .editor-toolbar>*:last-child {
325
  justify-self: end;
326
  }
327
 
@@ -350,7 +350,7 @@
350
 
351
  .editor-tab:hover {
352
  color: var(--color-text-primary);
353
- background: rgba(255, 255, 255, 0.06);
354
  }
355
 
356
  .editor-tab.active {
@@ -365,13 +365,11 @@
365
  align-items: center;
366
  gap: 5px;
367
  }
368
-
369
  .tab-icon {
370
  flex-shrink: 0;
371
  opacity: 0.8;
372
  vertical-align: middle;
373
  }
374
-
375
  .editor-tab.active .tab-icon {
376
  opacity: 1;
377
  }
@@ -380,7 +378,6 @@
380
  [data-tooltip] {
381
  position: relative;
382
  }
383
-
384
  [data-tooltip]::after {
385
  content: attr(data-tooltip);
386
  position: absolute;
@@ -398,12 +395,11 @@
398
  opacity: 0;
399
  visibility: hidden;
400
  transition: all 0.2s ease;
401
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
402
  border: 1px solid var(--color-border);
403
  z-index: 300;
404
  font-family: inherit;
405
  }
406
-
407
  [data-tooltip]:hover::after {
408
  opacity: 1;
409
  visibility: visible;
@@ -413,21 +409,21 @@
413
  /* ── Formatting Toolbar ── */
414
  .format-toolbar {
415
  display: flex;
416
- flex-wrap: wrap;
417
  align-items: center;
418
  justify-content: center;
419
- gap: 6px 3px; /* vertical and horizontal gaps */
420
  padding: 6px 10px;
421
  border-bottom: 1px solid var(--color-border);
422
  background: var(--color-surface);
 
423
  position: relative;
424
- z-index: 40;
425
  flex-shrink: 0;
426
  }
427
 
428
  .fmt-group {
429
  display: flex;
430
- flex-wrap: nowrap;
431
  align-items: center;
432
  gap: 1px;
433
  background: var(--color-border);
@@ -562,7 +558,7 @@
562
  background: var(--color-surface);
563
  border: 1px solid var(--color-border);
564
  border-radius: 8px;
565
- box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
566
  padding: 4px;
567
  z-index: 200;
568
  opacity: 0;
@@ -649,15 +645,11 @@
649
  }
650
 
651
  @media (min-width: 768px) {
652
- .editor-surface {
653
- min-height: 60vh;
654
- }
655
  }
656
 
657
  @media (min-width: 1024px) {
658
- .editor-surface {
659
- min-height: 500px;
660
- }
661
  }
662
 
663
  .editor-surface:focus {
@@ -697,7 +689,7 @@
697
 
698
  .editor-stats {
699
  display: flex;
700
- flex-wrap: nowrap;
701
  gap: var(--spacing-md);
702
  align-items: center;
703
  }
@@ -709,24 +701,15 @@
709
  flex-shrink: 0;
710
  }
711
 
712
- .stat-dot--spelling {
713
- background: var(--color-error);
714
- }
715
-
716
- .stat-dot--grammar {
717
- background: var(--color-warning);
718
- }
719
-
720
- .stat-dot--punctuation {
721
- background: var(--color-success);
722
- }
723
 
724
  .editor-actions {
725
  display: flex;
726
- flex-wrap: nowrap;
727
  gap: var(--spacing-sm);
728
  }
729
-
730
  .editor-actions .btn-ghost,
731
  .editor-actions .doc-dropdown .btn-ghost {
732
  width: 40px;
@@ -736,7 +719,6 @@
736
  display: inline-flex;
737
  align-items: center;
738
  justify-content: center;
739
- flex-shrink: 0;
740
  }
741
 
742
  /* ── Buttons ── */
@@ -856,17 +838,9 @@
856
  gap: var(--spacing-sm);
857
  }
858
 
859
- .popover-type--spelling {
860
- color: var(--color-error);
861
- }
862
-
863
- .popover-type--grammar {
864
- color: var(--color-warning);
865
- }
866
-
867
- .popover-type--punctuation {
868
- color: var(--color-success);
869
- }
870
 
871
  .popover-original-word {
872
  font-size: var(--font-size-sm);
@@ -965,7 +939,6 @@
965
  cursor: pointer;
966
  transition: all var(--transition-fast);
967
  }
968
-
969
  .popover-dismiss:hover {
970
  color: var(--color-error);
971
  border-color: var(--color-error);
@@ -1048,15 +1021,8 @@
1048
  }
1049
 
1050
  @keyframes fadeIn {
1051
- from {
1052
- opacity: 0;
1053
- transform: translateY(4px);
1054
- }
1055
-
1056
- to {
1057
- opacity: 1;
1058
- transform: translateY(0);
1059
- }
1060
  }
1061
 
1062
 
@@ -1489,9 +1455,8 @@ input[type="range"]::-webkit-slider-thumb {
1489
  .editor-layout.tools-mode {
1490
  grid-template-columns: 1fr !important;
1491
  }
1492
-
1493
- .editor-layout.tools-mode>.docs-panel-desktop,
1494
- .editor-layout.tools-mode>.sidebar-panel {
1495
  display: none !important;
1496
  }
1497
 
@@ -1647,13 +1612,8 @@ input[type="range"]::-webkit-slider-thumb {
1647
  border: 1px solid var(--color-primary-subtle-border);
1648
  }
1649
 
1650
- .check-icon {
1651
- color: var(--color-success);
1652
- }
1653
-
1654
- .muted-icon {
1655
- color: var(--color-text-muted);
1656
- }
1657
 
1658
  .demo-editor-surface {
1659
  background: var(--color-editor);
@@ -2074,8 +2034,7 @@ input[type="range"]::-webkit-slider-thumb {
2074
  transform: translateX(100%);
2075
  transition: transform var(--transition-slow), box-shadow var(--transition-slow);
2076
  box-shadow: none;
2077
- padding-top: 64px;
2078
- /* below nav */
2079
  }
2080
 
2081
  .docs-sidebar.is-open {
@@ -2480,7 +2439,7 @@ input[type="range"]::-webkit-slider-thumb {
2480
  background: linear-gradient(135deg, var(--color-primary), var(--color-secondary));
2481
  cursor: pointer;
2482
  border: 3px solid var(--color-surface);
2483
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
2484
  transition: transform 0.15s ease;
2485
  }
2486
 
@@ -2495,7 +2454,7 @@ input[type="range"]::-webkit-slider-thumb {
2495
  background: linear-gradient(135deg, var(--color-primary), var(--color-secondary));
2496
  cursor: pointer;
2497
  border: 3px solid var(--color-surface);
2498
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
2499
  }
2500
 
2501
  /* ── Item 3: Empty States ── */
@@ -2685,7 +2644,6 @@ input[type="range"]::-webkit-slider-thumb {
2685
  font-weight: 700;
2686
  color: var(--color-text-muted);
2687
  }
2688
-
2689
  .fmt-color-swatch--reset:hover {
2690
  border-color: var(--color-error);
2691
  color: var(--color-error);
@@ -2900,36 +2858,17 @@ input[type="range"]::-moz-range-thumb {
2900
  animation: toast-out 0.25s ease forwards;
2901
  }
2902
 
2903
- .toast--success {
2904
- border-color: rgba(34, 197, 94, 0.4);
2905
- }
2906
-
2907
- .toast--error {
2908
- border-color: rgba(239, 68, 68, 0.4);
2909
- }
2910
 
2911
  @keyframes toast-in {
2912
- from {
2913
- opacity: 0;
2914
- transform: translateY(16px);
2915
- }
2916
-
2917
- to {
2918
- opacity: 1;
2919
- transform: translateY(0);
2920
- }
2921
  }
2922
 
2923
  @keyframes toast-out {
2924
- from {
2925
- opacity: 1;
2926
- transform: translateY(0);
2927
- }
2928
-
2929
- to {
2930
- opacity: 0;
2931
- transform: translateY(16px);
2932
- }
2933
  }
2934
 
2935
  /* ── Scroll to Top ── */
@@ -2968,7 +2907,7 @@ input[type="range"]::-moz-range-thumb {
2968
 
2969
  /* ── Loading Skeleton ── */
2970
  .skeleton {
2971
- background: linear-gradient(90deg, var(--color-border) 25%, rgba(255, 255, 255, 0.08) 50%, var(--color-border) 75%);
2972
  background-size: 200% 100%;
2973
  animation: skeleton-shimmer 1.5s ease infinite;
2974
  border-radius: 8px;
@@ -2985,13 +2924,8 @@ input[type="range"]::-moz-range-thumb {
2985
  }
2986
 
2987
  @keyframes skeleton-shimmer {
2988
- 0% {
2989
- background-position: 200% 0;
2990
- }
2991
-
2992
- 100% {
2993
- background-position: -200% 0;
2994
- }
2995
  }
2996
 
2997
  /* ── Word Count Goal ── */
@@ -3050,15 +2984,8 @@ input[type="range"]::-moz-range-thumb {
3050
  }
3051
 
3052
  @keyframes punc-blink {
3053
-
3054
- 0%,
3055
- 100% {
3056
- border-left-color: var(--highlight-punctuation-border);
3057
- }
3058
-
3059
- 50% {
3060
- border-left-color: transparent;
3061
- }
3062
  }
3063
 
3064
  /* ── Fix #6: Document title truncation ── */
@@ -3074,12 +3001,11 @@ input[type="range"]::-moz-range-thumb {
3074
  /* ── Fix #8: Editor placeholder alignment (Removed hack) ── */
3075
 
3076
  /* ── Fix #11: Pricing cards equal heights ── */
3077
- #page-pricing .grid>div {
3078
  display: flex;
3079
  flex-direction: column;
3080
  }
3081
-
3082
- #page-pricing .grid>div>ul {
3083
  flex: 1;
3084
  }
3085
 
@@ -3088,18 +3014,15 @@ input[type="range"]::-moz-range-thumb {
3088
  cursor: default;
3089
  transition: transform 0.3s ease, filter 0.3s ease, box-shadow 0.3s ease;
3090
  }
3091
-
3092
  .window-dots:hover .dot--red {
3093
  transform: scale(1.25);
3094
  box-shadow: 0 0 8px rgba(239, 68, 68, 0.5);
3095
  }
3096
-
3097
  .window-dots:hover .dot--yellow {
3098
  transform: scale(1.25);
3099
  box-shadow: 0 0 8px rgba(234, 179, 8, 0.5);
3100
  transition-delay: 0.05s;
3101
  }
3102
-
3103
  .window-dots:hover .dot--green {
3104
  transform: scale(1.25);
3105
  box-shadow: 0 0 8px rgba(34, 197, 94, 0.5);
@@ -3110,11 +3033,9 @@ input[type="range"]::-moz-range-thumb {
3110
  .sidebar-desktop.collapsed {
3111
  display: none !important;
3112
  }
3113
-
3114
  .editor-layout.editor-fullscreen {
3115
  grid-template-columns: 1fr !important;
3116
  }
3117
-
3118
  .editor-layout.editor-fullscreen .sidebar-panel.sidebar-desktop,
3119
  .editor-layout.editor-fullscreen .docs-panel,
3120
  .editor-layout.editor-fullscreen .docs-panel-desktop {
@@ -3126,47 +3047,38 @@ input[type="range"]::-moz-range-thumb {
3126
  color: #3A424E;
3127
  background: rgba(26, 29, 33, 0.04);
3128
  }
3129
-
3130
  [data-theme="light"] .fmt-btn:hover {
3131
  background: rgba(26, 29, 33, 0.1);
3132
  color: #1A1D21;
3133
  }
3134
-
3135
  [data-theme="light"] .fmt-btn.fmt-active {
3136
  background: rgba(43, 108, 184, 0.14);
3137
  color: #2B6CB8;
3138
  }
3139
-
3140
  [data-theme="light"] .format-toolbar {
3141
  background: #FAF9F6;
3142
  border-bottom-color: rgba(26, 29, 33, 0.12);
3143
  }
3144
-
3145
  [data-theme="light"] .surface-card {
3146
  box-shadow: 0 2px 8px rgba(26, 29, 33, 0.06);
3147
  border: 1px solid rgba(26, 29, 33, 0.08);
3148
  }
3149
-
3150
  [data-theme="light"] .editor-tab {
3151
  color: #5A6472;
3152
  }
3153
-
3154
  [data-theme="light"] .editor-tab:hover {
3155
  color: #1A1D21;
3156
  background: rgba(26, 29, 33, 0.06);
3157
  }
3158
-
3159
  [data-theme="light"] .editor-tab.active {
3160
  color: #fff !important;
3161
  background: linear-gradient(135deg, #4A8FD4, #7C6BC4);
3162
  box-shadow: 0 2px 8px rgba(74, 143, 212, 0.25);
3163
  }
3164
-
3165
  [data-theme="light"] .stat-item {
3166
  color: #3A424E;
3167
  opacity: 1;
3168
  }
3169
-
3170
  [data-theme="light"] .scroll-top-btn {
3171
  box-shadow: 0 4px 16px rgba(26, 29, 33, 0.15);
3172
  }
@@ -3197,7 +3109,7 @@ input[type="range"]::-moz-range-thumb {
3197
  #autocomplete-dropdown {
3198
  position: fixed;
3199
  background: var(--color-surface, #1a1d21);
3200
- border: 1px solid var(--color-border, rgba(255, 255, 255, 0.1));
3201
  border-radius: 10px;
3202
  box-shadow:
3203
  0 4px 24px rgba(0, 0, 0, 0.25),
@@ -3214,15 +3126,8 @@ input[type="range"]::-moz-range-thumb {
3214
  }
3215
 
3216
  @keyframes ac-dropdown-in {
3217
- from {
3218
- opacity: 0;
3219
- transform: translateY(-4px);
3220
- }
3221
-
3222
- to {
3223
- opacity: 1;
3224
- transform: translateY(0);
3225
- }
3226
  }
3227
 
3228
  /* ── Dropdown Items ── */
@@ -3242,8 +3147,8 @@ input[type="range"]::-moz-range-thumb {
3242
  .ac-dropdown-item:hover,
3243
  .ac-dropdown-item.ac-selected {
3244
  background: linear-gradient(135deg,
3245
- rgba(107, 163, 224, 0.15),
3246
- rgba(160, 131, 237, 0.12));
3247
  color: var(--color-primary, #6ba3e0);
3248
  }
3249
 
@@ -3255,11 +3160,9 @@ input[type="range"]::-moz-range-thumb {
3255
  #autocomplete-dropdown::-webkit-scrollbar {
3256
  width: 4px;
3257
  }
3258
-
3259
  #autocomplete-dropdown::-webkit-scrollbar-track {
3260
  background: transparent;
3261
  }
3262
-
3263
  #autocomplete-dropdown::-webkit-scrollbar-thumb {
3264
  background: rgba(255, 255, 255, 0.12);
3265
  border-radius: 2px;
@@ -3291,7 +3194,6 @@ input[type="range"]::-moz-range-thumb {
3291
 
3292
  /* ── Print: hide autocomplete ── */
3293
  @media print {
3294
-
3295
  #autocomplete-ghost,
3296
  #autocomplete-dropdown {
3297
  display: none !important;
@@ -3308,10 +3210,7 @@ input[type="range"]::-moz-range-thumb {
3308
  justify-content: center;
3309
  padding: 1rem;
3310
  }
3311
-
3312
- .quran-modal.is-hidden {
3313
- display: none;
3314
- }
3315
 
3316
  /* Quran applied text — protected from analysis */
3317
  .quran-applied {
@@ -3323,7 +3222,6 @@ input[type="range"]::-moz-range-thumb {
3323
  cursor: default;
3324
  user-select: text;
3325
  }
3326
-
3327
  .quran-applied .spelling-error,
3328
  .quran-applied .grammar-error,
3329
  .quran-applied .punctuation-suggestion {
@@ -3332,7 +3230,6 @@ input[type="range"]::-moz-range-thumb {
3332
  background: none !important;
3333
  cursor: default !important;
3334
  }
3335
-
3336
  .quran-ref-inline {
3337
  font-size: 0.72em;
3338
  opacity: 0.6;
@@ -3364,15 +3261,8 @@ input[type="range"]::-moz-range-thumb {
3364
  }
3365
 
3366
  @keyframes quranModalIn {
3367
- from {
3368
- opacity: 0;
3369
- transform: scale(0.95) translateY(10px);
3370
- }
3371
-
3372
- to {
3373
- opacity: 1;
3374
- transform: scale(1) translateY(0);
3375
- }
3376
  }
3377
 
3378
  .quran-result-card {
@@ -3412,15 +3302,11 @@ input[type="range"]::-moz-range-thumb {
3412
  transition: all 0.2s;
3413
  white-space: nowrap;
3414
  }
3415
-
3416
  .quran-apply-btn:hover {
3417
  transform: scale(1.05);
3418
  box-shadow: 0 4px 12px rgba(6, 182, 212, 0.35);
3419
  }
3420
-
3421
- .quran-apply-btn.is-hidden {
3422
- display: none;
3423
- }
3424
 
3425
  .quran-copy-btn {
3426
  padding: 6px 10px;
@@ -3433,15 +3319,11 @@ input[type="range"]::-moz-range-thumb {
3433
  transition: all 0.2s;
3434
  line-height: 1;
3435
  }
3436
-
3437
  .quran-copy-btn:hover {
3438
  background: rgba(6, 182, 212, 0.2);
3439
  transform: scale(1.05);
3440
  }
3441
-
3442
- .quran-copy-btn.is-hidden {
3443
- display: none;
3444
- }
3445
 
3446
  .quran-lang-select {
3447
  padding: 6px 12px;
@@ -3454,11 +3336,9 @@ input[type="range"]::-moz-range-thumb {
3454
  cursor: pointer;
3455
  transition: border-color 0.2s;
3456
  }
3457
-
3458
  .quran-lang-select:hover {
3459
  border-color: #06b6d4;
3460
  }
3461
-
3462
  .quran-lang-select:focus {
3463
  outline: none;
3464
  border-color: #06b6d4;
@@ -3471,7 +3351,6 @@ input[type="range"]::-moz-range-thumb {
3471
  border-radius: 1.25rem;
3472
  padding: 1.25rem;
3473
  }
3474
-
3475
  .quran-uthmani {
3476
  font-size: 20px;
3477
  }
@@ -3491,7 +3370,6 @@ input[type="range"]::-moz-range-thumb {
3491
  .card-hover {
3492
  transition: transform var(--transition-base), box-shadow var(--transition-base);
3493
  }
3494
-
3495
  .card-hover:hover {
3496
  transform: translateY(-3px);
3497
  box-shadow: var(--shadow-glow);
@@ -3507,7 +3385,6 @@ input[type="range"]::-moz-range-thumb {
3507
  text-align: center;
3508
  gap: 0.75rem;
3509
  }
3510
-
3511
  .empty-state__icon {
3512
  width: 48px;
3513
  height: 48px;
@@ -3519,13 +3396,11 @@ input[type="range"]::-moz-range-thumb {
3519
  color: var(--color-primary);
3520
  margin-bottom: 0.25rem;
3521
  }
3522
-
3523
  .empty-state__title {
3524
  font-size: var(--font-size-body);
3525
  font-weight: var(--font-weight-semibold);
3526
  color: var(--color-text-primary);
3527
  }
3528
-
3529
  .empty-state__subtitle {
3530
  font-size: var(--font-size-caption);
3531
  color: var(--color-text-secondary);
@@ -3544,7 +3419,6 @@ input[type="range"]::-moz-range-thumb {
3544
  justify-content: center;
3545
  animation: fadeIn 0.15s ease-out;
3546
  }
3547
-
3548
  .confirm-dialog {
3549
  background: var(--color-surface);
3550
  border: 1px solid var(--color-border-strong);
@@ -3556,26 +3430,22 @@ input[type="range"]::-moz-range-thumb {
3556
  text-align: center;
3557
  animation: modalSlideUp 0.25s ease-out;
3558
  }
3559
-
3560
  .confirm-dialog__title {
3561
  font-size: 1.125rem;
3562
  font-weight: var(--font-weight-bold);
3563
  margin-bottom: 0.5rem;
3564
  }
3565
-
3566
  .confirm-dialog__message {
3567
  font-size: var(--font-size-caption);
3568
  color: var(--color-text-secondary);
3569
  margin-bottom: 1.5rem;
3570
  line-height: 1.7;
3571
  }
3572
-
3573
  .confirm-dialog__actions {
3574
  display: flex;
3575
  gap: 0.75rem;
3576
  justify-content: center;
3577
  }
3578
-
3579
  .confirm-dialog__btn {
3580
  padding: 0.6rem 1.5rem;
3581
  border-radius: var(--radius-md);
@@ -3588,34 +3458,23 @@ input[type="range"]::-moz-range-thumb {
3588
  transition: all var(--transition-fast);
3589
  font-family: inherit;
3590
  }
3591
-
3592
  .confirm-dialog__btn:hover {
3593
  background: var(--color-border);
3594
  }
3595
-
3596
  .confirm-dialog__btn--danger {
3597
  background: var(--color-error);
3598
  color: white;
3599
  border-color: transparent;
3600
  }
3601
-
3602
  .confirm-dialog__btn--danger:hover {
3603
  opacity: 0.9;
3604
  }
3605
 
3606
  /* ── Modal entrance animation ── */
3607
  @keyframes modalSlideUp {
3608
- from {
3609
- opacity: 0;
3610
- transform: translateY(16px) scale(0.97);
3611
- }
3612
-
3613
- to {
3614
- opacity: 1;
3615
- transform: translateY(0) scale(1);
3616
- }
3617
  }
3618
-
3619
  .quran-modal-panel,
3620
  .auth-gate-panel,
3621
  .confirm-dialog {
@@ -3623,23 +3482,14 @@ input[type="range"]::-moz-range-thumb {
3623
  }
3624
 
3625
  /* ── Toast with icons ── */
3626
- .toast--success::before {
3627
- content: ' ';
3628
- }
3629
-
3630
- .toast--error::before {
3631
- content: '✕ ';
3632
- }
3633
-
3634
- .toast--warning::before {
3635
- content: '⚠ ';
3636
- }
3637
 
3638
  /* ── Pricing card glow (active plan) ── */
3639
  .pricing-glow {
3640
  position: relative;
3641
  }
3642
-
3643
  .pricing-glow::before {
3644
  content: '';
3645
  position: absolute;
@@ -3651,37 +3501,24 @@ input[type="range"]::-moz-range-thumb {
3651
  filter: blur(12px);
3652
  animation: pricingPulse 3s ease-in-out infinite;
3653
  }
3654
-
3655
  @keyframes pricingPulse {
3656
-
3657
- 0%,
3658
- 100% {
3659
- opacity: 0.3;
3660
- }
3661
-
3662
- 50% {
3663
- opacity: 0.6;
3664
- }
3665
  }
3666
 
3667
  /* ── Beta banner shimmer ── */
3668
  @keyframes betaShimmer {
3669
- 0% {
3670
- background-position: -200% center;
3671
- }
3672
-
3673
- 100% {
3674
- background-position: 200% center;
3675
- }
3676
  }
3677
-
3678
  .beta-shimmer {
3679
  background-size: 200% auto;
3680
  background-image: linear-gradient(90deg,
3681
- transparent 0%,
3682
- rgba(107, 163, 224, 0.06) 40%,
3683
- rgba(165, 148, 232, 0.08) 60%,
3684
- transparent 100%);
 
3685
  animation: betaShimmer 4s linear infinite;
3686
  }
3687
 
@@ -3719,29 +3556,19 @@ select:focus-visible,
3719
  border-radius: 12px;
3720
  background: var(--color-surface-elevated);
3721
  border: 1px solid var(--color-border-strong);
3722
- box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18), 0 0 0 1px rgba(255, 255, 255, 0.05);
3723
  backdrop-filter: blur(16px);
3724
  transform: translateX(-50%);
3725
  animation: selbar-in 0.2s ease;
3726
  pointer-events: auto;
3727
  }
3728
-
3729
  .selection-toolbar.is-hidden {
3730
  display: none;
3731
  }
3732
-
3733
  @keyframes selbar-in {
3734
- from {
3735
- opacity: 0;
3736
- transform: translateX(-50%) translateY(6px);
3737
- }
3738
-
3739
- to {
3740
- opacity: 1;
3741
- transform: translateX(-50%) translateY(0);
3742
- }
3743
  }
3744
-
3745
  .sel-tool-btn {
3746
  display: inline-flex;
3747
  align-items: center;
@@ -3758,12 +3585,10 @@ select:focus-visible,
3758
  transition: all 0.15s ease;
3759
  white-space: nowrap;
3760
  }
3761
-
3762
  .sel-tool-btn:hover {
3763
  background: var(--color-surface);
3764
  color: var(--color-text-primary);
3765
  }
3766
-
3767
  .sel-tool-sep {
3768
  width: 1px;
3769
  height: 20px;
@@ -3781,7 +3606,6 @@ select:focus-visible,
3781
  padding: 3px;
3782
  overflow: hidden;
3783
  }
3784
-
3785
  .summary-source-btn {
3786
  flex: 1;
3787
  padding: 8px 16px;
@@ -3795,11 +3619,9 @@ select:focus-visible,
3795
  cursor: pointer;
3796
  transition: all 0.2s ease;
3797
  }
3798
-
3799
  .summary-source-btn:hover {
3800
  color: var(--color-text-primary);
3801
  }
3802
-
3803
  .summary-source-btn.active {
3804
  background: linear-gradient(135deg, var(--color-primary), var(--color-secondary));
3805
  color: var(--color-text-inverse);
@@ -3811,312 +3633,6 @@ select:focus-visible,
3811
  margin-left: 4px;
3812
  opacity: 0.7;
3813
  }
3814
-
3815
  .editor-tab.active svg {
3816
  opacity: 1;
3817
  }
3818
-
3819
- /* ── Error Badge on Tab ── */
3820
- .tab-badge {
3821
- display: inline-flex;
3822
- align-items: center;
3823
- justify-content: center;
3824
- min-width: 18px;
3825
- height: 18px;
3826
- padding: 0 5px;
3827
- border-radius: 10px;
3828
- background: #ef4444;
3829
- color: #fff;
3830
- font-size: 10px;
3831
- font-weight: 700;
3832
- margin-inline-start: 6px;
3833
- line-height: 1;
3834
- animation: badgePulse 2s ease-in-out infinite;
3835
- }
3836
- @keyframes badgePulse {
3837
- 0%, 100% { transform: scale(1); }
3838
- 50% { transform: scale(1.1); }
3839
- }
3840
-
3841
- /* ── Find & Replace Bar ── */
3842
- .find-replace-bar {
3843
- padding: 8px 16px;
3844
- background: var(--color-surface-elevated);
3845
- border-bottom: 1px solid var(--color-border);
3846
- display: flex;
3847
- flex-direction: column;
3848
- gap: 6px;
3849
- }
3850
- .find-replace-row {
3851
- display: flex;
3852
- align-items: center;
3853
- gap: 6px;
3854
- }
3855
- .find-input {
3856
- flex: 1;
3857
- background: var(--color-bg);
3858
- border: 1px solid var(--color-border);
3859
- border-radius: 6px;
3860
- padding: 6px 10px;
3861
- color: var(--color-text-primary);
3862
- font-size: 13px;
3863
- font-family: inherit;
3864
- outline: none;
3865
- transition: border-color 0.2s;
3866
- }
3867
- .find-input:focus {
3868
- border-color: var(--color-primary);
3869
- }
3870
- .find-count {
3871
- font-size: 11px;
3872
- color: var(--color-text-secondary);
3873
- min-width: 35px;
3874
- text-align: center;
3875
- }
3876
- .find-btn {
3877
- background: var(--color-surface);
3878
- border: 1px solid var(--color-border);
3879
- border-radius: 5px;
3880
- color: var(--color-text-secondary);
3881
- padding: 4px 8px;
3882
- cursor: pointer;
3883
- font-size: 12px;
3884
- transition: all 0.15s;
3885
- font-family: inherit;
3886
- }
3887
- .find-btn:hover {
3888
- background: var(--color-primary);
3889
- color: #fff;
3890
- border-color: var(--color-primary);
3891
- }
3892
-
3893
- /* ── Find Highlights ── */
3894
- .find-highlight {
3895
- background: rgba(255, 213, 79, 0.3);
3896
- border-radius: 2px;
3897
- }
3898
- .find-highlight--active {
3899
- background: rgba(255, 152, 0, 0.6);
3900
- outline: 2px solid var(--color-primary);
3901
- border-radius: 2px;
3902
- }
3903
-
3904
- body.focus-mode .main-nav,
3905
- body.focus-mode .sidebar-panel,
3906
- body.focus-mode .docs-panel,
3907
- body.focus-mode .docs-panel-desktop {
3908
- display: none !important;
3909
- }
3910
-
3911
- body.focus-mode .editor-footer {
3912
- opacity: 0.2;
3913
- transition: opacity 0.3s ease;
3914
- }
3915
-
3916
- body.focus-mode .editor-footer:hover {
3917
- opacity: 1;
3918
- }
3919
-
3920
- body.focus-mode .editor-layout {
3921
- grid-template-columns: 1fr !important;
3922
- }
3923
- body.focus-mode .format-toolbar {
3924
- opacity: 0.3;
3925
- transition: opacity 0.3s;
3926
- }
3927
- body.focus-mode .format-toolbar:hover {
3928
- opacity: 1;
3929
- }
3930
- body.focus-mode .editor-surface {
3931
- width: 100%;
3932
- }
3933
-
3934
- /* ── Blockquote Styling in Editor ── */
3935
- #editor-container blockquote {
3936
- border-right: 4px solid var(--color-primary);
3937
- margin: 8px 0;
3938
- padding: 8px 16px;
3939
- background: rgba(124, 131, 237, 0.08);
3940
- border-radius: 0 6px 6px 0;
3941
- color: var(--color-text-secondary);
3942
- font-style: italic;
3943
- }
3944
-
3945
- /* ── HR Styling in Editor ── */
3946
- #editor-container hr {
3947
- border: none;
3948
- height: 2px;
3949
- background: linear-gradient(90deg, transparent, var(--color-border), transparent);
3950
- margin: 16px 0;
3951
- }
3952
-
3953
- /* ── Tab Switch Animation ── */
3954
- #write-area,
3955
- #summarize-area,
3956
- #dialect-area,
3957
- #quran-area {
3958
- animation: tabFadeIn 0.3s ease-out;
3959
- }
3960
- @keyframes tabFadeIn {
3961
- from { opacity: 0; transform: translateY(6px); }
3962
- to { opacity: 1; transform: translateY(0); }
3963
- }
3964
-
3965
- /* ── Typewriter Mode ── */
3966
- .typewriter-mode {
3967
- scroll-behavior: smooth;
3968
- padding-top: 40vh !important;
3969
- padding-bottom: 40vh !important;
3970
- }
3971
-
3972
- /* ── Collaboration Hint ── */
3973
- .collab-hint {
3974
- font-size: 10px;
3975
- color: var(--color-text-secondary);
3976
- opacity: 0.7;
3977
- display: inline-flex;
3978
- align-items: center;
3979
- gap: 4px;
3980
- }
3981
- .collab-hint::before {
3982
- content: '';
3983
- width: 6px;
3984
- height: 6px;
3985
- border-radius: 50%;
3986
- background: #22c55e;
3987
- display: inline-block;
3988
- }
3989
-
3990
- /* ── Error Category Tabs ── */
3991
- .error-tabs {
3992
- display: flex;
3993
- gap: 2px;
3994
- margin-bottom: 10px;
3995
- background: var(--color-border);
3996
- border-radius: 8px;
3997
- padding: 2px;
3998
- overflow: hidden;
3999
- }
4000
- .error-tab {
4001
- flex: 1;
4002
- padding: 5px 4px;
4003
- border: none;
4004
- background: transparent;
4005
- color: var(--color-text-secondary);
4006
- font-size: 11px;
4007
- font-weight: 600;
4008
- cursor: pointer;
4009
- border-radius: 6px;
4010
- transition: all 0.2s;
4011
- font-family: inherit;
4012
- }
4013
- .error-tab.active {
4014
- background: var(--color-primary);
4015
- color: #fff;
4016
- }
4017
- .error-tab:hover:not(.active) {
4018
- background: var(--color-surface);
4019
- }
4020
-
4021
- /* ── Error Donut Chart ── */
4022
- .error-chart-wrap {
4023
- display: flex;
4024
- align-items: center;
4025
- justify-content: center;
4026
- gap: 10px;
4027
- margin-bottom: 10px;
4028
- min-height: 0;
4029
- }
4030
- .error-donut {
4031
- transform: rotate(-90deg);
4032
- }
4033
- .chart-legend {
4034
- display: flex;
4035
- flex-direction: column;
4036
- gap: 4px;
4037
- }
4038
- .chart-legend-item {
4039
- display: flex;
4040
- align-items: center;
4041
- gap: 5px;
4042
- font-size: 11px;
4043
- color: var(--color-text-secondary);
4044
- }
4045
- .chart-dot {
4046
- width: 8px;
4047
- height: 8px;
4048
- border-radius: 50%;
4049
- flex-shrink: 0;
4050
- }
4051
-
4052
- /* ── Dismiss All Button ── */
4053
- .dismiss-all-btn {
4054
- width: 100%;
4055
- margin-top: 6px;
4056
- font-size: 12px;
4057
- color: var(--color-text-secondary);
4058
- border: 1px dashed var(--color-border);
4059
- border-radius: 6px;
4060
- padding: 6px;
4061
- text-align: center;
4062
- }
4063
- .dismiss-all-btn:hover {
4064
- border-color: #ef4444;
4065
- color: #ef4444;
4066
- }
4067
-
4068
- /* ── Score Sparkline ── */
4069
- .sparkline {
4070
- display: block;
4071
- margin: 6px auto;
4072
- }
4073
- /* ── Fix Layout: Editor Full Height Fit ── */
4074
- #page-editor > section {
4075
- height: 100vh;
4076
- display: flex;
4077
- flex-direction: column;
4078
- overflow: hidden;
4079
- padding-bottom: 0;
4080
- }
4081
-
4082
- #page-editor .max-w-\[1600px\] {
4083
- flex: 1;
4084
- display: flex;
4085
- flex-direction: column;
4086
- min-height: 0;
4087
- width: 100%;
4088
- }
4089
-
4090
- #page-editor .editor-layout {
4091
- flex: 1;
4092
- min-height: 0;
4093
- height: 100%;
4094
- }
4095
-
4096
- /* Prevent grid items from growing beyond their track */
4097
- #page-editor .editor-layout > div {
4098
- min-width: 0;
4099
- min-height: 0;
4100
- }
4101
-
4102
- #page-editor .editor-shell {
4103
- display: flex;
4104
- flex-direction: column;
4105
- height: 100%;
4106
- overflow: hidden;
4107
- }
4108
-
4109
- #page-editor #write-area,
4110
- #page-editor #summarize-area,
4111
- #page-editor #dialect-area,
4112
- #page-editor #quran-area {
4113
- flex: 1;
4114
- overflow-y: auto;
4115
- min-height: 0;
4116
- }
4117
-
4118
- /* Prevent sidebar cards from squishing */
4119
- #page-editor .sidebar-panel > div {
4120
- flex-shrink: 0;
4121
- }
4122
-
 
299
  position: relative;
300
  }
301
 
302
+ .editor-shell > *:first-child {
303
  border-radius: var(--radius-card) var(--radius-card) 0 0;
304
  }
305
 
306
+ .editor-shell > *:last-child {
307
  border-radius: 0 0 var(--radius-card) var(--radius-card);
308
  }
309
 
 
317
  background: var(--color-surface);
318
  }
319
 
320
+ .editor-toolbar > *:first-child {
321
  justify-self: start;
322
  }
323
 
324
+ .editor-toolbar > *:last-child {
325
  justify-self: end;
326
  }
327
 
 
350
 
351
  .editor-tab:hover {
352
  color: var(--color-text-primary);
353
+ background: rgba(255,255,255,0.06);
354
  }
355
 
356
  .editor-tab.active {
 
365
  align-items: center;
366
  gap: 5px;
367
  }
 
368
  .tab-icon {
369
  flex-shrink: 0;
370
  opacity: 0.8;
371
  vertical-align: middle;
372
  }
 
373
  .editor-tab.active .tab-icon {
374
  opacity: 1;
375
  }
 
378
  [data-tooltip] {
379
  position: relative;
380
  }
 
381
  [data-tooltip]::after {
382
  content: attr(data-tooltip);
383
  position: absolute;
 
395
  opacity: 0;
396
  visibility: hidden;
397
  transition: all 0.2s ease;
398
+ box-shadow: 0 4px 12px rgba(0,0,0,0.2);
399
  border: 1px solid var(--color-border);
400
  z-index: 300;
401
  font-family: inherit;
402
  }
 
403
  [data-tooltip]:hover::after {
404
  opacity: 1;
405
  visibility: visible;
 
409
  /* ── Formatting Toolbar ── */
410
  .format-toolbar {
411
  display: flex;
412
+ flex-wrap: nowrap;
413
  align-items: center;
414
  justify-content: center;
415
+ gap: 3px;
416
  padding: 6px 10px;
417
  border-bottom: 1px solid var(--color-border);
418
  background: var(--color-surface);
419
+ overflow: visible;
420
  position: relative;
421
+ z-index: 50;
422
  flex-shrink: 0;
423
  }
424
 
425
  .fmt-group {
426
  display: flex;
 
427
  align-items: center;
428
  gap: 1px;
429
  background: var(--color-border);
 
558
  background: var(--color-surface);
559
  border: 1px solid var(--color-border);
560
  border-radius: 8px;
561
+ box-shadow: 0 8px 24px rgba(0,0,0,0.15);
562
  padding: 4px;
563
  z-index: 200;
564
  opacity: 0;
 
645
  }
646
 
647
  @media (min-width: 768px) {
648
+ .editor-surface { min-height: 60vh; }
 
 
649
  }
650
 
651
  @media (min-width: 1024px) {
652
+ .editor-surface { min-height: 500px; }
 
 
653
  }
654
 
655
  .editor-surface:focus {
 
689
 
690
  .editor-stats {
691
  display: flex;
692
+ flex-wrap: wrap;
693
  gap: var(--spacing-md);
694
  align-items: center;
695
  }
 
701
  flex-shrink: 0;
702
  }
703
 
704
+ .stat-dot--spelling { background: var(--color-error); }
705
+ .stat-dot--grammar { background: var(--color-warning); }
706
+ .stat-dot--punctuation { background: var(--color-success); }
 
 
 
 
 
 
 
 
707
 
708
  .editor-actions {
709
  display: flex;
710
+ flex-wrap: wrap;
711
  gap: var(--spacing-sm);
712
  }
 
713
  .editor-actions .btn-ghost,
714
  .editor-actions .doc-dropdown .btn-ghost {
715
  width: 40px;
 
719
  display: inline-flex;
720
  align-items: center;
721
  justify-content: center;
 
722
  }
723
 
724
  /* ── Buttons ── */
 
838
  gap: var(--spacing-sm);
839
  }
840
 
841
+ .popover-type--spelling { color: var(--color-error); }
842
+ .popover-type--grammar { color: var(--color-warning); }
843
+ .popover-type--punctuation { color: var(--color-success); }
 
 
 
 
 
 
 
 
844
 
845
  .popover-original-word {
846
  font-size: var(--font-size-sm);
 
939
  cursor: pointer;
940
  transition: all var(--transition-fast);
941
  }
 
942
  .popover-dismiss:hover {
943
  color: var(--color-error);
944
  border-color: var(--color-error);
 
1021
  }
1022
 
1023
  @keyframes fadeIn {
1024
+ from { opacity: 0; transform: translateY(4px); }
1025
+ to { opacity: 1; transform: translateY(0); }
 
 
 
 
 
 
 
1026
  }
1027
 
1028
 
 
1455
  .editor-layout.tools-mode {
1456
  grid-template-columns: 1fr !important;
1457
  }
1458
+ .editor-layout.tools-mode > .docs-panel-desktop,
1459
+ .editor-layout.tools-mode > .sidebar-panel {
 
1460
  display: none !important;
1461
  }
1462
 
 
1612
  border: 1px solid var(--color-primary-subtle-border);
1613
  }
1614
 
1615
+ .check-icon { color: var(--color-success); }
1616
+ .muted-icon { color: var(--color-text-muted); }
 
 
 
 
 
1617
 
1618
  .demo-editor-surface {
1619
  background: var(--color-editor);
 
2034
  transform: translateX(100%);
2035
  transition: transform var(--transition-slow), box-shadow var(--transition-slow);
2036
  box-shadow: none;
2037
+ padding-top: 64px; /* below nav */
 
2038
  }
2039
 
2040
  .docs-sidebar.is-open {
 
2439
  background: linear-gradient(135deg, var(--color-primary), var(--color-secondary));
2440
  cursor: pointer;
2441
  border: 3px solid var(--color-surface);
2442
+ box-shadow: 0 2px 8px rgba(0,0,0,0.25);
2443
  transition: transform 0.15s ease;
2444
  }
2445
 
 
2454
  background: linear-gradient(135deg, var(--color-primary), var(--color-secondary));
2455
  cursor: pointer;
2456
  border: 3px solid var(--color-surface);
2457
+ box-shadow: 0 2px 8px rgba(0,0,0,0.25);
2458
  }
2459
 
2460
  /* ── Item 3: Empty States ── */
 
2644
  font-weight: 700;
2645
  color: var(--color-text-muted);
2646
  }
 
2647
  .fmt-color-swatch--reset:hover {
2648
  border-color: var(--color-error);
2649
  color: var(--color-error);
 
2858
  animation: toast-out 0.25s ease forwards;
2859
  }
2860
 
2861
+ .toast--success { border-color: rgba(34, 197, 94, 0.4); }
2862
+ .toast--error { border-color: rgba(239, 68, 68, 0.4); }
 
 
 
 
 
2863
 
2864
  @keyframes toast-in {
2865
+ from { opacity: 0; transform: translateY(16px); }
2866
+ to { opacity: 1; transform: translateY(0); }
 
 
 
 
 
 
 
2867
  }
2868
 
2869
  @keyframes toast-out {
2870
+ from { opacity: 1; transform: translateY(0); }
2871
+ to { opacity: 0; transform: translateY(16px); }
 
 
 
 
 
 
 
2872
  }
2873
 
2874
  /* ── Scroll to Top ── */
 
2907
 
2908
  /* ── Loading Skeleton ── */
2909
  .skeleton {
2910
+ background: linear-gradient(90deg, var(--color-border) 25%, rgba(255,255,255,0.08) 50%, var(--color-border) 75%);
2911
  background-size: 200% 100%;
2912
  animation: skeleton-shimmer 1.5s ease infinite;
2913
  border-radius: 8px;
 
2924
  }
2925
 
2926
  @keyframes skeleton-shimmer {
2927
+ 0% { background-position: 200% 0; }
2928
+ 100% { background-position: -200% 0; }
 
 
 
 
 
2929
  }
2930
 
2931
  /* ── Word Count Goal ── */
 
2984
  }
2985
 
2986
  @keyframes punc-blink {
2987
+ 0%, 100% { border-left-color: var(--highlight-punctuation-border); }
2988
+ 50% { border-left-color: transparent; }
 
 
 
 
 
 
 
2989
  }
2990
 
2991
  /* ── Fix #6: Document title truncation ── */
 
3001
  /* ── Fix #8: Editor placeholder alignment (Removed hack) ── */
3002
 
3003
  /* ── Fix #11: Pricing cards equal heights ── */
3004
+ #page-pricing .grid > div {
3005
  display: flex;
3006
  flex-direction: column;
3007
  }
3008
+ #page-pricing .grid > div > ul {
 
3009
  flex: 1;
3010
  }
3011
 
 
3014
  cursor: default;
3015
  transition: transform 0.3s ease, filter 0.3s ease, box-shadow 0.3s ease;
3016
  }
 
3017
  .window-dots:hover .dot--red {
3018
  transform: scale(1.25);
3019
  box-shadow: 0 0 8px rgba(239, 68, 68, 0.5);
3020
  }
 
3021
  .window-dots:hover .dot--yellow {
3022
  transform: scale(1.25);
3023
  box-shadow: 0 0 8px rgba(234, 179, 8, 0.5);
3024
  transition-delay: 0.05s;
3025
  }
 
3026
  .window-dots:hover .dot--green {
3027
  transform: scale(1.25);
3028
  box-shadow: 0 0 8px rgba(34, 197, 94, 0.5);
 
3033
  .sidebar-desktop.collapsed {
3034
  display: none !important;
3035
  }
 
3036
  .editor-layout.editor-fullscreen {
3037
  grid-template-columns: 1fr !important;
3038
  }
 
3039
  .editor-layout.editor-fullscreen .sidebar-panel.sidebar-desktop,
3040
  .editor-layout.editor-fullscreen .docs-panel,
3041
  .editor-layout.editor-fullscreen .docs-panel-desktop {
 
3047
  color: #3A424E;
3048
  background: rgba(26, 29, 33, 0.04);
3049
  }
 
3050
  [data-theme="light"] .fmt-btn:hover {
3051
  background: rgba(26, 29, 33, 0.1);
3052
  color: #1A1D21;
3053
  }
 
3054
  [data-theme="light"] .fmt-btn.fmt-active {
3055
  background: rgba(43, 108, 184, 0.14);
3056
  color: #2B6CB8;
3057
  }
 
3058
  [data-theme="light"] .format-toolbar {
3059
  background: #FAF9F6;
3060
  border-bottom-color: rgba(26, 29, 33, 0.12);
3061
  }
 
3062
  [data-theme="light"] .surface-card {
3063
  box-shadow: 0 2px 8px rgba(26, 29, 33, 0.06);
3064
  border: 1px solid rgba(26, 29, 33, 0.08);
3065
  }
 
3066
  [data-theme="light"] .editor-tab {
3067
  color: #5A6472;
3068
  }
 
3069
  [data-theme="light"] .editor-tab:hover {
3070
  color: #1A1D21;
3071
  background: rgba(26, 29, 33, 0.06);
3072
  }
 
3073
  [data-theme="light"] .editor-tab.active {
3074
  color: #fff !important;
3075
  background: linear-gradient(135deg, #4A8FD4, #7C6BC4);
3076
  box-shadow: 0 2px 8px rgba(74, 143, 212, 0.25);
3077
  }
 
3078
  [data-theme="light"] .stat-item {
3079
  color: #3A424E;
3080
  opacity: 1;
3081
  }
 
3082
  [data-theme="light"] .scroll-top-btn {
3083
  box-shadow: 0 4px 16px rgba(26, 29, 33, 0.15);
3084
  }
 
3109
  #autocomplete-dropdown {
3110
  position: fixed;
3111
  background: var(--color-surface, #1a1d21);
3112
+ border: 1px solid var(--color-border, rgba(255,255,255,0.1));
3113
  border-radius: 10px;
3114
  box-shadow:
3115
  0 4px 24px rgba(0, 0, 0, 0.25),
 
3126
  }
3127
 
3128
  @keyframes ac-dropdown-in {
3129
+ from { opacity: 0; transform: translateY(-4px); }
3130
+ to { opacity: 1; transform: translateY(0); }
 
 
 
 
 
 
 
3131
  }
3132
 
3133
  /* ── Dropdown Items ── */
 
3147
  .ac-dropdown-item:hover,
3148
  .ac-dropdown-item.ac-selected {
3149
  background: linear-gradient(135deg,
3150
+ rgba(107, 163, 224, 0.15),
3151
+ rgba(160, 131, 237, 0.12));
3152
  color: var(--color-primary, #6ba3e0);
3153
  }
3154
 
 
3160
  #autocomplete-dropdown::-webkit-scrollbar {
3161
  width: 4px;
3162
  }
 
3163
  #autocomplete-dropdown::-webkit-scrollbar-track {
3164
  background: transparent;
3165
  }
 
3166
  #autocomplete-dropdown::-webkit-scrollbar-thumb {
3167
  background: rgba(255, 255, 255, 0.12);
3168
  border-radius: 2px;
 
3194
 
3195
  /* ── Print: hide autocomplete ── */
3196
  @media print {
 
3197
  #autocomplete-ghost,
3198
  #autocomplete-dropdown {
3199
  display: none !important;
 
3210
  justify-content: center;
3211
  padding: 1rem;
3212
  }
3213
+ .quran-modal.is-hidden { display: none; }
 
 
 
3214
 
3215
  /* Quran applied text — protected from analysis */
3216
  .quran-applied {
 
3222
  cursor: default;
3223
  user-select: text;
3224
  }
 
3225
  .quran-applied .spelling-error,
3226
  .quran-applied .grammar-error,
3227
  .quran-applied .punctuation-suggestion {
 
3230
  background: none !important;
3231
  cursor: default !important;
3232
  }
 
3233
  .quran-ref-inline {
3234
  font-size: 0.72em;
3235
  opacity: 0.6;
 
3261
  }
3262
 
3263
  @keyframes quranModalIn {
3264
+ from { opacity: 0; transform: scale(0.95) translateY(10px); }
3265
+ to { opacity: 1; transform: scale(1) translateY(0); }
 
 
 
 
 
 
 
3266
  }
3267
 
3268
  .quran-result-card {
 
3302
  transition: all 0.2s;
3303
  white-space: nowrap;
3304
  }
 
3305
  .quran-apply-btn:hover {
3306
  transform: scale(1.05);
3307
  box-shadow: 0 4px 12px rgba(6, 182, 212, 0.35);
3308
  }
3309
+ .quran-apply-btn.is-hidden { display: none; }
 
 
 
3310
 
3311
  .quran-copy-btn {
3312
  padding: 6px 10px;
 
3319
  transition: all 0.2s;
3320
  line-height: 1;
3321
  }
 
3322
  .quran-copy-btn:hover {
3323
  background: rgba(6, 182, 212, 0.2);
3324
  transform: scale(1.05);
3325
  }
3326
+ .quran-copy-btn.is-hidden { display: none; }
 
 
 
3327
 
3328
  .quran-lang-select {
3329
  padding: 6px 12px;
 
3336
  cursor: pointer;
3337
  transition: border-color 0.2s;
3338
  }
 
3339
  .quran-lang-select:hover {
3340
  border-color: #06b6d4;
3341
  }
 
3342
  .quran-lang-select:focus {
3343
  outline: none;
3344
  border-color: #06b6d4;
 
3351
  border-radius: 1.25rem;
3352
  padding: 1.25rem;
3353
  }
 
3354
  .quran-uthmani {
3355
  font-size: 20px;
3356
  }
 
3370
  .card-hover {
3371
  transition: transform var(--transition-base), box-shadow var(--transition-base);
3372
  }
 
3373
  .card-hover:hover {
3374
  transform: translateY(-3px);
3375
  box-shadow: var(--shadow-glow);
 
3385
  text-align: center;
3386
  gap: 0.75rem;
3387
  }
 
3388
  .empty-state__icon {
3389
  width: 48px;
3390
  height: 48px;
 
3396
  color: var(--color-primary);
3397
  margin-bottom: 0.25rem;
3398
  }
 
3399
  .empty-state__title {
3400
  font-size: var(--font-size-body);
3401
  font-weight: var(--font-weight-semibold);
3402
  color: var(--color-text-primary);
3403
  }
 
3404
  .empty-state__subtitle {
3405
  font-size: var(--font-size-caption);
3406
  color: var(--color-text-secondary);
 
3419
  justify-content: center;
3420
  animation: fadeIn 0.15s ease-out;
3421
  }
 
3422
  .confirm-dialog {
3423
  background: var(--color-surface);
3424
  border: 1px solid var(--color-border-strong);
 
3430
  text-align: center;
3431
  animation: modalSlideUp 0.25s ease-out;
3432
  }
 
3433
  .confirm-dialog__title {
3434
  font-size: 1.125rem;
3435
  font-weight: var(--font-weight-bold);
3436
  margin-bottom: 0.5rem;
3437
  }
 
3438
  .confirm-dialog__message {
3439
  font-size: var(--font-size-caption);
3440
  color: var(--color-text-secondary);
3441
  margin-bottom: 1.5rem;
3442
  line-height: 1.7;
3443
  }
 
3444
  .confirm-dialog__actions {
3445
  display: flex;
3446
  gap: 0.75rem;
3447
  justify-content: center;
3448
  }
 
3449
  .confirm-dialog__btn {
3450
  padding: 0.6rem 1.5rem;
3451
  border-radius: var(--radius-md);
 
3458
  transition: all var(--transition-fast);
3459
  font-family: inherit;
3460
  }
 
3461
  .confirm-dialog__btn:hover {
3462
  background: var(--color-border);
3463
  }
 
3464
  .confirm-dialog__btn--danger {
3465
  background: var(--color-error);
3466
  color: white;
3467
  border-color: transparent;
3468
  }
 
3469
  .confirm-dialog__btn--danger:hover {
3470
  opacity: 0.9;
3471
  }
3472
 
3473
  /* ── Modal entrance animation ── */
3474
  @keyframes modalSlideUp {
3475
+ from { opacity: 0; transform: translateY(16px) scale(0.97); }
3476
+ to { opacity: 1; transform: translateY(0) scale(1); }
 
 
 
 
 
 
 
3477
  }
 
3478
  .quran-modal-panel,
3479
  .auth-gate-panel,
3480
  .confirm-dialog {
 
3482
  }
3483
 
3484
  /* ── Toast with icons ── */
3485
+ .toast--success::before { content: '✓ '; }
3486
+ .toast--error::before { content: ' '; }
3487
+ .toast--warning::before { content: '⚠ '; }
 
 
 
 
 
 
 
 
3488
 
3489
  /* ── Pricing card glow (active plan) ── */
3490
  .pricing-glow {
3491
  position: relative;
3492
  }
 
3493
  .pricing-glow::before {
3494
  content: '';
3495
  position: absolute;
 
3501
  filter: blur(12px);
3502
  animation: pricingPulse 3s ease-in-out infinite;
3503
  }
 
3504
  @keyframes pricingPulse {
3505
+ 0%, 100% { opacity: 0.3; }
3506
+ 50% { opacity: 0.6; }
 
 
 
 
 
 
 
3507
  }
3508
 
3509
  /* ── Beta banner shimmer ── */
3510
  @keyframes betaShimmer {
3511
+ 0% { background-position: -200% center; }
3512
+ 100% { background-position: 200% center; }
 
 
 
 
 
3513
  }
 
3514
  .beta-shimmer {
3515
  background-size: 200% auto;
3516
  background-image: linear-gradient(90deg,
3517
+ transparent 0%,
3518
+ rgba(107, 163, 224, 0.06) 40%,
3519
+ rgba(165, 148, 232, 0.08) 60%,
3520
+ transparent 100%
3521
+ );
3522
  animation: betaShimmer 4s linear infinite;
3523
  }
3524
 
 
3556
  border-radius: 12px;
3557
  background: var(--color-surface-elevated);
3558
  border: 1px solid var(--color-border-strong);
3559
+ box-shadow: 0 8px 32px rgba(0,0,0,0.18), 0 0 0 1px rgba(255,255,255,0.05);
3560
  backdrop-filter: blur(16px);
3561
  transform: translateX(-50%);
3562
  animation: selbar-in 0.2s ease;
3563
  pointer-events: auto;
3564
  }
 
3565
  .selection-toolbar.is-hidden {
3566
  display: none;
3567
  }
 
3568
  @keyframes selbar-in {
3569
+ from { opacity: 0; transform: translateX(-50%) translateY(6px); }
3570
+ to { opacity: 1; transform: translateX(-50%) translateY(0); }
 
 
 
 
 
 
 
3571
  }
 
3572
  .sel-tool-btn {
3573
  display: inline-flex;
3574
  align-items: center;
 
3585
  transition: all 0.15s ease;
3586
  white-space: nowrap;
3587
  }
 
3588
  .sel-tool-btn:hover {
3589
  background: var(--color-surface);
3590
  color: var(--color-text-primary);
3591
  }
 
3592
  .sel-tool-sep {
3593
  width: 1px;
3594
  height: 20px;
 
3606
  padding: 3px;
3607
  overflow: hidden;
3608
  }
 
3609
  .summary-source-btn {
3610
  flex: 1;
3611
  padding: 8px 16px;
 
3619
  cursor: pointer;
3620
  transition: all 0.2s ease;
3621
  }
 
3622
  .summary-source-btn:hover {
3623
  color: var(--color-text-primary);
3624
  }
 
3625
  .summary-source-btn.active {
3626
  background: linear-gradient(135deg, var(--color-primary), var(--color-secondary));
3627
  color: var(--color-text-inverse);
 
3633
  margin-left: 4px;
3634
  opacity: 0.7;
3635
  }
 
3636
  .editor-tab.active svg {
3637
  opacity: 1;
3638
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/index.html CHANGED
@@ -673,10 +673,10 @@
673
  <span id="auto-save-status" class="text-xs text-secondary" style="opacity:0;transition:opacity 0.3s;"></span>
674
  </div>
675
  <div class="editor-tabs-center">
676
- <button id="write-tab" onclick="switchTab('write')" class="editor-tab active" data-tooltip="كتابة — الاختصار: Alt+1" type="button"><svg class="tab-icon" width="15" height="15" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"/></svg>كتابة<span id="error-badge" class="tab-badge" style="display:none"></span></button>
677
- <button id="summarize-tab" onclick="switchTab('summarize')" class="editor-tab" data-tooltip="تلخيص — الاختصار: Alt+2" type="button"><svg class="tab-icon" width="15" height="15" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/></svg>تلخيص</button>
678
- <button id="dialect-tab" onclick="switchTab('dialect')" class="editor-tab" data-tooltip="تحويل للفصحى — الاختصار: Alt+3" type="button"><svg class="tab-icon" width="15" height="15" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4"/></svg>تحويل للفصحى</button>
679
- <button id="quran-tab" onclick="switchTab('quran')" class="editor-tab" data-tooltip="تدقيق القرآن — الاختصار: Ctrl+Q" type="button"><svg class="tab-icon" width="15" height="15" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"/></svg>تدقيق النص القرآني</button>
680
  </div>
681
  <div class="flex items-center gap-2">
682
  <span id="doc-current-title" class="doc-current-title" style="display:none;"></span>
@@ -748,17 +748,6 @@
748
  <button id="fmt-ltr" class="fmt-btn" onclick="setDirection('ltr')" type="button" data-tooltip="يسار لليمين"><svg width="15" height="15" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 5H7a4 4 0 000 8h2m4-8v14m4-14v14M21 8l-4-3v6"/></svg></button>
749
  <button id="fmt-link" class="fmt-btn" onclick="insertLink()" type="button" data-tooltip="إدراج رابط"><svg width="15" height="15" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"/></svg></button>
750
  <button id="fmt-line-height" class="fmt-btn" onclick="cycleLineHeight()" type="button" data-tooltip="ارتفاع السطر"><svg width="15" height="15" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M20 4v4m0-4l-1.5 1.5M20 4l1.5 1.5M20 20v-4m0 4l-1.5-1.5M20 20l1.5-1.5"/></svg></button>
751
- <button id="fmt-indent" class="fmt-btn" onclick="execFormat('indent')" type="button" data-tooltip="مسافة بادئة"><svg width="15" height="15" fill="currentColor" viewBox="0 0 24 24"><path d="M3 5h18v2H3V5zm6 4h12v2H9V9zm0 4h12v2H9v-2zm-6 4h18v2H3v-2zM3 9l4 3-4 3V9z"/></svg></button>
752
- <button id="fmt-outdent" class="fmt-btn" onclick="execFormat('outdent')" type="button" data-tooltip="إزالة المسافة البادئة"><svg width="15" height="15" fill="currentColor" viewBox="0 0 24 24"><path d="M3 5h18v2H3V5zm6 4h12v2H9V9zm0 4h12v2H9v-2zm-6 4h18v2H3v-2zM7 9l-4 3 4 3V9z"/></svg></button>
753
- <button id="fmt-superscript" class="fmt-btn" onclick="execFormat('superscript')" type="button" data-tooltip="نص مرتفع"><svg width="15" height="15" fill="currentColor" viewBox="0 0 24 24"><path d="M16 7h2v1h-2v1h3V6h-2V5h2V4h-3v3zM5.47 13h2.06L10 7.22 12.47 13h2.06L10 3.3 5.47 13zM4 21l5-7h-3l5-7"/></svg></button>
754
- <button id="fmt-subscript" class="fmt-btn" onclick="execFormat('subscript')" type="button" data-tooltip="نص منخفض"><svg width="15" height="15" fill="currentColor" viewBox="0 0 24 24"><path d="M16 18h2v1h-2v1h3v-4h-2v1h2v1h-3v1zM5.47 13h2.06L10 7.22 12.47 13h2.06L10 3.3 5.47 13z"/></svg></button>
755
- <button id="fmt-blockquote" class="fmt-btn" onclick="formatBlockquote()" type="button" data-tooltip="اقتباس"><svg width="15" height="15" fill="currentColor" viewBox="0 0 24 24"><path d="M6 17h3l2-4V7H5v6h3l-2 4zm8 0h3l2-4V7h-6v6h3l-2 4z"/></svg></button>
756
- <button id="fmt-hr" class="fmt-btn" onclick="execFormat('insertHorizontalRule')" type="button" data-tooltip="فاصل أفقي"><svg width="15" height="15" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-width="2" d="M3 12h18"/></svg></button>
757
- <button id="fmt-paragraph-spacing" class="fmt-btn" onclick="cycleParagraphSpacing()" type="button" data-tooltip="تباعد الفقرات"><svg width="15" height="15" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-width="2" d="M3 5h18M3 19h18"/><path stroke-linecap="round" stroke-width="1.5" d="M12 8v8m0-8l-2 2m2-2l2 2m-2 6l-2-2m2 2l2-2"/></svg></button>
758
- <button id="fmt-remove-tashkeel" class="fmt-btn" onclick="removeTashkeel()" type="button" data-tooltip="إزالة التشكيل"><svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor"><path d="M3 17h18v2H3v-2zm0-6h12v2H3v-2zm0-6h18v2H3V5z"/><path d="M17 7l4 4m0-4l-4 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" fill="none"/></svg></button>
759
- <button id="fmt-to-hindi" class="fmt-btn" onclick="convertToHindiNumerals()" type="button" data-tooltip="أرقام هندية ١٢٣"><svg width="15" height="15" viewBox="0 0 24 24"><text x="12" y="17" text-anchor="middle" font-size="14" font-weight="700" fill="currentColor">١٢</text></svg></button>
760
- <button id="fmt-to-arabic" class="fmt-btn" onclick="convertToArabicNumerals()" type="button" data-tooltip="أرقام عربية 123"><svg width="15" height="15" viewBox="0 0 24 24"><text x="12" y="17" text-anchor="middle" font-size="14" font-weight="700" fill="currentColor">12</text></svg></button>
761
- <button id="fmt-cleanup" class="fmt-btn" onclick="cleanupText()" type="button" data-tooltip="تنظيف النص"><svg width="15" height="15" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z"/></svg></button>
762
  </div>
763
  </div>
764
  <div class="fmt-divider"></div>
@@ -792,21 +781,6 @@
792
  <button class="fmt-btn" onclick="execFormat('removeFormat')" type="button" data-tooltip="مسح التنسيق"><svg width="15" height="15" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 4h12v3M12 4v16"/><path stroke-linecap="round" stroke-width="2.5" d="M5 19L19 5" opacity="0.6"/></svg></button>
793
  </div>
794
  </div>
795
- <div id="find-replace-bar" class="find-replace-bar" style="display:none;">
796
- <div class="find-replace-row">
797
- <input type="text" id="find-input" class="find-input" placeholder="بحث..." autocomplete="off">
798
- <span id="find-count" class="find-count">0/0</span>
799
- <button type="button" class="find-btn" onclick="findPrev()" data-tooltip="السابق">▲</button>
800
- <button type="button" class="find-btn" onclick="findNext()" data-tooltip="��لتالي">▼</button>
801
- <button type="button" class="find-btn" onclick="toggleReplace()" data-tooltip="استبدال">⇄</button>
802
- <button type="button" class="find-btn" onclick="closeFindReplace()" data-tooltip="إغلاق">✕</button>
803
- </div>
804
- <div id="replace-row" class="find-replace-row" style="display:none;">
805
- <input type="text" id="replace-input" class="find-input" placeholder="استبدال بـ..." autocomplete="off">
806
- <button type="button" class="find-btn" onclick="replaceCurrent()">استبدال</button>
807
- <button type="button" class="find-btn" onclick="replaceAll()">استبدال الكل</button>
808
- </div>
809
- </div>
810
  <input type="file" id="doc-import-input" class="sr-only" accept=".txt,.docx,text/plain,application/vnd.openxmlformats-officedocument.wordprocessingml.document" aria-hidden="true">
811
  <div id="write-area">
812
  <div id="analysis-limit-banner" class="analysis-limit-banner is-hidden" role="status" aria-live="polite"></div>
@@ -829,18 +803,14 @@
829
  <div class="flex items-center gap-2"><span class="stat-dot stat-dot--punctuation" aria-hidden="true"></span><span class="text-sm text-secondary"><span id="punctuation-count">٠</span> ترقيم</span></div>
830
  <span class="stat-item--sep"></span>
831
  <span class="stat-item"><span id="char-count">٠</span> حرف</span>
832
- <span class="stat-item"><span id="paragraph-count">٠</span> فقرة</span>
833
- <span class="stat-item"><span id="sentence-count">٠</span> جملة</span>
834
  <span class="stat-item" style="cursor:pointer;" onclick="setWordGoalUI()" title="اضغط لتحديد هدف عدد الكلمات"><span id="word-count" class="font-bold">٠</span> كلمة</span>
835
  <span id="word-goal-indicator" class="word-goal-badge" style="display:none;cursor:pointer;" onclick="setWordGoalUI()" title="اضغط لتغيير الهدف"></span>
836
  <span class="stat-item--sep"></span>
837
  <span class="stat-item">⏱ <span id="reading-time">٠</span> د قراءة</span>
838
- <span class="collab-hint" id="last-edit-hint"></span></div>
839
  <div class="editor-actions">
840
- <button id="focus-mode-btn" class="btn-ghost" type="button" data-tooltip="وضع التركيز (Ctrl+Shift+F)" onclick="toggleFocusMode()"><svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"/></svg></button>
841
- <button id="typewriter-mode-btn" class="btn-ghost" type="button" data-tooltip="وضع الآلة الكاتبة" onclick="toggleTypewriterMode()"><svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 10h16M7 14h10M9 18h6"/></svg></button>
842
- <button id="version-history-btn" class="btn-ghost" type="button" data-tooltip="سجل النسخ" onclick="showVersionHistory()"><svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/></svg></button>
843
- <button id="doc-save-btn" class="doc-save-btn-icon btn-ghost" type="button" aria-label="حفظ المستند" title="حفظ">
844
  <svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4"/></svg>
845
  </button>
846
  <button onclick="clearEditor()" class="btn-ghost" type="button" title="مسح الكل">
@@ -1016,17 +986,9 @@
1016
  <!-- LEFT: Sidebar (score + suggestions + import/export) -->
1017
  <div class="sidebar-panel sidebar-desktop">
1018
  <div class="surface-card sidebar-card">
1019
- <h3 class="text-xl font-bold mb-3 text-right">الاقتراحات</h3>
1020
- <div class="error-tabs">
1021
- <button class="error-tab active" data-filter="all" onclick="filterErrors('all')">الكل</button>
1022
- <button class="error-tab" data-filter="spelling" onclick="filterErrors('spelling')">إملائي</button>
1023
- <button class="error-tab" data-filter="grammar" onclick="filterErrors('grammar')">نحوي</button>
1024
- <button class="error-tab" data-filter="punctuation" onclick="filterErrors('punctuation')">ترقيم</button>
1025
- </div>
1026
- <div id="error-chart" class="error-chart-wrap"></div>
1027
  <div id="suggestions-list" class="suggestions-scroll" role="list" aria-live="polite" aria-label="اقتراحات التصحيح"></div>
1028
  <button id="apply-all-btn" class="btn-primary apply-all-btn is-hidden" type="button">تطبيق الكل</button>
1029
- <button id="dismiss-filtered-btn" class="btn-ghost dismiss-all-btn is-hidden" type="button" onclick="dismissAllFiltered()">تجاهل الكل</button>
1030
  </div>
1031
  <div class="surface-card sidebar-card">
1032
  <h3 class="text-xl font-bold mb-4 text-right">تقييم الكتابة</h3>
@@ -1038,7 +1000,6 @@
1038
  </svg>
1039
  <div class="score-value"><span id="score-value">--</span></div>
1040
  </div>
1041
- <div id="score-sparkline"></div>
1042
  <p id="score-hint" class="text-center text-sm text-secondary">ابدأ الكتابة لرؤية تقييمك</p>
1043
  </div>
1044
  </div>
 
673
  <span id="auto-save-status" class="text-xs text-secondary" style="opacity:0;transition:opacity 0.3s;"></span>
674
  </div>
675
  <div class="editor-tabs-center">
676
+ <button id="write-tab" onclick="switchTab('write')" class="editor-tab active" type="button"><svg class="tab-icon" width="15" height="15" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"/></svg>كتابة</button>
677
+ <button id="summarize-tab" onclick="switchTab('summarize')" class="editor-tab" type="button"><svg class="tab-icon" width="15" height="15" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/></svg>تلخيص</button>
678
+ <button id="dialect-tab" onclick="switchTab('dialect')" class="editor-tab" type="button"><svg class="tab-icon" width="15" height="15" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4"/></svg>تحويل للفصحى</button>
679
+ <button id="quran-tab" onclick="switchTab('quran')" class="editor-tab" type="button"><svg class="tab-icon" width="15" height="15" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"/></svg>تدقيق النص القرآني</button>
680
  </div>
681
  <div class="flex items-center gap-2">
682
  <span id="doc-current-title" class="doc-current-title" style="display:none;"></span>
 
748
  <button id="fmt-ltr" class="fmt-btn" onclick="setDirection('ltr')" type="button" data-tooltip="يسار لليمين"><svg width="15" height="15" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 5H7a4 4 0 000 8h2m4-8v14m4-14v14M21 8l-4-3v6"/></svg></button>
749
  <button id="fmt-link" class="fmt-btn" onclick="insertLink()" type="button" data-tooltip="إدراج رابط"><svg width="15" height="15" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"/></svg></button>
750
  <button id="fmt-line-height" class="fmt-btn" onclick="cycleLineHeight()" type="button" data-tooltip="ارتفاع السطر"><svg width="15" height="15" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M20 4v4m0-4l-1.5 1.5M20 4l1.5 1.5M20 20v-4m0 4l-1.5-1.5M20 20l1.5-1.5"/></svg></button>
 
 
 
 
 
 
 
 
 
 
 
751
  </div>
752
  </div>
753
  <div class="fmt-divider"></div>
 
781
  <button class="fmt-btn" onclick="execFormat('removeFormat')" type="button" data-tooltip="مسح التنسيق"><svg width="15" height="15" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 4h12v3M12 4v16"/><path stroke-linecap="round" stroke-width="2.5" d="M5 19L19 5" opacity="0.6"/></svg></button>
782
  </div>
783
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
784
  <input type="file" id="doc-import-input" class="sr-only" accept=".txt,.docx,text/plain,application/vnd.openxmlformats-officedocument.wordprocessingml.document" aria-hidden="true">
785
  <div id="write-area">
786
  <div id="analysis-limit-banner" class="analysis-limit-banner is-hidden" role="status" aria-live="polite"></div>
 
803
  <div class="flex items-center gap-2"><span class="stat-dot stat-dot--punctuation" aria-hidden="true"></span><span class="text-sm text-secondary"><span id="punctuation-count">٠</span> ترقيم</span></div>
804
  <span class="stat-item--sep"></span>
805
  <span class="stat-item"><span id="char-count">٠</span> حرف</span>
806
+ <span class="stat-item"><span id="sentence-count">٠</span> جملة</span>
 
807
  <span class="stat-item" style="cursor:pointer;" onclick="setWordGoalUI()" title="اضغط لتحديد هدف عدد الكلمات"><span id="word-count" class="font-bold">٠</span> كلمة</span>
808
  <span id="word-goal-indicator" class="word-goal-badge" style="display:none;cursor:pointer;" onclick="setWordGoalUI()" title="اضغط لتغيير الهدف"></span>
809
  <span class="stat-item--sep"></span>
810
  <span class="stat-item">⏱ <span id="reading-time">٠</span> د قراءة</span>
811
+ </div>
812
  <div class="editor-actions">
813
+ <button id="doc-save-btn" class="doc-save-btn-icon btn-ghost" type="button" aria-label="حفظ المستند" title="حفظ">
 
 
 
814
  <svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4"/></svg>
815
  </button>
816
  <button onclick="clearEditor()" class="btn-ghost" type="button" title="مسح الكل">
 
986
  <!-- LEFT: Sidebar (score + suggestions + import/export) -->
987
  <div class="sidebar-panel sidebar-desktop">
988
  <div class="surface-card sidebar-card">
989
+ <h3 class="text-xl font-bold mb-4 text-right">الاقتراحات</h3>
 
 
 
 
 
 
 
990
  <div id="suggestions-list" class="suggestions-scroll" role="list" aria-live="polite" aria-label="اقتراحات التصحيح"></div>
991
  <button id="apply-all-btn" class="btn-primary apply-all-btn is-hidden" type="button">تطبيق الكل</button>
 
992
  </div>
993
  <div class="surface-card sidebar-card">
994
  <h3 class="text-xl font-bold mb-4 text-right">تقييم الكتابة</h3>
 
1000
  </svg>
1001
  <div class="score-value"><span id="score-value">--</span></div>
1002
  </div>
 
1003
  <p id="score-hint" class="text-center text-sm text-secondary">ابدأ الكتابة لرؤية تقييمك</p>
1004
  </div>
1005
  </div>
src/js/editor.js CHANGED
@@ -666,38 +666,6 @@ function dismissSuggestion(suggestion) {
666
  const _ed3 = getEditorElement(); if (_ed3) _ed3.focus();
667
  }
668
 
669
- window.dismissAndReRenderAll = function(type) {
670
- if (!window.currentSuggestions || window.currentSuggestions.length === 0) return;
671
- pushUndoState();
672
- const toDismiss = type === 'all' ? window.currentSuggestions : window.currentSuggestions.filter(s => s.type === type);
673
-
674
- toDismiss.forEach(s => {
675
- if (s.original) _dismissedWords.add(s.original);
676
- });
677
- _saveDismissedWords();
678
-
679
- window.currentSuggestions = window.currentSuggestions.filter(s =>
680
- type === 'all' ? false : s.type !== type
681
- );
682
-
683
- const editor = getEditorElement();
684
- clearOverlays(editor);
685
- overlaySuggestions(editor, window.currentSuggestions);
686
-
687
- const spellingCount = window.currentSuggestions.filter(s => s.type === 'spelling').length;
688
- const grammarCount = window.currentSuggestions.filter(s => s.type === 'grammar').length;
689
- const punctuationCount = window.currentSuggestions.filter(s => s.type === 'punctuation').length;
690
-
691
- updateSuggestionCounts(spellingCount, grammarCount, punctuationCount);
692
- updateWritingScore(spellingCount, grammarCount, punctuationCount);
693
- updateSuggestionsList(window.currentSuggestions);
694
-
695
- // Update sidebar button visibility via global format.js function if it exists
696
- if (typeof window.renderSuggestionsSidebar === 'function') {
697
- window.renderSuggestionsSidebar(window.currentSuggestions);
698
- }
699
- };
700
-
701
  function applySuggestionById(id) {
702
  // Pipeline Hardening v3.3: UUID-based lookup
703
  const suggestion = findSuggestionById(id);
 
666
  const _ed3 = getEditorElement(); if (_ed3) _ed3.focus();
667
  }
668
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
669
  function applySuggestionById(id) {
670
  // Pipeline Hardening v3.3: UUID-based lookup
671
  const suggestion = findSuggestionById(id);
src/js/format.js CHANGED
@@ -95,369 +95,13 @@ function cycleLineHeight() {
95
  const idx = heights.indexOf(_currentLineHeight);
96
  _currentLineHeight = heights[(idx + 1) % heights.length];
97
  editor.style.lineHeight = _currentLineHeight;
 
98
  const btn = document.getElementById('fmt-line-height');
99
  if (btn) {
100
  btn.setAttribute('data-tooltip', 'ارتفاع السطر: ' + _currentLineHeight);
101
  }
102
  }
103
 
104
- /* ── Blockquote ── */
105
- function formatBlockquote() {
106
- execFormat('formatBlock', 'blockquote');
107
- }
108
-
109
- /* ── Paragraph Spacing ── */
110
- var _paragraphSpacing = 'normal';
111
- function cycleParagraphSpacing() {
112
- const editor = getEditorElement();
113
- if (!editor) return;
114
- const modes = { tight: '0.3em', normal: '0.8em', wide: '1.5em' };
115
- const order = ['tight', 'normal', 'wide'];
116
- const idx = order.indexOf(_paragraphSpacing);
117
- _paragraphSpacing = order[(idx + 1) % order.length];
118
- const val = modes[_paragraphSpacing];
119
- editor.style.setProperty('--paragraph-spacing', val);
120
- editor.querySelectorAll('div,p').forEach(el => {
121
- el.style.marginBottom = val;
122
- });
123
- }
124
-
125
- /* ── Find & Replace ── */
126
- var _findMatches = [];
127
- var _findIdx = -1;
128
-
129
- function openFindReplace() {
130
- const bar = document.getElementById('find-replace-bar');
131
- if (bar) {
132
- bar.style.display = 'block';
133
- document.getElementById('find-input')?.focus();
134
- }
135
- }
136
-
137
- function closeFindReplace() {
138
- const bar = document.getElementById('find-replace-bar');
139
- if (bar) bar.style.display = 'none';
140
- clearHighlights();
141
- _findMatches = [];
142
- _findIdx = -1;
143
- const countEl = document.getElementById('find-count');
144
- if (countEl) countEl.textContent = '0/0';
145
- }
146
-
147
- function toggleReplace() {
148
- const row = document.getElementById('replace-row');
149
- if (row) row.style.display = row.style.display === 'none' ? 'flex' : 'none';
150
- }
151
-
152
- function doFind() {
153
- const query = document.getElementById('find-input')?.value;
154
- if (!query) { clearHighlights(); return; }
155
- const editor = getEditorElement();
156
- if (!editor) return;
157
- clearHighlights();
158
- const walker = document.createTreeWalker(editor, NodeFilter.SHOW_TEXT, null, false);
159
- _findMatches = [];
160
- let node;
161
- while (node = walker.nextNode()) {
162
- let idx = node.textContent.indexOf(query);
163
- while (idx !== -1) {
164
- _findMatches.push({ node, idx, len: query.length });
165
- idx = node.textContent.indexOf(query, idx + 1);
166
- }
167
- }
168
- // Highlight all matches
169
- for (let i = _findMatches.length - 1; i >= 0; i--) {
170
- const m = _findMatches[i];
171
- const range = document.createRange();
172
- range.setStart(m.node, m.idx);
173
- range.setEnd(m.node, m.idx + m.len);
174
- const span = document.createElement('span');
175
- span.className = 'find-highlight';
176
- range.surroundContents(span);
177
- }
178
- // Re-collect highlighted spans
179
- _findMatches = Array.from(editor.querySelectorAll('.find-highlight'));
180
- _findIdx = _findMatches.length > 0 ? 0 : -1;
181
- updateFindCount();
182
- if (_findIdx >= 0) highlightCurrent();
183
- }
184
-
185
- function findNext() {
186
- if (_findMatches.length === 0) { doFind(); return; }
187
- _findIdx = (_findIdx + 1) % _findMatches.length;
188
- updateFindCount();
189
- highlightCurrent();
190
- }
191
-
192
- function findPrev() {
193
- if (_findMatches.length === 0) { doFind(); return; }
194
- _findIdx = (_findIdx - 1 + _findMatches.length) % _findMatches.length;
195
- updateFindCount();
196
- highlightCurrent();
197
- }
198
-
199
- function highlightCurrent() {
200
- _findMatches.forEach((el, i) => {
201
- el.classList.toggle('find-highlight--active', i === _findIdx);
202
- });
203
- if (_findMatches[_findIdx]) {
204
- _findMatches[_findIdx].scrollIntoView({ block: 'center', behavior: 'smooth' });
205
- }
206
- }
207
-
208
- function updateFindCount() {
209
- const el = document.getElementById('find-count');
210
- if (el) el.textContent = _findMatches.length > 0 ? `${_findIdx + 1}/${_findMatches.length}` : '0/0';
211
- }
212
-
213
- function replaceCurrent() {
214
- if (_findIdx < 0 || !_findMatches[_findIdx]) return;
215
- const replaceVal = document.getElementById('replace-input')?.value || '';
216
- _findMatches[_findIdx].textContent = replaceVal;
217
- _findMatches[_findIdx].className = '';
218
- _findMatches.splice(_findIdx, 1);
219
- if (_findIdx >= _findMatches.length) _findIdx = 0;
220
- updateFindCount();
221
- if (_findMatches.length > 0) highlightCurrent();
222
- }
223
-
224
- function replaceAll() {
225
- const replaceVal = document.getElementById('replace-input')?.value || '';
226
- _findMatches.forEach(el => {
227
- el.textContent = replaceVal;
228
- el.className = '';
229
- });
230
- _findMatches = [];
231
- _findIdx = -1;
232
- updateFindCount();
233
- }
234
-
235
- function clearHighlights() {
236
- const editor = getEditorElement();
237
- if (!editor) return;
238
- editor.querySelectorAll('.find-highlight').forEach(el => {
239
- const parent = el.parentNode;
240
- parent.replaceChild(document.createTextNode(el.textContent), el);
241
- parent.normalize();
242
- });
243
- }
244
-
245
- /* ── Focus Mode ── */
246
- var _focusMode = false;
247
- function toggleFocusMode() {
248
- _focusMode = !_focusMode;
249
- document.body.classList.toggle('focus-mode', _focusMode);
250
- const btn = document.getElementById('focus-mode-btn');
251
- if (btn) btn.classList.toggle('fmt-active', _focusMode);
252
- }
253
-
254
- /* ── Typewriter Mode ── */
255
- var _typewriterMode = false;
256
- function toggleTypewriterMode() {
257
- _typewriterMode = !_typewriterMode;
258
- const editor = getEditorElement();
259
- if (!editor) return;
260
- editor.classList.toggle('typewriter-mode', _typewriterMode);
261
- if (_typewriterMode) {
262
- editor.addEventListener('input', typewriterScroll);
263
- editor.addEventListener('click', typewriterScroll);
264
- } else {
265
- editor.removeEventListener('input', typewriterScroll);
266
- editor.removeEventListener('click', typewriterScroll);
267
- }
268
- }
269
- function typewriterScroll() {
270
- const sel = window.getSelection();
271
- if (!sel.rangeCount) return;
272
- const range = sel.getRangeAt(0);
273
- const rect = range.getBoundingClientRect();
274
- const editor = getEditorElement();
275
- if (!editor) return;
276
- const editorRect = editor.getBoundingClientRect();
277
- const middle = editorRect.height / 2;
278
- const offset = rect.top - editorRect.top - middle;
279
- editor.scrollTop += offset;
280
- }
281
-
282
- /* ── Version History ── */
283
- function saveVersion() {
284
- const editor = getEditorElement();
285
- if (!editor) return;
286
- const versions = JSON.parse(localStorage.getItem('bayan_versions') || '[]');
287
- versions.push({
288
- timestamp: Date.now(),
289
- content: editor.innerHTML,
290
- preview: editor.textContent.substring(0, 50)
291
- });
292
- // Keep last 20 versions
293
- if (versions.length > 20) versions.shift();
294
- localStorage.setItem('bayan_versions', JSON.stringify(versions));
295
- }
296
-
297
- function showVersionHistory() {
298
- const versions = JSON.parse(localStorage.getItem('bayan_versions') || '[]');
299
- if (!versions.length) { alert('لا توجد نسخ سابقة'); return; }
300
- let msg = 'اختر نسخة للاستعادة:\n\n';
301
- versions.forEach((v, i) => {
302
- const date = new Date(v.timestamp);
303
- msg += `${i + 1}. ${date.toLocaleString('ar-EG')} — "${v.preview}..."\n`;
304
- });
305
- const choice = prompt(msg + '\nأدخل رقم النسخة:');
306
- if (!choice) return;
307
- const idx = parseInt(choice) - 1;
308
- if (idx >= 0 && idx < versions.length) {
309
- const editor = getEditorElement();
310
- if (editor) {
311
- pushUndoState();
312
- editor.innerHTML = versions[idx].content;
313
- }
314
- }
315
- }
316
-
317
- /* ── Collaboration Hints (last edit timestamp) ── */
318
- var _lastEditTime = null;
319
- function updateLastEditTime() {
320
- _lastEditTime = Date.now();
321
- updateCollabHint();
322
- }
323
- function updateCollabHint() {
324
- const el = document.getElementById('last-edit-hint');
325
- if (!el || !_lastEditTime) return;
326
- const diff = Math.floor((Date.now() - _lastEditTime) / 1000);
327
- if (diff < 5) el.textContent = 'الآن';
328
- else if (diff < 60) el.textContent = `منذ ${diff} ثانية`;
329
- else if (diff < 3600) el.textContent = `منذ ${Math.floor(diff/60)} دقيقة`;
330
- else el.textContent = `منذ ${Math.floor(diff/3600)} ساعة`;
331
- }
332
-
333
- /* ── Tashkeel (Diacritics) ── */
334
- function addTashkeel() {
335
- // This adds basic tashkeel placeholder — real implementation needs NLP
336
- alert('ميزة التشكيل التلقائي قيد التطوير. سيتم إضافتها قريباً.');
337
- }
338
- function removeTashkeel() {
339
- const editor = getEditorElement();
340
- if (!editor) return;
341
- pushUndoState();
342
- const diacritics = /[\u064B-\u065F\u0670\u06D6-\u06ED]/g;
343
- // Walk through text nodes only
344
- const walker = document.createTreeWalker(editor, NodeFilter.SHOW_TEXT, null, false);
345
- let node;
346
- while (node = walker.nextNode()) {
347
- const cleaned = node.textContent.replace(diacritics, '');
348
- if (cleaned !== node.textContent) {
349
- node.textContent = cleaned;
350
- }
351
- }
352
- }
353
-
354
- /* ── Number Conversion (Arabic ↔ Hindi) ── */
355
- function convertToHindiNumerals() {
356
- const editor = getEditorElement();
357
- if (!editor) return;
358
- pushUndoState();
359
- const map = {'0':'٠','1':'١','2':'٢','3':'٣','4':'٤','5':'٥','6':'٦','7':'٧','8':'٨','9':'٩'};
360
- fmtWalkTextNodes(editor, text => text.replace(/[0-9]/g, d => map[d]));
361
- }
362
- function convertToArabicNumerals() {
363
- const editor = getEditorElement();
364
- if (!editor) return;
365
- pushUndoState();
366
- const map = {'٠':'0','١':'1','٢':'2','٣':'3','٤':'4','٥':'5','٦':'6','٧':'7','٨':'8','٩':'9'};
367
- fmtWalkTextNodes(editor, text => text.replace(/[٠-٩]/g, d => map[d]));
368
- }
369
- function fmtWalkTextNodes(root, fn) {
370
- const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false);
371
- let node;
372
- while (node = walker.nextNode()) {
373
- const result = fn(node.textContent);
374
- if (result !== node.textContent) node.textContent = result;
375
- }
376
- }
377
-
378
- /* ── Text Cleanup ── */
379
- function cleanupText() {
380
- const editor = getEditorElement();
381
- if (!editor) return;
382
- pushUndoState();
383
- fmtWalkTextNodes(editor, text => {
384
- return text
385
- .replace(/[\u064B-\u065F\u0670\u06D6-\u06ED]/g, '') // Remove diacritics
386
- .replace(/\u200C/g, '') // Remove ZWNJ
387
- .replace(/\u200D/g, '') // Remove ZWJ
388
- .replace(/\u00A0/g, ' ') // NBSP → space
389
- .replace(/ {2,}/g, ' ') // Multiple spaces → one
390
- .replace(/\n{3,}/g, '\n\n'); // Multiple newlines → two
391
- });
392
- }
393
-
394
- /* ── Error Badge Update ── */
395
- function updateErrorBadge() {
396
- const badge = document.getElementById('error-badge');
397
- if (!badge) return;
398
- const s = parseInt(document.getElementById('spelling-count')?.textContent) || 0;
399
- const g = parseInt(document.getElementById('grammar-count')?.textContent) || 0;
400
- const p = parseInt(document.getElementById('punctuation-count')?.textContent) || 0;
401
- const total = s + g + p;
402
- if (total > 0) {
403
- badge.textContent = total;
404
- badge.style.display = 'inline-flex';
405
- } else {
406
- badge.style.display = 'none';
407
- }
408
- }
409
-
410
- /* ── Paragraph Count ── */
411
- function updateParagraphCount() {
412
- const editor = getEditorElement();
413
- if (!editor) return;
414
- const text = editor.textContent || '';
415
- const paras = text.split(/\n\s*\n/).filter(p => p.trim().length > 0);
416
- const count = text.trim().length > 0 ? Math.max(1, paras.length) : 0;
417
- const el = document.getElementById('paragraph-count');
418
- if (el) el.textContent = count.toLocaleString('ar-EG');
419
- }
420
-
421
- /* ── Tab Keyboard Shortcuts ── */
422
- function initTabShortcuts() {
423
- document.addEventListener('keydown', (e) => {
424
- if (e.altKey && !e.ctrlKey) {
425
- if (e.key === '1') { e.preventDefault(); switchTab('write'); }
426
- else if (e.key === '2') { e.preventDefault(); switchTab('summarize'); }
427
- else if (e.key === '3') { e.preventDefault(); switchTab('dialect'); }
428
- else if (e.key === '4') { e.preventDefault(); switchTab('quran'); }
429
- }
430
- // Ctrl+H for Find & Replace
431
- if (e.ctrlKey && e.key === 'h') {
432
- e.preventDefault();
433
- openFindReplace();
434
- }
435
- // Ctrl+Shift+F for Focus Mode
436
- if (e.ctrlKey && e.shiftKey && e.key === 'F') {
437
- e.preventDefault();
438
- toggleFocusMode();
439
- }
440
- // Ctrl+K for link
441
- if (e.ctrlKey && e.key === 'k') {
442
- e.preventDefault();
443
- insertLink();
444
- }
445
- });
446
- }
447
-
448
- /* ── Font Hover Preview ── */
449
- function initFontHoverPreview() {
450
- document.querySelectorAll('#fmt-font-menu .fmt-dropdown__item').forEach(item => {
451
- item.addEventListener('mouseenter', () => {
452
- const label = document.getElementById('fmt-font-label');
453
- if (label) label.style.fontFamily = item.dataset.font;
454
- });
455
- item.addEventListener('mouseleave', () => {
456
- const label = document.getElementById('fmt-font-label');
457
- if (label) label.style.fontFamily = '';
458
- });
459
- });
460
- }
461
 
462
  /* ── Font family ── */
463
  function formatFont(fontName) {
@@ -664,42 +308,6 @@ function initFormatToolbar() {
664
  // Item 8: Color pickers
665
  initColorPicker('fmt-textcolor', 'foreColor', 'fmt-textcolor-bar');
666
  initColorPicker('fmt-highlight', 'hiliteColor', 'fmt-highlight-bar');
667
-
668
- // Tab keyboard shortcuts (Alt+1/2/3/4, Ctrl+H, Ctrl+Shift+F, Ctrl+K)
669
- initTabShortcuts();
670
-
671
- // Font hover preview
672
- initFontHoverPreview();
673
-
674
- // Find input listener
675
- const findInput = document.getElementById('find-input');
676
- if (findInput) {
677
- findInput.addEventListener('input', doFind);
678
- findInput.addEventListener('keydown', (e) => {
679
- if (e.key === 'Enter') { e.shiftKey ? findPrev() : findNext(); }
680
- if (e.key === 'Escape') closeFindReplace();
681
- });
682
- }
683
-
684
- // Auto-save version every 2 minutes
685
- setInterval(() => {
686
- const ed = getEditorElement();
687
- if (ed && ed.textContent.trim().length > 10) saveVersion();
688
- }, 120000);
689
-
690
- // Collaboration hint updater every 30s
691
- setInterval(updateCollabHint, 30000);
692
-
693
- // Hook editor input for error badge + paragraph count + last edit time
694
- if (editor) {
695
- const origInputHandler = editor.oninput;
696
- editor.addEventListener('input', () => {
697
- updateParagraphCount();
698
- updateLastEditTime();
699
- // Delay badge update to let analysis finish
700
- setTimeout(updateErrorBadge, 2000);
701
- });
702
- }
703
  }
704
 
705
  /* ── Item 8: Color Picker ── */
@@ -835,99 +443,3 @@ function initDocSearch() {
835
  });
836
  });
837
  }
838
-
839
- /* ── Error Filtering (Sidebar tabs) ── */
840
- var _currentErrorFilter = 'all';
841
- function filterErrors(type) {
842
- _currentErrorFilter = type;
843
- // Update tab active state
844
- document.querySelectorAll('.error-tab').forEach(tab => {
845
- tab.classList.toggle('active', tab.dataset.filter === type);
846
- });
847
- // Filter suggestion items
848
- document.querySelectorAll('#suggestions-list .suggestion-item, #suggestions-list .sugg-card, #suggestions-list .suggestion-card').forEach(item => {
849
- if (type === 'all') {
850
- item.style.display = '';
851
- } else {
852
- const itemType = item.dataset.type || item.getAttribute('data-error-type') || '';
853
- item.style.display = itemType.includes(type) ? '' : 'none';
854
- }
855
- });
856
- // Show/hide dismiss button
857
- const dismissBtn = document.getElementById('dismiss-filtered-btn');
858
- if (dismissBtn) {
859
- dismissBtn.classList.remove('is-hidden');
860
- // For 'all', show total count, else show filtered count
861
- const count = type === 'all' ? window.currentSuggestions?.length || 0
862
- : (window.currentSuggestions?.filter(s => s.type === type).length || 0);
863
- dismissBtn.style.display = count > 0 ? '' : 'none';
864
- }
865
- }
866
-
867
- function dismissAllFiltered() {
868
- const type = window._currentErrorFilter || 'all';
869
- if (typeof window.dismissAndReRenderAll === 'function') {
870
- window.dismissAndReRenderAll(type);
871
- }
872
- }
873
-
874
- /* ── Error Breakdown Chart (SVG Donut) ── */
875
- function renderErrorChart() {
876
- const container = document.getElementById('error-chart');
877
- if (!container) return;
878
- const s = parseInt(document.getElementById('spelling-count')?.textContent) || 0;
879
- const g = parseInt(document.getElementById('grammar-count')?.textContent) || 0;
880
- const p = parseInt(document.getElementById('punctuation-count')?.textContent) || 0;
881
- const total = s + g + p;
882
- if (total === 0) {
883
- container.innerHTML = '';
884
- return;
885
- }
886
- const r = 30, cx = 40, cy = 40, c = 2 * Math.PI * r;
887
- const segments = [
888
- { val: s, color: '#ef4444', label: 'إملائي' },
889
- { val: g, color: '#f59e0b', label: 'نحوي' },
890
- { val: p, color: '#22c55e', label: 'ترقيم' },
891
- ].filter(seg => seg.val > 0);
892
- let offset = 0;
893
- let paths = '';
894
- segments.forEach(seg => {
895
- const pct = seg.val / total;
896
- const dash = c * pct;
897
- const gap = c - dash;
898
- paths += `<circle cx="${cx}" cy="${cy}" r="${r}" fill="none" stroke="${seg.color}" stroke-width="8" stroke-dasharray="${dash} ${gap}" stroke-dashoffset="${-offset}" opacity="0.85"/>`;
899
- offset += dash;
900
- });
901
- let legend = segments.map(seg => `<span class="chart-legend-item"><span class="chart-dot" style="background:${seg.color}"></span>${seg.label}: ${seg.val}</span>`).join('');
902
- container.innerHTML = `<svg width="80" height="80" viewBox="0 0 80 80" class="error-donut">${paths}<text x="${cx}" y="${cy}" text-anchor="middle" dominant-baseline="central" fill="var(--color-text-primary)" font-size="14" font-weight="700">${total}</text></svg><div class="chart-legend">${legend}</div>`;
903
- }
904
-
905
- /* ── Score History (Sparkline) ── */
906
- var _scoreHistory = [];
907
- function trackScore(score) {
908
- _scoreHistory.push(score);
909
- if (_scoreHistory.length > 20) _scoreHistory.shift();
910
- renderSparkline();
911
- }
912
- function renderSparkline() {
913
- const container = document.getElementById('score-sparkline');
914
- if (!container) return;
915
- if (_scoreHistory.length < 3) {
916
- container.innerHTML = '';
917
- return;
918
- }
919
- const w = 120, h = 30;
920
- const max = Math.max(..._scoreHistory, 100);
921
- const min = Math.min(..._scoreHistory, 0);
922
- const range = max - min || 1;
923
- const points = _scoreHistory.map((v, i) => {
924
- const x = (i / (_scoreHistory.length - 1)) * w;
925
- const y = h - ((v - min) / range) * h;
926
- return `${x},${y}`;
927
- }).join(' ');
928
- const polygonPoints = `0,${h} ${points} ${w},${h}`;
929
- container.innerHTML = `<svg width="${w}" height="${h}" class="sparkline">
930
- <polygon points="${polygonPoints}" fill="var(--color-primary)" opacity="0.15"/>
931
- <polyline points="${points}" fill="none" stroke="var(--color-primary)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
932
- </svg>`;
933
- }
 
95
  const idx = heights.indexOf(_currentLineHeight);
96
  _currentLineHeight = heights[(idx + 1) % heights.length];
97
  editor.style.lineHeight = _currentLineHeight;
98
+ // Show brief notification
99
  const btn = document.getElementById('fmt-line-height');
100
  if (btn) {
101
  btn.setAttribute('data-tooltip', 'ارتفاع السطر: ' + _currentLineHeight);
102
  }
103
  }
104
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
 
106
  /* ── Font family ── */
107
  function formatFont(fontName) {
 
308
  // Item 8: Color pickers
309
  initColorPicker('fmt-textcolor', 'foreColor', 'fmt-textcolor-bar');
310
  initColorPicker('fmt-highlight', 'hiliteColor', 'fmt-highlight-bar');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
  }
312
 
313
  /* ── Item 8: Color Picker ── */
 
443
  });
444
  });
445
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/js/renderer.js CHANGED
@@ -288,7 +288,6 @@ function overlaySuggestions(editor, suggestions) {
288
  const localEnd = Math.min(tn.node.length, end - tn.start);
289
 
290
  // Split the text node
291
- if (!tn.node || !tn.node.textContent) return;
292
  const textContent = tn.node.textContent;
293
  const beforeText = textContent.slice(0, localStart);
294
  const errorText = textContent.slice(localStart, localEnd);
 
288
  const localEnd = Math.min(tn.node.length, end - tn.start);
289
 
290
  // Split the text node
 
291
  const textContent = tn.node.textContent;
292
  const beforeText = textContent.slice(0, localStart);
293
  const errorText = textContent.slice(localStart, localEnd);
src/js/ui.js CHANGED
@@ -54,13 +54,6 @@ function updateWritingScore(spelling, grammar, punctuation) {
54
  const total = spelling + grammar + punctuation;
55
  sheetCount.textContent = total.toLocaleString('ar-EG');
56
  }
57
-
58
- // Hook: update error donut chart
59
- if (typeof renderErrorChart === 'function') renderErrorChart();
60
- // Hook: update error badge on write tab
61
- if (typeof updateErrorBadge === 'function') updateErrorBadge();
62
- // Hook: track score for sparkline
63
- if (typeof trackScore === 'function' && (spelling + grammar + punctuation) > 0) trackScore(score);
64
  }
65
 
66
  /**
@@ -96,7 +89,6 @@ function buildSuggestionCardHTML(suggestion, index) {
96
  return `
97
  <div class="suggestion-card" role="listitem" tabindex="0"
98
  data-suggestion-id="${suggestionId}"
99
- data-type="${suggestion.type}"
100
  aria-label="${label}: ${suggestion.original} إلى ${suggestion.correction}">
101
  <span class="suggestion-card-badge ${badgeClass}">${label}</span>
102
  <div class="suggestion-card-change">
 
54
  const total = spelling + grammar + punctuation;
55
  sheetCount.textContent = total.toLocaleString('ar-EG');
56
  }
 
 
 
 
 
 
 
57
  }
58
 
59
  /**
 
89
  return `
90
  <div class="suggestion-card" role="listitem" tabindex="0"
91
  data-suggestion-id="${suggestionId}"
 
92
  aria-label="${label}: ${suggestion.original} إلى ${suggestion.correction}">
93
  <span class="suggestion-card-badge ${badgeClass}">${label}</span>
94
  <div class="suggestion-card-change">