Nischal Subedi commited on
Commit
f8a1cae
·
1 Parent(s): 4ddd3a0
Files changed (1) hide show
  1. app.py +151 -361
app.py CHANGED
@@ -242,8 +242,7 @@ Answer:"""
242
  logging.error(f"Failed to load or process PDF '{pdf_path}': {str(e)}", exc_info=True)
243
  raise RuntimeError(f"Failed to process PDF '{pdf_path}': {e}") from e
244
 
245
- # --- GRADIO INTERFACE (NEW UI DESIGN) ---
246
- import gradio as gr
247
 
248
  def gradio_interface(self):
249
  def query_interface_wrapper(api_key: str, query: str, state: str) -> str:
@@ -275,7 +274,6 @@ Answer:"""
275
  print(f"DEBUG: Error loading states for selection: {e}")
276
  radio_choices = ["Error: Critical failure loading states"]
277
  initial_value_radio = None
278
-
279
  example_queries_base = [
280
  ["What are the rules for security deposit returns?", "California"],
281
  ["Can a landlord enter my apartment without notice?", "New York"],
@@ -293,285 +291,201 @@ Answer:"""
293
  example_queries.append(["What basic rights do tenants have?", "California"])
294
 
295
  custom_css = """
296
- /* Import modern fonts from Google Fonts */
297
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Poppins:wght@600;700&display=swap');
298
 
299
- /* Root variables for the single light orange theme */
300
  :root {
301
- --primary-color: #FF8C00; /* Orange for buttons and accents */
302
- --primary-hover: #E07B00; /* Darker orange for hover states */
303
- --background-page: #FFE8CC; /* Light orange background for the page */
304
- --background-card: #FFFFFF; /* White background for cards */
305
- --text-primary: #333333; /* Dark gray for primary text */
306
- --text-secondary: #666666; /* Lighter gray for secondary text */
307
- --border-color: #E5E5E5; /* Light gray for borders */
308
- --border-focus: #FF8C00; /* Orange for focused input borders */
309
  --shadow-sm: 0 2px 4px rgba(0,0,0,0.05);
310
- --shadow-md: 0 4px 8px rgba(0,0,0,0.1);
311
- --error-bg: #FFF0E0; /* Light orange for error background */
312
- --error-border: #FFD2B2; /* Slightly darker orange for error borders */
313
- --error-text: #E05C00; /* Orange for error text */
314
- --gradient-start: #FFDAB3; /* Lighter orange for gradient start */
315
- --gradient-end: #FFF5E6; /* Very light orange-cream for gradient end */
 
 
 
 
 
 
 
 
 
 
316
  }
317
 
318
- body, html {
319
- background-color: var(--background-page) !important;
 
320
  color: var(--text-primary) !important;
321
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;
322
- margin: 0;
323
- padding: 0;
324
  }
325
 
326
  .gradio-container {
327
  max-width: 1000px !important;
328
  margin: 2rem auto !important;
329
  padding: 2rem !important;
330
- background-color: var(--background-page) !important;
331
- box-shadow: none !important;
332
- color: var(--text-primary) !important;
333
- }
334
-
335
- .main-dashboard-container {
336
- display: flex !important;
337
- flex-direction: column !important;
338
- gap: 2rem !important; /* Increased spacing between sections */
339
  }
340
 
 
341
  .app-header-wrapper {
342
- background: linear-gradient(145deg, var(--gradient-start) 0%, var(--gradient-end) 100%) !important;
 
343
  border-radius: 12px !important;
344
- padding: 3rem 2rem !important;
345
  margin-bottom: 2rem !important;
346
- box-shadow: var(--shadow-md) !important;
347
  text-align: center !important;
348
- color: var(--text-primary) !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
349
  }
350
 
351
  .app-header-logo {
352
- font-size: 6rem !important;
 
353
  margin-bottom: 1rem !important;
354
- display: block !important;
355
- color: var(--primary-color) !important;
356
- animation: float-icon 3s ease-in-out infinite alternate;
357
  }
358
 
359
- @keyframes float-icon {
360
- 0% { transform: translateY(0px); }
361
- 50% { transform: translateY(-5px); }
362
- 100% { transform: translateY(0px); }
363
  }
364
 
365
  .app-header-title {
366
  font-family: 'Poppins', sans-serif !important;
367
- font-size: 2.5rem !important;
368
  font-weight: 700 !important;
369
- color: var(--text-primary) !important;
370
- margin: 0 0 0.5rem 0 !important;
371
  line-height: 1.2 !important;
 
 
 
372
  }
373
 
374
  .app-header-tagline {
375
- font-size: 1.1rem !important;
376
  color: var(--text-secondary) !important;
 
377
  font-weight: 400 !important;
378
- margin: 0 !important;
379
- max-width: 600px;
380
- margin: 0 auto;
 
 
 
 
 
 
381
  }
382
 
383
  .dashboard-card-section {
384
- background-color: var(--background-card) !important;
385
- border-radius: 12px !important;
 
386
  padding: 0 !important;
387
  box-shadow: var(--shadow-sm) !important;
388
  transition: transform 0.2s ease, box-shadow 0.2s ease !important;
389
- color: var(--text-primary) !important;
390
  }
391
 
392
  .dashboard-card-section:hover {
 
393
  box-shadow: var(--shadow-md) !important;
394
- transform: translateY(-2px) !important;
395
- }
396
-
397
- .full-width-center {
398
- display: flex !important;
399
- justify-content: center !important;
400
- align-items: center !important;
401
- width: 100% !important;
402
- flex-direction: column !important;
403
- background-color: transparent !important;
404
  }
405
 
406
  .section-title-gradient-bar {
407
- background: linear-gradient(145deg, var(--gradient-start) 0%, var(--gradient-end) 100%) !important;
408
- padding: 1rem 1.5rem !important;
409
- border-top-left-radius: 12px !important;
410
- border-top-right-radius: 12px !important;
411
- margin-bottom: 0 !important;
412
  text-align: center !important;
413
- box-sizing: border-box;
414
- width: 100%;
415
- color: var(--text-primary) !important;
416
  }
417
 
418
  .section-title {
419
  font-family: 'Poppins', sans-serif !important;
420
- font-size: 1.5rem !important;
421
  font-weight: 600 !important;
422
  color: var(--text-primary) !important;
423
  margin: 0 !important;
424
- line-height: 1.2 !important;
 
425
  }
426
 
427
  .dashboard-card-content-area {
428
  padding: 1.5rem !important;
429
- background-color: var(--background-card) !important;
430
- border-bottom-left-radius: 12px !important;
431
- border-bottom-right-radius: 12px !important;
432
- box-sizing: border-box;
433
- width: 100%;
434
- color: var(--text-primary) !important;
435
- }
436
-
437
- .dashboard-card-section p {
438
- line-height: 1.6 !important;
439
  color: var(--text-primary) !important;
440
- font-size: 1rem !important;
441
- text-align: left !important;
442
- margin: 0 !important;
443
- padding: 0 !important;
444
- }
445
-
446
- .dashboard-card-section strong, .dashboard-card-section b {
447
- font-weight: 600 !important;
448
- color: var(--primary-color) !important;
449
- }
450
-
451
- .gr-block, .gr-box, .gr-prose, .gr-form, .gr-panel,
452
- .gr-columns, .gr-column,
453
- .gradio-html, .gradio-markdown, .gradio-textbox, .gradio-radio, .gradio-button {
454
- background-color: transparent !important;
455
- color: var(--text-primary) !important;
456
- white-space: normal !important;
457
- overflow-wrap: break-word;
458
- word-break: break-word;
459
- }
460
-
461
- .gradio-textbox textarea,
462
- .gradio-textbox input,
463
- .gradio-radio label,
464
- .placeholder {
465
- background-color: #FFFFFF !important;
466
- color: var(--text-primary) !important;
467
- border-radius: 8px !important;
468
- box-shadow: var(--shadow-sm) !important;
469
- }
470
-
471
- .gradio-textbox {
472
- margin-bottom: 1rem !important;
473
  }
474
 
 
475
  .gradio-textbox textarea,
476
  .gradio-textbox input {
 
 
477
  border: 1px solid var(--border-color) !important;
478
  border-radius: 8px !important;
479
- padding: 0.75rem 1rem !important;
480
  font-size: 1rem !important;
481
- font-family: 'Inter', sans-serif !important;
482
- color: var(--text-primary) !important;
483
  transition: border-color 0.2s ease, box-shadow 0.2s ease !important;
484
  }
485
 
486
  .gradio-textbox textarea:focus,
487
  .gradio-textbox input:focus {
 
 
488
  outline: none !important;
489
- border-color: var(--border-focus) !important;
490
- box-shadow: 0 0 0 3px rgba(255, 140, 0, 0.1) !important;
491
- }
492
-
493
- .gradio-radio {
494
- padding: 0 !important;
495
- margin-top: 1rem !important;
496
- }
497
-
498
- .gradio-radio input[type="radio"] {
499
- display: none !important;
500
  }
501
 
502
  .gradio-radio label {
503
- display: flex !important;
504
- justify-content: center !important;
505
- align-items: center !important;
506
- padding: 0.75rem 1rem !important;
507
  border: 1px solid var(--border-color) !important;
508
  border-radius: 8px !important;
509
- color: var(--text-primary) !important;
510
- font-weight: 500 !important;
511
- cursor: pointer !important;
512
- transition: all 0.2s ease-out !important;
513
  margin: 0.25rem 0 !important;
514
- width: 100% !important;
515
- box-sizing: border-box !important;
516
- }
517
-
518
- .gradio-radio label span.text-lg {
519
- font-weight: 500 !important;
520
- color: var(--text-primary) !important;
521
- font-size: 1rem !important;
522
  }
523
 
524
  .gradio-radio label:hover {
525
- border-color: var(--primary-color) !important;
526
- box-shadow: var(--shadow-md) !important;
527
  }
528
 
529
  .gradio-radio input[type="radio"]:checked + label {
530
- background-color: var(--primary-color) !important;
531
- color: #FFFFFF !important;
532
- border-color: var(--primary-color) !important;
533
- box-shadow: var(--shadow-md) !important;
534
- }
535
-
536
- .gradio-radio input[type="radio"]:checked + label span.text-lg {
537
- color: #FFFFFF !important;
538
- }
539
-
540
- .gradio-textbox label,
541
- .gradio-radio > label {
542
- font-weight: 600 !important;
543
- color: var(--text-primary) !important;
544
- font-size: 1rem !important;
545
- margin-bottom: 0.5rem !important;
546
- display: block !important;
547
- text-align: left !important;
548
- }
549
-
550
- .gr-prose {
551
- font-size: 0.9rem !important;
552
- color: var(--text-secondary) !important;
553
- margin-top: 0.5rem !important;
554
- text-align: left !important;
555
- background-color: transparent !important;
556
- }
557
-
558
- .input-column {
559
- display: flex !important;
560
- flex-direction: column !important;
561
- gap: 1.5rem !important;
562
- margin-bottom: 1rem !important;
563
- }
564
-
565
- .input-field {
566
- flex: none !important;
567
- width: 100% !important;
568
- }
569
-
570
- .button-row {
571
- display: flex !important;
572
- gap: 1rem !important;
573
- justify-content: flex-end !important;
574
- margin-top: 1.5rem !important;
575
  }
576
 
577
  .gradio-button {
@@ -579,265 +493,142 @@ Answer:"""
579
  border-radius: 8px !important;
580
  font-weight: 600 !important;
581
  font-size: 1rem !important;
582
- font-family: 'Inter', sans-serif !important;
583
- transition: all 0.2s ease-out !important;
584
- cursor: pointer !important;
585
- border: none !important;
586
- text-align: center !important;
587
  }
588
 
589
  .gr-button-primary {
590
- background-color: var(--primary-color) !important;
591
- color: #FFFFFF !important;
592
- box-shadow: var(--shadow-sm) !important;
593
  }
594
 
595
  .gr-button-primary:hover {
596
- background-color: var(--primary-hover) !important;
597
- box-shadow: var(--shadow-md) !important;
598
- transform: translateY(-1px) !important;
599
- }
600
-
601
- .gr-button-primary:active {
602
- transform: translateY(0) !important;
603
- box-shadow: var(--shadow-sm) !important;
604
  }
605
 
606
  .gr-button-secondary {
607
- background-color: #F5F5F5 !important;
608
  color: var(--text-primary) !important;
609
  border: 1px solid var(--border-color) !important;
610
  }
611
 
612
  .gr-button-secondary:hover {
613
- background-color: #E5E5E5 !important;
614
- border-color: var(--primary-color) !important;
615
- transform: translateY(-1px) !important;
616
- }
617
-
618
- .gr-button-secondary:active {
619
- transform: translateY(0) !important;
620
- box-shadow: none !important;
621
  }
622
 
 
623
  .output-content-wrapper {
624
- background-color: #FFFFFF !important;
 
625
  border-radius: 8px !important;
626
  padding: 1.5rem !important;
627
- min-height: 120px !important;
628
  color: var(--text-primary) !important;
629
- display: flex;
630
- flex-direction: column;
631
- justify-content: center;
632
- align-items: center;
633
- box-shadow: var(--shadow-sm) !important;
634
  }
635
 
636
  .animated-output-content {
637
- opacity: 0;
638
- animation: fadeInAndSlideUp 0.5s ease-out forwards;
639
- width: 100%;
640
- white-space: pre-wrap;
641
- overflow-wrap: break-word;
642
- word-break: break-word;
643
- text-align: left !important;
644
  color: var(--text-primary) !important;
645
  }
646
 
647
- @keyframes fadeInAndSlideUp {
648
- from { opacity: 0; transform: translateY(10px); }
649
- to { opacity: 1; transform: translateY(0); }
650
  }
651
 
652
  .response-header {
653
- font-size: 1.2rem !important;
654
  font-weight: 600 !important;
655
- color: var(--primary-color) !important;
656
  margin-bottom: 0.75rem !important;
657
  display: flex !important;
658
  align-items: center !important;
659
  gap: 0.5rem !important;
660
- text-align: left !important;
661
- width: 100%;
662
  }
663
 
664
  .response-icon {
665
- font-size: 1.3rem !important;
666
- color: var(--primary-color) !important;
667
  }
668
 
669
  .divider {
670
  border: none !important;
671
- border-top: 1px solid var(--border-color) !important;
672
  margin: 1rem 0 !important;
673
  }
674
 
675
  .error-message {
676
  background-color: var(--error-bg) !important;
677
- border: 1px solid var(--error-border) !important;
678
  color: var(--error-text) !important;
679
  padding: 1rem !important;
680
  border-radius: 8px !important;
681
  display: flex !important;
682
- align-items: flex-start !important;
683
  gap: 0.5rem !important;
684
- font-size: 0.9rem !important;
685
- font-weight: 500 !important;
686
- line-height: 1.5 !important;
687
- text-align: left !important;
688
- width: 100%;
689
- box-sizing: border-box;
690
- }
691
-
692
- .error-message a {
693
- color: var(--error-text) !important;
694
- text-decoration: underline !important;
695
  }
696
 
697
  .error-icon {
698
  font-size: 1.2rem !important;
699
- line-height: 1 !important;
700
- margin-top: 0.1rem !important;
701
  }
702
 
703
  .placeholder {
704
- background-color: #FFFFFF !important;
705
- border: 1px dashed var(--border-color) !important;
706
- border-radius: 8px !important;
707
- padding: 2rem 1.5rem !important;
708
- text-align: center !important;
709
  color: var(--text-secondary) !important;
710
  font-style: italic !important;
711
- font-size: 1rem !important;
712
- width: 100%;
713
- box-sizing: border-box;
714
- }
715
-
716
- .examples-section .gr-samples-table {
717
- border: 1px solid var(--border-color) !important;
718
- border-radius: 8px !important;
719
- overflow: hidden !important;
720
- margin-top: 1rem !important;
721
- }
722
-
723
- .examples-section .gr-samples-table th,
724
- .examples-section .gr-samples-table td {
725
- padding: 0.75rem 1rem !important;
726
- border: none !important;
727
- font-size: 0.95rem !important;
728
- text-align: left !important;
729
- color: var(--text-primary) !important;
730
- }
731
-
732
- .examples-section .gr-samples-table th {
733
- background-color: #F5F5F5 !important;
734
- font-weight: 600 !important;
735
- color: var(--text-primary) !important;
736
- }
737
-
738
- .examples-section .gr-samples-table td {
739
- background-color: #FFFFFF !important;
740
- color: var(--text-primary) !important;
741
- border-top: 1px solid var(--border-color) !important;
742
- cursor: pointer !important;
743
- transition: background 0.2s ease !important;
744
- }
745
-
746
- .examples-section .gr-samples-table tr:hover td {
747
- background-color: #F9F9F9 !important;
748
- }
749
-
750
- .gr-examples .gr-label,
751
- .gr-examples .label-wrap,
752
- .gr-examples .gr-accordion-header {
753
- display: none !important;
754
  }
755
 
 
756
  .app-footer-wrapper {
757
- background-color: var(--background-card) !important;
 
758
  border-radius: 12px !important;
759
  padding: 1.5rem !important;
760
  margin-top: 2rem !important;
761
  text-align: center !important;
762
- color: var(--text-primary) !important;
763
- box-shadow: var(--shadow-sm) !important;
764
  }
765
 
766
  .app-footer p {
767
- margin: 0 !important;
768
- font-size: 0.9rem !important;
769
  color: var(--text-secondary) !important;
770
- line-height: 1.5 !important;
771
- background-color: transparent !important;
772
- text-align: center !important;
773
- }
774
-
775
- .app-footer strong, .app-footer b {
776
- font-weight: 600 !important;
777
- color: var(--primary-color) !important;
778
  }
779
 
780
  .app-footer a {
781
- color: var(--primary-color) !important;
782
  text-decoration: underline !important;
783
- font-weight: 500 !important;
784
  }
785
 
786
  .app-footer a:hover {
787
  text-decoration: none !important;
788
  }
789
 
 
790
  @media (max-width: 768px) {
791
  .gradio-container {
792
  padding: 1rem !important;
793
- margin: 1rem auto !important;
794
  }
795
-
796
  .app-header-title {
797
  font-size: 2rem !important;
798
  }
799
-
800
- .app-header-tagline {
801
- font-size: 1rem !important;
802
- }
803
-
804
  .section-title {
805
  font-size: 1.3rem !important;
806
  }
807
-
808
- .input-column {
809
- flex-direction: column !important;
810
- }
811
-
812
- .button-row {
813
- flex-direction: column !important;
814
- gap: 0.75rem !important;
815
- }
816
-
817
  .gradio-button {
818
  width: 100% !important;
819
  }
820
-
821
- .section-title-gradient-bar {
822
- padding: 0.75rem 1rem !important;
823
- }
824
-
825
- .dashboard-card-content-area {
826
- padding: 1rem !important;
827
- }
828
-
829
- .output-content-wrapper {
830
- min-height: 100px !important;
831
- }
832
-
833
- .placeholder {
834
- padding: 1.5rem 1rem !important;
835
- font-size: 0.9rem !important;
836
- }
837
  }
838
  """
839
 
840
- with gr.Blocks(css=custom_css, title="Landlord-Tenant Rights Assistant") as demo:
 
 
 
 
 
 
 
841
  with gr.Group(elem_classes="app-header-wrapper"):
842
  gr.Markdown(
843
  """
@@ -930,7 +721,7 @@ Answer:"""
930
  <style>
931
  .custom-link {{
932
  font-weight: bold !important;
933
- color: var(--primary-color) !important;
934
  text-decoration: underline;
935
  }}
936
  </style>
@@ -945,7 +736,7 @@ Answer:"""
945
  outputs=output,
946
  api_name="submit_query"
947
  )
948
-
949
  clear_button.click(
950
  fn=lambda: (
951
  "", "", initial_value_radio, "<div class='placeholder'>Inputs cleared. Ready for your next question.</div>"
@@ -955,7 +746,6 @@ Answer:"""
955
  )
956
 
957
  return demo
958
-
959
  # --- Main Execution Block (UNCHANGED from original logic) ---
960
  if __name__ == "__main__":
961
  logging.info("Starting Landlord-Tenant Rights Bot application...")
 
242
  logging.error(f"Failed to load or process PDF '{pdf_path}': {str(e)}", exc_info=True)
243
  raise RuntimeError(f"Failed to process PDF '{pdf_path}': {e}") from e
244
 
245
+
 
246
 
247
  def gradio_interface(self):
248
  def query_interface_wrapper(api_key: str, query: str, state: str) -> str:
 
274
  print(f"DEBUG: Error loading states for selection: {e}")
275
  radio_choices = ["Error: Critical failure loading states"]
276
  initial_value_radio = None
 
277
  example_queries_base = [
278
  ["What are the rules for security deposit returns?", "California"],
279
  ["Can a landlord enter my apartment without notice?", "New York"],
 
291
  example_queries.append(["What basic rights do tenants have?", "California"])
292
 
293
  custom_css = """
294
+ /* Import modern fonts */
295
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Poppins:wght@600;700;800&display=swap');
296
 
297
+ /* Define custom properties for light and dark themes */
298
  :root {
299
+ --background-primary: #FAFAFA;
300
+ --background-secondary: #F1F5F9;
301
+ --text-primary: #2D3748;
302
+ --text-secondary: #718096;
303
+ --title-color: #1A1A1A;
304
+ --accent-primary: #2C7A7B;
305
+ --accent-hover: #234E52;
306
+ --border-color: #E2E8F0;
307
  --shadow-sm: 0 2px 4px rgba(0,0,0,0.05);
308
+ --shadow-md: 0 4px 12px rgba(0,0,0,0.1);
309
+ --error-bg: #FEE2E2;
310
+ --error-text: #DC2626;
311
+ }
312
+
313
+ /* Dark theme variables */
314
+ @media (prefers-color-scheme: dark) {
315
+ :root {
316
+ --background-primary: #1A1A1A;
317
+ --background-secondary: #2D3748;
318
+ --text-primary: #D1D5DB;
319
+ --text-secondary: #A0AEC0;
320
+ --title-color: #E5E5E5;
321
+ --border-color: #4A5568;
322
+ --error-bg: #7F1D1D;
323
+ }
324
  }
325
 
326
+ /* Base styles */
327
+ html, body, .gradio-container {
328
+ background-color: var(--background-primary) !important;
329
  color: var(--text-primary) !important;
330
+ font-family: 'Inter', sans-serif !important;
331
+ margin: 0 !important;
332
+ padding: 0 !important;
333
  }
334
 
335
  .gradio-container {
336
  max-width: 1000px !important;
337
  margin: 2rem auto !important;
338
  padding: 2rem !important;
339
+ border-radius: 12px !important;
340
+ background-color: var(--background-primary) !important;
341
+ box-shadow: var(--shadow-md) !important;
 
 
 
 
 
 
342
  }
343
 
344
+ /* Header Section */
345
  .app-header-wrapper {
346
+ background: linear-gradient(135deg, var(--background-secondary), var(--background-primary)) !important;
347
+ border: 1px solid var(--border-color) !important;
348
  border-radius: 12px !important;
349
+ padding: 2rem !important;
350
  margin-bottom: 2rem !important;
351
+ position: relative;
352
  text-align: center !important;
353
+ box-shadow: var(--shadow-sm) !important;
354
+ overflow: hidden;
355
+ }
356
+
357
+ .app-header-wrapper::before {
358
+ content: '';
359
+ position: absolute;
360
+ top: 0;
361
+ left: 0;
362
+ width: 100%;
363
+ height: 100%;
364
+ background: radial-gradient(circle at top left, rgba(44, 122, 123, 0.2), transparent 70%);
365
+ z-index: 0;
366
+ opacity: 0.8;
367
  }
368
 
369
  .app-header-logo {
370
+ font-size: 5rem !important;
371
+ color: var(--accent-primary) !important;
372
  margin-bottom: 1rem !important;
373
+ position: relative;
374
+ z-index: 1;
375
+ animation: bounce 2s infinite ease-in-out;
376
  }
377
 
378
+ @keyframes bounce {
379
+ 0%, 100% { transform: translateY(0); }
380
+ 50% { transform: translateY(-10px); }
 
381
  }
382
 
383
  .app-header-title {
384
  font-family: 'Poppins', sans-serif !important;
385
+ font-size: 2.8rem !important;
386
  font-weight: 700 !important;
387
+ color: var(--title-color) !important; /* Ensure high contrast with background */
388
+ margin: 0 !important;
389
  line-height: 1.2 !important;
390
+ text-shadow: 1px 1px 2px rgba(0,0,0,0.1) !important;
391
+ position: relative;
392
+ z-index: 1;
393
  }
394
 
395
  .app-header-tagline {
396
+ font-size: 1.2rem !important;
397
  color: var(--text-secondary) !important;
398
+ margin-top: 0.5rem !important;
399
  font-weight: 400 !important;
400
+ position: relative;
401
+ z-index: 1;
402
+ }
403
+
404
+ /* Main Dashboard Layout */
405
+ .main-dashboard-container {
406
+ display: flex !important;
407
+ flex-direction: column !important;
408
+ gap: 1.5rem !important;
409
  }
410
 
411
  .dashboard-card-section {
412
+ background-color: var(--background-primary) !important;
413
+ border: 1px solid var(--border-color) !important;
414
+ border-radius: 10px !important;
415
  padding: 0 !important;
416
  box-shadow: var(--shadow-sm) !important;
417
  transition: transform 0.2s ease, box-shadow 0.2s ease !important;
 
418
  }
419
 
420
  .dashboard-card-section:hover {
421
+ transform: translateY(-3px) !important;
422
  box-shadow: var(--shadow-md) !important;
 
 
 
 
 
 
 
 
 
 
423
  }
424
 
425
  .section-title-gradient-bar {
426
+ background-color: var(--background-secondary) !important;
427
+ padding: 1rem !important;
428
+ border-top-left-radius: 10px !important;
429
+ border-top-right-radius: 10px !important;
 
430
  text-align: center !important;
 
 
 
431
  }
432
 
433
  .section-title {
434
  font-family: 'Poppins', sans-serif !important;
435
+ font-size: 1.6rem !important;
436
  font-weight: 600 !important;
437
  color: var(--text-primary) !important;
438
  margin: 0 !important;
439
+ border-bottom: 2px solid var(--accent-primary) !important;
440
+ display: inline-block !important;
441
  }
442
 
443
  .dashboard-card-content-area {
444
  padding: 1.5rem !important;
445
+ background-color: var(--background-primary) !important;
 
 
 
 
 
 
 
 
 
446
  color: var(--text-primary) !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
447
  }
448
 
449
+ /* Input and Form Elements */
450
  .gradio-textbox textarea,
451
  .gradio-textbox input {
452
+ background-color: var(--background-primary) !important;
453
+ color: var(--text-primary) !important;
454
  border: 1px solid var(--border-color) !important;
455
  border-radius: 8px !important;
456
+ padding: 0.75rem !important;
457
  font-size: 1rem !important;
458
+ box-shadow: var(--shadow-sm) !important;
 
459
  transition: border-color 0.2s ease, box-shadow 0.2s ease !important;
460
  }
461
 
462
  .gradio-textbox textarea:focus,
463
  .gradio-textbox input:focus {
464
+ border-color: var(--accent-primary) !important;
465
+ box-shadow: 0 0 0 3px rgba(44, 122, 123, 0.2) !important;
466
  outline: none !important;
 
 
 
 
 
 
 
 
 
 
 
467
  }
468
 
469
  .gradio-radio label {
470
+ background-color: var(--background-primary) !important;
471
+ color: var(--text-primary) !important;
 
 
472
  border: 1px solid var(--border-color) !important;
473
  border-radius: 8px !important;
474
+ padding: 0.75rem !important;
 
 
 
475
  margin: 0.25rem 0 !important;
476
+ cursor: pointer !important;
477
+ transition: all 0.2s ease !important;
 
 
 
 
 
 
478
  }
479
 
480
  .gradio-radio label:hover {
481
+ border-color: var(--accent-primary) !important;
482
+ background-color: var(--background-secondary) !important;
483
  }
484
 
485
  .gradio-radio input[type="radio"]:checked + label {
486
+ background-color: var(--accent-primary) !important;
487
+ color: white !important;
488
+ border-color: var(--accent-hover) !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
489
  }
490
 
491
  .gradio-button {
 
493
  border-radius: 8px !important;
494
  font-weight: 600 !important;
495
  font-size: 1rem !important;
496
+ transition: all 0.2s ease !important;
 
 
 
 
497
  }
498
 
499
  .gr-button-primary {
500
+ background-color: var(--accent-primary) !important;
501
+ color: white !important;
502
+ border: none !important;
503
  }
504
 
505
  .gr-button-primary:hover {
506
+ background-color: var(--accent-hover) !important;
507
+ transform: translateY(-2px) !important;
 
 
 
 
 
 
508
  }
509
 
510
  .gr-button-secondary {
511
+ background-color: transparent !important;
512
  color: var(--text-primary) !important;
513
  border: 1px solid var(--border-color) !important;
514
  }
515
 
516
  .gr-button-secondary:hover {
517
+ background-color: var(--background-secondary) !important;
518
+ border-color: var(--accent-primary) !important;
 
 
 
 
 
 
519
  }
520
 
521
+ /* Output and Error Messages */
522
  .output-content-wrapper {
523
+ background-color: var(--background-primary) !important;
524
+ border: 1px solid var(--border-color) !important;
525
  border-radius: 8px !important;
526
  padding: 1.5rem !important;
527
+ min-height: 150px !important;
528
  color: var(--text-primary) !important;
 
 
 
 
 
529
  }
530
 
531
  .animated-output-content {
532
+ animation: fadeIn 0.5s ease-out forwards;
 
 
 
 
 
 
533
  color: var(--text-primary) !important;
534
  }
535
 
536
+ @keyframes fadeIn {
537
+ from { opacity: 0; }
538
+ to { opacity: 1; }
539
  }
540
 
541
  .response-header {
542
+ font-size: 1.3rem !important;
543
  font-weight: 600 !important;
544
+ color: var(--accent-primary) !important;
545
  margin-bottom: 0.75rem !important;
546
  display: flex !important;
547
  align-items: center !important;
548
  gap: 0.5rem !important;
 
 
549
  }
550
 
551
  .response-icon {
552
+ font-size: 1.5rem !important;
 
553
  }
554
 
555
  .divider {
556
  border: none !important;
557
+ border-top: 1px dashed var(--border-color) !important;
558
  margin: 1rem 0 !important;
559
  }
560
 
561
  .error-message {
562
  background-color: var(--error-bg) !important;
 
563
  color: var(--error-text) !important;
564
  padding: 1rem !important;
565
  border-radius: 8px !important;
566
  display: flex !important;
567
+ align-items: center !important;
568
  gap: 0.5rem !important;
 
 
 
 
 
 
 
 
 
 
 
569
  }
570
 
571
  .error-icon {
572
  font-size: 1.2rem !important;
 
 
573
  }
574
 
575
  .placeholder {
 
 
 
 
 
576
  color: var(--text-secondary) !important;
577
  font-style: italic !important;
578
+ text-align: center !important;
579
+ padding: 2rem !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
580
  }
581
 
582
+ /* Footer */
583
  .app-footer-wrapper {
584
+ background: linear-gradient(135deg, var(--background-primary), var(--background-secondary)) !important;
585
+ border: 1px solid var(--border-color) !important;
586
  border-radius: 12px !important;
587
  padding: 1.5rem !important;
588
  margin-top: 2rem !important;
589
  text-align: center !important;
 
 
590
  }
591
 
592
  .app-footer p {
 
 
593
  color: var(--text-secondary) !important;
594
+ font-size: 0.9rem !important;
 
 
 
 
 
 
 
595
  }
596
 
597
  .app-footer a {
598
+ color: var(--accent-primary) !important;
599
  text-decoration: underline !important;
 
600
  }
601
 
602
  .app-footer a:hover {
603
  text-decoration: none !important;
604
  }
605
 
606
+ /* Responsive Design */
607
  @media (max-width: 768px) {
608
  .gradio-container {
609
  padding: 1rem !important;
610
+ margin: 1rem !important;
611
  }
 
612
  .app-header-title {
613
  font-size: 2rem !important;
614
  }
 
 
 
 
 
615
  .section-title {
616
  font-size: 1.3rem !important;
617
  }
 
 
 
 
 
 
 
 
 
 
618
  .gradio-button {
619
  width: 100% !important;
620
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
621
  }
622
  """
623
 
624
+ # Use a professional Gradio theme with custom hues
625
+ custom_theme = gr.themes.Soft(
626
+ primary_hue="teal",
627
+ secondary_hue="gray",
628
+ neutral_hue="stone"
629
+ )
630
+
631
+ with gr.Blocks(css=custom_css, theme=custom_theme, title="Landlord-Tenant Rights Assistant") as demo:
632
  with gr.Group(elem_classes="app-header-wrapper"):
633
  gr.Markdown(
634
  """
 
721
  <style>
722
  .custom-link {{
723
  font-weight: bold !important;
724
+ color: var(--accent-primary) !important;
725
  text-decoration: underline;
726
  }}
727
  </style>
 
736
  outputs=output,
737
  api_name="submit_query"
738
  )
739
+
740
  clear_button.click(
741
  fn=lambda: (
742
  "", "", initial_value_radio, "<div class='placeholder'>Inputs cleared. Ready for your next question.</div>"
 
746
  )
747
 
748
  return demo
 
749
  # --- Main Execution Block (UNCHANGED from original logic) ---
750
  if __name__ == "__main__":
751
  logging.info("Starting Landlord-Tenant Rights Bot application...")