Nischal Subedi commited on
Commit
6c9ad73
·
1 Parent(s): 728d3ad
Files changed (1) hide show
  1. app.py +380 -311
app.py CHANGED
@@ -263,7 +263,7 @@ Answer:"""
263
  return answer
264
  else:
265
  # Wrap successful response in a div with an animation class
266
- formatted_response_content = f"<div class='response-header'><span class='response-icon'>📋</span>Legal Analysis for {state}</div><hr class='divider'>{answer}"
267
  return f"<div class='animated-output-content'>{formatted_response_content}</div>"
268
 
269
  try:
@@ -279,6 +279,7 @@ Answer:"""
279
  radio_choices = ["Error: Critical failure loading states"]
280
  initial_value_radio = radio_choices[0]
281
 
 
282
  # Define example queries, filtering based on available states
283
  example_queries_base = [
284
  ["What are the rules for security deposit returns?", "California"],
@@ -299,587 +300,655 @@ Answer:"""
299
  else: # Fallback if states list is problematic (e.g., empty or error)
300
  example_queries.append(["What basic rights do tenants have?", "California"])
301
 
302
- # Professional custom CSS with refined design
 
303
  custom_css = """
304
- /* Import professional fonts */
305
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Playfair+Display:wght@600;700&display=swap');
306
 
307
- /* Professional color palette with refined oranges and neutrals */
308
  :root {
309
- --primary-color: #D97706; /* Refined amber-orange */
310
- --primary-hover: #B45309; /* Deeper amber for hover */
311
- --primary-light: #FEF3C7; /* Very light amber for backgrounds */
312
- --secondary-color: #6B7280; /* Professional gray */
313
- --accent-color: #0F172A; /* Deep slate for text */
314
-
315
- --background-primary: #FFFFFF; /* Pure white for cards */
316
- --background-secondary: #F8FAFC; /* Very light gray for page background */
317
- --background-tertiary: #F1F5F9; /* Slightly darker for subtle contrast */
318
-
319
- --text-primary: #0F172A; /* Deep slate for primary text */
320
- --text-secondary: #475569; /* Medium slate for secondary text */
321
- --text-muted: #64748B; /* Lighter slate for muted text */
322
-
323
- --border-color: #E2E8F0; /* Light gray for borders */
324
- --border-focus: #D97706; /* Primary color for focus states */
325
- --border-subtle: #F1F5F9; /* Very subtle border */
326
-
327
- --shadow-xs: 0 1px 2px 0 rgba(0,0,0,0.05);
328
- --shadow-sm: 0 1px 3px 0 rgba(0,0,0,0.1), 0 1px 2px -1px rgba(0,0,0,0.1);
329
- --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -2px rgba(0,0,0,0.1);
330
- --shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1);
331
- --shadow-xl: 0 20px 25px -5px rgba(0,0,0,0.1), 0 8px 10px -6px rgba(0,0,0,0.1);
332
-
333
- --error-bg: #FEF2F2; /* Light red background */
334
- --error-border: #FECACA; /* Light red border */
335
- --error-text: #DC2626; /* Strong red text */
336
-
337
- --success-bg: #F0FDF4; /* Light green background */
338
- --success-border: #BBF7D0; /* Light green border */
339
- --success-text: #16A34A; /* Strong green text */
340
  }
341
-
342
- /* Base styling */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
343
  body, html {
344
  background-color: var(--background-secondary) !important;
345
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;
346
  }
347
 
348
- /* Main container with professional spacing */
349
  .gradio-container {
350
- max-width: 1000px !important;
351
- margin: 0 auto !important;
352
- padding: 2rem !important;
353
- background-color: var(--background-secondary) !important;
 
 
 
 
 
 
354
  }
355
 
356
- /* Professional header with subtle elegance */
357
  .app-header-wrapper {
358
- background: linear-gradient(135deg, var(--background-primary) 0%, var(--primary-light) 100%) !important;
359
- border: 1px solid var(--border-color) !important;
360
  border-radius: 16px !important;
361
- padding: 3rem 2rem !important;
362
- margin-bottom: 2rem !important;
363
- box-shadow: var(--shadow-sm) !important;
364
- position: relative !important;
365
- text-align: center !important;
366
- overflow: hidden !important;
367
  }
368
 
369
- .app-header-wrapper::before {
370
  content: '';
371
  position: absolute;
372
  top: 0;
373
  left: 0;
374
  width: 100%;
375
  height: 100%;
376
- background: radial-gradient(circle at 30% 20%, rgba(217, 119, 6, 0.03) 0%, transparent 50%),
377
- radial-gradient(circle at 70% 80%, rgba(217, 119, 6, 0.03) 0%, transparent 50%);
378
  z-index: 0;
 
379
  pointer-events: none;
380
  }
381
 
382
  .app-header-logo {
383
- font-size: 3.5rem !important;
384
- margin-bottom: 1rem !important;
385
- display: block !important;
386
- color: var(--primary-color) !important;
387
  position: relative;
388
- z-index: 1;
389
- filter: drop-shadow(0 2px 4px rgba(217, 119, 6, 0.1));
 
 
 
 
 
 
390
  }
391
 
392
  .app-header-title {
393
- font-family: 'Playfair Display', serif !important;
394
- font-size: 2.75rem !important;
395
- font-weight: 700 !important;
396
  color: var(--text-primary) !important;
397
- margin: 0 0 1rem 0 !important;
398
- line-height: 1.2 !important;
399
- letter-spacing: -0.02em !important;
400
  position: relative;
401
  z-index: 1;
 
 
402
  }
403
-
404
  .app-header-tagline {
405
- font-size: 1.125rem !important;
406
  color: var(--text-secondary) !important;
407
  font-weight: 400 !important;
408
  margin: 0 !important;
409
- max-width: 600px;
410
- margin: 0 auto !important;
411
  position: relative;
412
  z-index: 1;
413
  }
414
 
415
- /* Professional card sections */
416
  .main-dashboard-container {
417
  display: flex !important;
418
  flex-direction: column !important;
419
- gap: 1.5rem !important;
420
  }
421
-
422
  .dashboard-card-section {
423
- background-color: var(--background-primary) !important;
424
- border: 1px solid var(--border-color) !important;
425
  border-radius: 12px !important;
426
- padding: 2rem !important;
427
- box-shadow: var(--shadow-sm) !important;
428
- transition: all 0.2s ease !important;
 
429
  }
430
-
431
  .dashboard-card-section:hover {
432
  box-shadow: var(--shadow-md) !important;
433
- transform: translateY(-1px) !important;
434
  }
435
 
436
- /* Professional typography for section titles */
437
- .section-title {
438
- font-family: 'Playfair Display', serif !important;
439
- font-size: 1.5rem !important;
440
- font-weight: 700 !important;
 
 
 
 
 
 
 
 
 
441
  color: var(--text-primary) !important;
442
- margin: 0 0 1.5rem 0 !important;
443
  padding-bottom: 0.75rem !important;
444
- border-bottom: 2px solid var(--primary-light) !important;
445
- text-align: center !important;
446
- position: relative !important;
 
 
 
 
447
  }
448
-
449
- .section-title::after {
450
- content: '';
451
- position: absolute;
452
- bottom: -2px;
453
- left: 50%;
454
- transform: translateX(-50%);
455
- width: 60px;
456
- height: 2px;
457
- background-color: var(--primary-color);
458
- border-radius: 1px;
459
  }
460
 
461
- /* Professional input styling */
 
 
 
462
  .gradio-textbox textarea,
463
  .gradio-textbox input {
464
- background-color: var(--background-primary) !important;
465
- border: 1px solid var(--border-color) !important;
466
  border-radius: 8px !important;
467
- padding: 0.875rem 1rem !important;
468
- font-size: 0.95rem !important;
469
  font-family: 'Inter', sans-serif !important;
470
- color: var(--text-primary) !important;
471
- transition: all 0.2s ease !important;
472
- box-shadow: var(--shadow-xs) !important;
473
  }
474
-
475
  .gradio-textbox textarea:focus,
476
  .gradio-textbox input:focus {
477
  outline: none !important;
478
- border-color: var(--border-focus) !important;
479
- box-shadow: 0 0 0 3px rgba(217, 119, 6, 0.1) !important;
480
  }
481
 
482
- /* Professional radio button styling */
483
  .gradio-radio {
484
- padding: 0 !important;
485
- margin-top: 0.5rem !important;
486
  }
487
-
488
- .gradio-radio .gr-radio-input {
489
  display: none !important;
490
  }
491
 
492
  .gradio-radio label {
493
- display: flex !important;
494
- justify-content: center !important;
 
495
  align-items: center !important;
496
  padding: 0.75rem 1rem !important;
497
- border: 1px solid var(--border-color) !important;
498
  border-radius: 8px !important;
499
- background-color: var(--background-primary) !important;
500
  color: var(--text-primary) !important;
501
  font-weight: 500 !important;
502
  cursor: pointer !important;
503
- transition: all 0.2s ease !important;
504
- box-shadow: var(--shadow-xs) !important;
505
- margin: 0.25rem 0 !important;
506
- width: 100% !important;
507
- box-sizing: border-box !important;
508
  }
509
 
 
 
 
 
 
 
 
 
510
  .gradio-radio label:hover {
511
- background-color: var(--background-tertiary) !important;
512
- border-color: var(--primary-color) !important;
513
- box-shadow: var(--shadow-sm) !important;
514
- transform: translateY(-1px) !important;
515
  }
516
 
517
- .gradio-radio label.selected {
518
- background-color: var(--primary-color) !important;
519
- color: white !important;
 
520
  border-color: var(--primary-hover) !important;
521
  box-shadow: var(--shadow-md) !important;
 
522
  }
523
-
524
- .gradio-radio label.selected span {
525
- color: white !important;
526
  }
 
 
 
 
 
527
 
528
- /* Professional label styling */
529
  .gradio-textbox label,
530
- .gradio-radio .gr-form-label {
531
- font-weight: 600 !important;
532
  color: var(--text-primary) !important;
533
- font-size: 0.95rem !important;
534
- margin-bottom: 0.5rem !important;
535
  display: block !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
536
  }
537
 
538
- /* Professional button styling */
539
  .button-row {
540
  display: flex !important;
541
- gap: 0.75rem !important;
542
- justify-content: flex-end !important;
543
- margin-top: 1.5rem !important;
544
  }
545
-
546
  .gradio-button {
547
- padding: 0.75rem 2rem !important;
548
- border-radius: 8px !important;
549
- font-weight: 600 !important;
550
- font-size: 0.95rem !important;
551
- transition: all 0.2s ease !important;
552
  cursor: pointer !important;
553
- border: 1px solid transparent !important;
554
- text-align: center !important;
555
  }
556
-
557
  .gr-button-primary {
558
- background-color: var(--primary-color) !important;
559
  color: white !important;
560
  box-shadow: var(--shadow-sm) !important;
561
  }
562
-
563
  .gr-button-primary:hover {
564
- background-color: var(--primary-hover) !important;
565
  box-shadow: var(--shadow-md) !important;
566
- transform: translateY(-1px) !important;
 
 
 
 
567
  }
568
-
569
  .gr-button-secondary {
570
- background-color: transparent !important;
571
- color: var(--text-secondary) !important;
572
  border-color: var(--border-color) !important;
573
  }
574
-
575
  .gr-button-secondary:hover {
576
- background-color: var(--background-tertiary) !important;
577
  border-color: var(--primary-color) !important;
578
- color: var(--text-primary) !important;
579
- transform: translateY(-1px) !important;
 
 
 
580
  }
581
 
582
- /* Professional output styling */
583
  .output-content-wrapper {
584
- background-color: var(--background-primary) !important;
585
- border: 1px solid var(--border-color) !important;
586
  border-radius: 8px !important;
587
  padding: 1.5rem !important;
588
- min-height: 120px !important;
589
  color: var(--text-primary) !important;
 
590
  display: flex;
591
  flex-direction: column;
592
- justify-content: center;
593
- align-items: center;
594
  }
595
-
596
  .animated-output-content {
597
  opacity: 0;
598
- animation: fadeInUp 0.5s ease-out forwards;
599
- width: 100%;
 
600
  white-space: pre-wrap;
601
  overflow-wrap: break-word;
602
  word-break: break-word;
603
- text-align: left !important;
604
  }
605
-
606
- @keyframes fadeInUp {
607
- from {
608
- opacity: 0;
609
- transform: translateY(10px);
610
- }
611
- to {
612
- opacity: 1;
613
- transform: translateY(0);
614
- }
615
  }
616
 
617
  .response-header {
618
- font-size: 1.25rem !important;
619
  font-weight: 700 !important;
620
- color: var(--primary-color) !important;
621
- margin-bottom: 1rem !important;
622
  display: flex !important;
623
  align-items: center !important;
624
- gap: 0.5rem !important;
625
- text-align: left !important;
626
- width: 100%;
627
- justify-content: flex-start;
628
  }
629
-
630
  .response-icon {
631
- font-size: 1.25rem !important;
632
  color: var(--primary-color) !important;
633
  }
634
-
635
  .divider {
636
  border: none !important;
637
- border-top: 1px solid var(--border-color) !important;
638
  margin: 1rem 0 !important;
639
  }
640
-
641
- /* Professional error styling */
642
  .error-message {
643
- background-color: var(--error-bg) !important;
644
- border: 1px solid var(--error-border) !important;
645
  color: var(--error-text) !important;
646
- padding: 1rem !important;
647
  border-radius: 8px !important;
648
  display: flex !important;
649
  align-items: flex-start !important;
650
- gap: 0.75rem !important;
651
  font-size: 0.95rem !important;
652
  font-weight: 500 !important;
653
- line-height: 1.5 !important;
654
- text-align: left !important;
655
- width: 100%;
656
- box-sizing: border-box;
657
  }
658
-
659
  .error-message a {
660
  color: var(--error-text) !important;
661
  text-decoration: underline !important;
662
  }
663
-
664
  .error-icon {
665
- font-size: 1.25rem !important;
666
  line-height: 1 !important;
667
  margin-top: 0.1rem !important;
668
  }
669
-
670
- /* Professional placeholder styling */
 
 
 
 
 
671
  .placeholder {
672
- background-color: var(--background-tertiary) !important;
673
- border: 1px dashed var(--border-color) !important;
674
  border-radius: 8px !important;
675
- padding: 2rem 1.5rem !important;
676
- text-align: center !important;
677
- color: var(--text-muted) !important;
678
  font-style: italic !important;
679
- font-size: 1rem !important;
680
- width: 100%;
681
- box-sizing: border-box;
682
  }
683
 
684
- /* Professional examples table */
685
  .examples-section .gr-samples-table {
686
- border: 1px solid var(--border-color) !important;
687
  border-radius: 8px !important;
688
  overflow: hidden !important;
689
  margin-top: 1rem !important;
690
- box-shadow: var(--shadow-xs) !important;
691
  }
692
-
693
  .examples-section .gr-samples-table th,
694
  .examples-section .gr-samples-table td {
695
- padding: 0.875rem !important;
696
  border: none !important;
697
  font-size: 0.95rem !important;
698
- text-align: left !important;
699
  }
700
-
701
  .examples-section .gr-samples-table th {
702
- background-color: var(--background-tertiary) !important;
703
- font-weight: 600 !important;
704
  color: var(--text-primary) !important;
705
  }
706
-
707
  .examples-section .gr-samples-table td {
708
- background-color: var(--background-primary) !important;
709
  color: var(--text-primary) !important;
710
- border-top: 1px solid var(--border-subtle) !important;
711
  cursor: pointer !important;
712
- transition: background-color 0.2s ease !important;
713
  }
714
-
715
  .examples-section .gr-samples-table tr:hover td {
716
- background-color: var(--background-tertiary) !important;
 
717
  }
718
-
719
- /* Professional footer */
 
 
 
 
 
 
720
  .app-footer-wrapper {
721
- background-color: var(--background-primary) !important;
722
- border: 1px solid var(--border-color) !important;
723
  border-radius: 12px !important;
724
- padding: 1.5rem !important;
725
- margin-top: 2rem !important;
726
- text-align: center !important;
727
- box-shadow: var(--shadow-xs) !important;
728
  }
729
-
730
- .app-footer-wrapper p {
731
- margin: 0.5rem 0 !important;
732
- font-size: 0.9rem !important;
733
  color: var(--text-secondary) !important;
734
  line-height: 1.6 !important;
735
  }
736
-
737
- .app-footer-wrapper a {
738
  color: var(--primary-color) !important;
739
  text-decoration: none !important;
740
  font-weight: 600 !important;
741
  }
742
-
743
- .app-footer-wrapper a:hover {
744
  text-decoration: underline !important;
745
  }
746
 
747
- /* Responsive design */
748
  @media (max-width: 768px) {
749
  .gradio-container {
750
  padding: 1rem !important;
751
  }
752
-
753
  .app-header-title {
754
- font-size: 2rem !important;
755
  }
756
-
757
  .app-header-tagline {
758
  font-size: 1rem !important;
759
  }
760
-
761
- .dashboard-card-section {
762
- padding: 1.5rem !important;
763
  }
764
-
765
  .input-row {
766
- flex-direction: column !important;
767
  }
768
-
769
  .button-row {
770
- flex-direction: column !important;
771
  }
772
-
773
  .gradio-button {
774
- width: 100% !important;
 
 
 
 
 
 
 
 
 
 
775
  }
776
  }
777
  """
778
 
779
- # Using gr.Blocks with custom CSS
780
  with gr.Blocks(css=custom_css, title="Landlord-Tenant Rights Assistant") as demo:
781
- # Professional Header
782
  with gr.Group(elem_classes="app-header-wrapper"):
 
 
783
  gr.Markdown(
784
  """
785
  <span class='app-header-logo'>⚖️</span>
786
  <h1 class='app-header-title'>Landlord-Tenant Rights Assistant</h1>
787
- <p class='app-header-tagline'>Professional Legal Research & Analysis Platform</p>
788
  """,
789
  elem_classes="full-width-center"
790
  )
791
 
792
- # Main Dashboard
793
  with gr.Column(elem_classes="main-dashboard-container"):
794
 
795
- # Welcome Section
796
  with gr.Group(elem_classes="dashboard-card-section"):
797
- gr.Markdown("<h3 class='section-title'>Welcome & Legal Disclaimer</h3>")
 
798
  gr.Markdown(
799
  """
800
- This professional legal research platform provides comprehensive, state-specific analysis of landlord-tenant laws. Our system delivers detailed responses grounded in legal authority and precedent.
801
 
802
- **Important Legal Disclaimer:** This platform provides informational content only and does not constitute legal advice. For specific legal matters, always consult with a qualified attorney licensed in your jurisdiction.
803
  """
804
  )
805
 
806
- # API Configuration
807
  with gr.Group(elem_classes="dashboard-card-section"):
808
- gr.Markdown("<h3 class='section-title'>API Configuration</h3>")
 
809
  api_key_input = gr.Textbox(
810
- label="OpenAI API Key",
811
- type="password",
812
- placeholder="Enter your OpenAI API key (sk-...)",
813
- info="Required for query processing. Obtain from: platform.openai.com/api-keys",
814
- lines=1
 
815
  )
816
 
817
- # Query Interface
818
  with gr.Group(elem_classes="dashboard-card-section"):
819
- gr.Markdown("<h3 class='section-title'>Legal Query Interface</h3>")
820
- with gr.Row(elem_classes="input-row"):
821
- with gr.Column(elem_classes="input-field", scale=3):
 
822
  query_input = gr.Textbox(
823
- label="Legal Question",
824
- placeholder="Enter your landlord-tenant law question here...",
825
  lines=4,
826
- max_lines=8
 
827
  )
828
- with gr.Column(elem_classes="input-field", scale=1):
829
  state_input = gr.Radio(
830
- label="Jurisdiction",
831
  choices=radio_choices,
832
- value=initial_value_radio
 
833
  )
834
- with gr.Row(elem_classes="button-row"):
835
- clear_button = gr.Button("Clear Form", variant="secondary")
836
- submit_button = gr.Button("Analyze Query", variant="primary")
837
 
838
- # Results Display
839
  with gr.Group(elem_classes="dashboard-card-section"):
840
- gr.Markdown("<h3 class='section-title'>Legal Analysis Results</h3>")
841
- output = gr.HTML(
842
- value="<div class='placeholder'>Your comprehensive legal analysis will appear here after submitting your query.</div>",
843
- elem_classes="output-content-wrapper"
 
844
  )
845
 
846
- # Example Queries
847
  with gr.Group(elem_classes="dashboard-card-section examples-section"):
848
- gr.Markdown("<h3 class='section-title'>Sample Legal Queries</h3>")
 
849
  if example_queries:
850
  gr.Examples(
851
  examples=example_queries,
852
  inputs=[query_input, state_input],
853
  examples_per_page=5,
854
- label=""
855
  )
856
  else:
857
- gr.Markdown("<div class='placeholder'>Sample queries are currently unavailable. Please ensure the legal database is properly configured.</div>")
858
 
859
- # Professional Footer
860
  with gr.Group(elem_classes="app-footer-wrapper"):
861
  gr.Markdown(
862
  """
863
- **Legal Notice:** This platform is designed for informational and research purposes only. It does not establish an attorney-client relationship and should not be relied upon as a substitute for professional legal counsel.
864
-
865
- **Platform Development:** Created by **Nischal Subedi** • [LinkedIn](https://www.linkedin.com/in/nischal1/) • [Professional Insights](https://datascientistinsights.substack.com/)
866
  """
867
  )
868
 
869
- # Event Handlers
870
  submit_button.click(
871
  fn=query_interface_wrapper,
872
  inputs=[api_key_input, query_input, state_input],
873
  outputs=output,
874
- api_name="submit_query"
875
  )
876
 
877
  clear_button.click(
878
  fn=lambda: (
879
- "",
880
- "",
881
- initial_value_radio,
882
- "<div class='placeholder'>Form cleared successfully. Ready for your next legal query.</div>"
883
  ),
884
  inputs=[],
885
  outputs=[api_key_input, query_input, state_input, output]
 
263
  return answer
264
  else:
265
  # Wrap successful response in a div with an animation class
266
+ formatted_response_content = f"<div class='response-header'><span class='response-icon'>📜</span>Response for {state}</div><hr class='divider'>{answer}"
267
  return f"<div class='animated-output-content'>{formatted_response_content}</div>"
268
 
269
  try:
 
279
  radio_choices = ["Error: Critical failure loading states"]
280
  initial_value_radio = radio_choices[0]
281
 
282
+
283
  # Define example queries, filtering based on available states
284
  example_queries_base = [
285
  ["What are the rules for security deposit returns?", "California"],
 
300
  else: # Fallback if states list is problematic (e.g., empty or error)
301
  example_queries.append(["What basic rights do tenants have?", "California"])
302
 
303
+
304
+ # Custom CSS for better UI design, clear boundaries, and text alignment for HuggingFace
305
  custom_css = """
306
+ /* Import legible fonts from Google Fonts */
307
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Poppins:wght@600;700;800&display=swap');
308
 
309
+ /* Root variables for consistent theming - adjusted for an inviting orange palette */
310
  :root {
311
+ --primary-color: #FF8C00; /* Darker Orange for buttons/accents */
312
+ --primary-hover: #E07B00; /* Slightly darker orange for hover */
313
+ --background-primary: #FFFFFF; /* Pure White for main cards, inputs, output area - NO GREY */
314
+ --background-secondary: #FFF5E0; /* Very light, warm cream for overall app background, table headers, placeholder */
315
+ --text-primary: #4A3C32; /* Dark warm brown/charcoal for main text */
316
+ --text-secondary: #8C7B6F; /* Muted warm gray/brown for secondary text */
317
+ --border-color: #DDC6AF; /* Light, desaturated orange-brown for borders */
318
+ --border-focus: #FF8C00; /* Focus color matches primary */
319
+ --shadow-sm: 0 1px 3px rgba(0,0,0,0.08);
320
+ --shadow-md: 0 4px 10px rgba(0,0,0,0.1);
321
+ --shadow-lg: 0 10px 20px rgba(0,0,0,0.15);
322
+ --error-bg: #FFF0E0; /* Light orange-pink for errors */
323
+ --error-border: #FFD2B2; /* Medium orange-pink for error borders */
324
+ --error-text: #E05C00; /* Darker, strong orange-red for error text */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
325
  }
326
+
327
+ /* Dark mode variables - for consistency if a dark mode toggle were present */
328
+ body.dark {
329
+ --primary-color: #FFA500; /* Bright orange for dark mode */
330
+ --primary-hover: #CC8400;
331
+ --background-primary: #2C2C2C; /* Dark charcoal */
332
+ --background-secondary: #1F1F1F; /* Even darker charcoal */
333
+ --text-primary: #F0F0F0;
334
+ --text-secondary: #B0B0B0;
335
+ --border-color: #555555;
336
+ --border-focus: #FFA500;
337
+ --error-bg: #400000;
338
+ --error-border: #800000;
339
+ --error-text: #FF6666;
340
+ }
341
+
342
+ /* Ensure the very outer body background is also set, overriding any Gradio defaults */
343
  body, html {
344
  background-color: var(--background-secondary) !important;
 
345
  }
346
 
347
+ /* Base container improvements */
348
  .gradio-container {
349
+ max-width: 900px !important; /* Slightly smaller for focused content */
350
+ margin: 0 auto !important; /* Center the whole app */
351
+ padding: 1.5rem !important;
352
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;
353
+ background-color: var(--background-secondary) !important; /* Overall background of the container */
354
+ box-shadow: none !important; /* Remove default gradio container shadow */
355
+ }
356
+ /* Ensure all main content sections have primary background */
357
+ .main-dashboard-container > * {
358
+ background-color: var(--background-primary) !important;
359
  }
360
 
361
+ /* Header styling - centered and prominent */
362
  .app-header-wrapper {
363
+ background-color: var(--background-primary) !important; /* Solid primary background, removed gradient */
364
+ border: 2px solid var(--border-color) !important;
365
  border-radius: 16px !important;
366
+ padding: 2.5rem 1.5rem !important; /* More vertical padding */
367
+ margin-bottom: 1.5rem !important;
368
+ box-shadow: var(--shadow-md) !important;
369
+ position: relative; /* For potential pseudo-element effects */
370
+ overflow: hidden; /* For any overflow animations */
371
+ text-align: center !important; /* Centers block content within the wrapper */
372
  }
373
 
374
+ .app-header-wrapper::before { /* Subtle background pattern for dynamism */
375
  content: '';
376
  position: absolute;
377
  top: 0;
378
  left: 0;
379
  width: 100%;
380
  height: 100%;
381
+ background: radial-gradient(circle at top left, rgba(255,140,0,0.1) 0%, transparent 40%), /* More orange tint, slightly more opaque */
382
+ radial-gradient(circle at bottom right, rgba(255,140,0,0.1) 0%, transparent 40%);
383
  z-index: 0;
384
+ opacity: 0.8;
385
  pointer-events: none;
386
  }
387
 
388
  .app-header-logo {
389
+ font-size: 5.5rem !important; /* Significantly larger icon */
390
+ margin-bottom: 0.75rem !important;
391
+ display: block !important;
392
+ color: var(--primary-color) !important; /* Theme color */
393
  position: relative;
394
+ z-index: 1; /* Bring icon to front of pseudo-element */
395
+ animation: float-icon 3s ease-in-out infinite alternate;
396
+ }
397
+ /* Keyframes for floating icon */
398
+ @keyframes float-icon {
399
+ 0% { transform: translateY(0px); }
400
+ 50% { transform: translateY(-5px); }
401
+ 100% { transform: translateY(0px); }
402
  }
403
 
404
  .app-header-title {
405
+ font-family: 'Poppins', sans-serif !important;
406
+ font-size: 3rem !important; /* Even larger title */
407
+ font-weight: 800 !important; /* Bolder */
408
  color: var(--text-primary) !important;
409
+ margin: 0 0 0.75rem 0 !important;
410
+ line-height: 1.1 !important;
411
+ letter-spacing: -0.03em !important; /* Tighter spacing */
412
  position: relative;
413
  z-index: 1;
414
+ display: inline-block; /* Essential for text-align: center on parent to work for this block */
415
+ max-width: 100%; /* Prevent overflow on smaller screens */
416
  }
 
417
  .app-header-tagline {
418
+ font-size: 1.25rem !important; /* Slightly larger tagline */
419
  color: var(--text-secondary) !important;
420
  font-weight: 400 !important;
421
  margin: 0 !important;
422
+ max-width: 700px; /* Constrain tagline width */
423
+ display: inline-block; /* Essential for text-align: center on parent to work for this block */
424
  position: relative;
425
  z-index: 1;
426
  }
427
 
428
+ /* Main container with consistent spacing */
429
  .main-dashboard-container {
430
  display: flex !important;
431
  flex-direction: column !important;
432
+ gap: 1.25rem !important; /* Consistent spacing between cards */
433
  }
434
+ /* Card sections with clear boundaries and subtle dynamic effects */
435
  .dashboard-card-section {
436
+ background-color: var(--background-primary) !important; /* Explicitly set background */
437
+ border: 2px solid var(--border-color) !important; /* Distinct border */
438
  border-radius: 12px !important;
439
+ padding: 1.75rem !important; /* Consistent padding */
440
+ box-shadow: var(--shadow-sm) !important; /* Subtle shadow */
441
+ transition: all 0.3s ease-out !important; /* Smoother transition */
442
+ cursor: default; /* Indicate not directly clickable (unless examples) */
443
  }
 
444
  .dashboard-card-section:hover {
445
  box-shadow: var(--shadow-md) !important;
446
+ transform: translateY(-3px) !important; /* More pronounced lift */
447
  }
448
 
449
+ /* NEW: Class for Markdown blocks to center their content */
450
+ .full-width-center {
451
+ display: flex !important;
452
+ justify-content: center !important;
453
+ align-items: center !important;
454
+ width: 100% !important;
455
+ flex-direction: column !important; /* Ensure content stacks vertically if needed */
456
+ }
457
+
458
+ /* Section titles (h3 inside markdown) */
459
+ .section-title { /* Renamed from sub-section-title for clarity */
460
+ font-family: 'Poppins', sans-serif !important;
461
+ font-size: 1.7rem !important; /* Slightly larger */
462
+ font-weight: 700 !important; /* Bolder */
463
  color: var(--text-primary) !important;
464
+ margin: 0 0 1.25rem 0 !important; /* More space below title */
465
  padding-bottom: 0.75rem !important;
466
+ border-bottom: 2px solid var(--border-color) !important; /* Underline effect */
467
+ display: block !important; /* Ensure it's a block-level element for proper width/border */
468
+ text-align: center !important; /* Ensure the text within the h3 is centered */
469
+ width: fit-content !important; /* Make it shrink-wrap its content */
470
+ margin-left: auto !important; /* Auto margins to center block-level element */
471
+ margin-right: auto !important;
472
+ letter-spacing: -0.01em !important;
473
  }
474
+
475
+ /* Specific styling for the welcome/disclaimer markdown content */
476
+ .dashboard-card-section p {
477
+ line-height: 1.7 !important;
478
+ color: var(--text-primary) !important;
479
+ font-size: 1rem !important;
480
+ text-align: left !important; /* Ensure content text is left-aligned */
481
+ }
482
+ .dashboard-card-section strong {
483
+ color: var(--primary-color) !important; /* Highlight strong text with primary color */
 
484
  }
485
 
486
+ /* Improved input styling with clear boundaries and focus */
487
+ .gradio-textbox {
488
+ margin-bottom: 0.75rem !important;
489
+ }
490
  .gradio-textbox textarea,
491
  .gradio-textbox input {
492
+ background-color: var(--background-primary) !important; /* Explicitly set background to primary cream */
493
+ border: 2px solid var(--border-color) !important; /* Clear border */
494
  border-radius: 8px !important;
495
+ padding: 0.85rem 1rem !important; /* Slightly more padding */
496
+ font-size: 0.98rem !important;
497
  font-family: 'Inter', sans-serif !important;
498
+ color: var(--text-primary) !important; /* Text color inside inputs */
499
+ transition: border-color 0.2s ease, box-shadow 0.2s ease !important; /* Smooth transitions */
500
+ box-shadow: var(--shadow-sm) !important;
501
  }
502
+ /* Focus styles for textboxes */
503
  .gradio-textbox textarea:focus,
504
  .gradio-textbox input:focus {
505
  outline: none !important;
506
+ border-color: var(--border-focus) !important; /* Distinct border on focus */
507
+ box-shadow: 0 0 0 4px rgba(255, 140, 0, 0.2) !important; /* Broader, softer glow on focus */
508
  }
509
 
510
+ /* Styling for the radio button group (state selection) */
511
  .gradio-radio {
512
+ padding: 0 !important; /* Remove any default padding */
513
+ margin-top: 0.5rem !important; /* Add a little space above */
514
  }
515
+ /* Hide default radio circle/dot */
516
+ .gradio-radio input[type="radio"] {
517
  display: none !important;
518
  }
519
 
520
  .gradio-radio label {
521
+ /* Style the clickable area for each radio option */
522
+ display: flex !important; /* Use flexbox for internal alignment */
523
+ justify-content: center !important; /* Center content horizontally */
524
  align-items: center !important;
525
  padding: 0.75rem 1rem !important;
526
+ border: 2px solid var(--border-color) !important;
527
  border-radius: 8px !important;
528
+ background-color: var(--background-primary) !important; /* Matches card background */
529
  color: var(--text-primary) !important;
530
  font-weight: 500 !important;
531
  cursor: pointer !important;
532
+ transition: all 0.2s ease-out !important;
533
+ box-shadow: var(--shadow-sm) !important;
534
+ margin: 0.25rem 0 !important; /* Small vertical margin between options */
535
+ width: 100% !important; /* Ensure options take full width of their column */
536
+ box-sizing: border-box !important; /* Include padding/border in width */
537
  }
538
 
539
+ /* Style the text/content within the radio label */
540
+ .gradio-radio label span.text-lg { /* Gradio uses text-lg for the label text by default */
541
+ font-weight: 600 !important; /* Make text bold */
542
+ color: var(--text-primary) !important;
543
+ font-size: 0.98rem !important; /* Match input text size */
544
+ }
545
+
546
+ /* Hover effect for radio options */
547
  .gradio-radio label:hover {
548
+ background-color: var(--background-secondary) !important; /* Slightly darker cream on hover */
549
+ border-color: var(--primary-color) !important; /* Highlight border with primary color */
550
+ box-shadow: var(--shadow-md) !important;
551
+ transform: translateY(-2px) !important;
552
  }
553
 
554
+ /* Selected state for radio options */
555
+ .gradio-radio input[type="radio"]:checked + label { /* Target label when its radio input is checked */
556
+ background-color: var(--primary-color) !important; /* Primary color for selected item */
557
+ color: white !important; /* White text on selected */
558
  border-color: var(--primary-hover) !important;
559
  box-shadow: var(--shadow-md) !important;
560
+ transform: translateY(-1px) !important;
561
  }
562
+ .gradio-radio input[type="radio"]:checked + label span.text-lg {
563
+ color: white !important; /* Ensure text is white when selected */
 
564
  }
565
+ /* Gradio's internal wrapper for radio buttons, ensure it doesn't add unwanted padding */
566
+ .gradio-radio .gr-form {
567
+ padding: 0 !important;
568
+ }
569
+
570
 
571
+ /* Label styling for better readability (for Query, State labels) */
572
  .gradio-textbox label,
573
+ .gradio-radio > label { /* Target the main label for the radio group */
574
+ font-weight: 600 !important; /* Bolder labels */
575
  color: var(--text-primary) !important;
576
+ font-size: 1rem !important;
577
+ margin-bottom: 0.6rem !important;
578
  display: block !important;
579
+ text-align: left !important; /* Ensure these labels are left-aligned */
580
+ }
581
+ /* Info text styling below inputs (e.g., for API Key) */
582
+ .gr-prose { /* This class is used by Gradio for info text */
583
+ font-size: 0.9rem !important;
584
+ color: var(--text-secondary) !important;
585
+ margin-top: 0.4rem !important; /* More space for info text */
586
+ text-align: left !important; /* Ensure info text is left aligned */
587
+ }
588
+ /* Input row layout improvements */
589
+ .input-row {
590
+ display: flex !important;
591
+ gap: 1.25rem !important; /* Consistent gap between query and state */
592
+ margin-bottom: 0.5rem !important;
593
+ }
594
+ .input-field {
595
+ flex: 1 !important;
596
  }
597
 
598
+ /* Button styling improvements with active state for dynamism */
599
  .button-row {
600
  display: flex !important;
601
+ gap: 1rem !important;
602
+ justify-content: flex-end !important; /* Align buttons to the right */
603
+ margin-top: 1.5rem !important; /* More space above buttons */
604
  }
 
605
  .gradio-button {
606
+ padding: 0.85rem 1.8rem !important; /* More padding for bigger buttons */
607
+ border-radius: 9px !important; /* Slightly more rounded */
608
+ font-weight: 600 !important; /* Bolder text */
609
+ font-size: 1rem !important;
610
+ transition: all 0.2s ease-out !important; /* Smooth transition for hover/active */
611
  cursor: pointer !important;
612
+ border: 2px solid transparent !important;
613
+ text-align: center !important; /* Ensure button text is centered */
614
  }
 
615
  .gr-button-primary {
616
+ background-color: var(--primary-color) !important; /* Explicitly set background */
617
  color: white !important;
618
  box-shadow: var(--shadow-sm) !important;
619
  }
 
620
  .gr-button-primary:hover {
621
+ background-color: var(--primary-hover) !important; /* Explicitly set background */
622
  box-shadow: var(--shadow-md) !important;
623
+ transform: translateY(-2px) !important; /* Subtle lift effect on hover */
624
+ }
625
+ .gr-button-primary:active { /* Press down effect on click */
626
+ transform: translateY(1px) !important;
627
+ box-shadow: none !important;
628
  }
 
629
  .gr-button-secondary {
630
+ background-color: transparent !important; /* Explicitly set background */
631
+ color: var(--text-primary) !important;
632
  border-color: var(--border-color) !important;
633
  }
 
634
  .gr-button-secondary:hover {
635
+ background-color: var(--background-secondary) !important; /* Explicitly set background */
636
  border-color: var(--primary-color) !important;
637
+ transform: translateY(-2px) !important;
638
+ }
639
+ .gr-button-secondary:active { /* Press down effect on click */
640
+ transform: translateY(1px) !important;
641
+ box-shadow: none !important;
642
  }
643
 
644
+ /* Output styling with clear boundaries and dynamic fade-in */
645
  .output-content-wrapper {
646
+ background-color: var(--background-primary) !important; /* Explicitly set background */
647
+ border: 2px solid var(--border-color) !important; /* Clear border */
648
  border-radius: 8px !important;
649
  padding: 1.5rem !important;
650
+ min-height: 150px !important; /* More space for output */
651
  color: var(--text-primary) !important;
652
+ /* Ensure the inner animated content fits well */
653
  display: flex;
654
  flex-direction: column;
655
+ justify-content: center; /* Center content vertically if small */
656
+ align-items: center; /* Center content horizontally if small */
657
  }
658
+ /* The div holding the actual response content, enabling fade-in animation */
659
  .animated-output-content {
660
  opacity: 0;
661
+ animation: fadeInAndSlideUp 0.7s ease-out forwards; /* More pronounced animation */
662
+ width: 100%; /* Take full width of parent */
663
+ /* Preserve formatting within the animated content */
664
  white-space: pre-wrap;
665
  overflow-wrap: break-word;
666
  word-break: break-word;
667
+ text-align: left !important; /* Ensure text is left-aligned within this div */
668
  }
669
+ @keyframes fadeInAndSlideUp {
670
+ from { opacity: 0; transform: translateY(15px); }
671
+ to { opacity: 1; transform: translateY(0); }
 
 
 
 
 
 
 
672
  }
673
 
674
  .response-header {
675
+ font-size: 1.3rem !important;
676
  font-weight: 700 !important;
677
+ color: var(--primary-color) !important; /* Matches primary color */
678
+ margin-bottom: 0.75rem !important;
679
  display: flex !important;
680
  align-items: center !important;
681
+ gap: 0.6rem !important;
682
+ text-align: left !important; /* Ensure header itself is not affected by parent centering */
683
+ width: 100%; /* Take full width */
684
+ justify-content: flex-start; /* Align content to the start */
685
  }
 
686
  .response-icon {
687
+ font-size: 1.5rem !important;
688
  color: var(--primary-color) !important;
689
  }
 
690
  .divider {
691
  border: none !important;
692
+ border-top: 1px dashed var(--border-color) !important; /* Dashed divider for visual separation */
693
  margin: 1rem 0 !important;
694
  }
695
+ /* Error message styling */
 
696
  .error-message {
697
+ background-color: var(--error-bg) !important; /* Explicitly set background */
698
+ border: 2px solid var(--error-border) !important;
699
  color: var(--error-text) !important;
700
+ padding: 1.25rem !important;
701
  border-radius: 8px !important;
702
  display: flex !important;
703
  align-items: flex-start !important;
704
+ gap: 0.8rem !important;
705
  font-size: 0.95rem !important;
706
  font-weight: 500 !important;
707
+ line-height: 1.6 !important;
708
+ text-align: left !important; /* Ensure error message text is left aligned */
709
+ width: 100%; /* Take full width of parent */
710
+ box-sizing: border-box; /* Include padding/border in width */
711
  }
 
712
  .error-message a {
713
  color: var(--error-text) !important;
714
  text-decoration: underline !important;
715
  }
 
716
  .error-icon {
717
+ font-size: 1.4rem !important;
718
  line-height: 1 !important;
719
  margin-top: 0.1rem !important;
720
  }
721
+ .error-details {
722
+ font-size: 0.85rem !important;
723
+ color: var(--error-text) !important;
724
+ margin-top: 0.5rem !important;
725
+ opacity: 0.8;
726
+ }
727
+ /* Placeholder styling for empty output */
728
  .placeholder {
729
+ background-color: var(--background-secondary) !important; /* Explicitly set background */
730
+ border: 2px dashed var(--border-color) !important;
731
  border-radius: 8px !important;
732
+ padding: 2.5rem 1.5rem !important;
733
+ text-align: center !important; /* Ensure placeholder text is centered */
734
+ color: var(--text-secondary) !important;
735
  font-style: italic !important;
736
+ font-size: 1.1rem !important;
737
+ width: 100%; /* Ensure it takes full width of parent */
738
+ box-sizing: border-box; /* Include padding/border in width */
739
  }
740
 
741
+ /* Examples table styling with dynamic hover */
742
  .examples-section .gr-samples-table {
743
+ border: 2px solid var(--border-color) !important;
744
  border-radius: 8px !important;
745
  overflow: hidden !important;
746
  margin-top: 1rem !important;
 
747
  }
 
748
  .examples-section .gr-samples-table th,
749
  .examples-section .gr-samples-table td {
750
+ padding: 0.9rem !important;
751
  border: none !important;
752
  font-size: 0.95rem !important;
753
+ text-align: left !important; /* Ensure example text is left-aligned */
754
  }
 
755
  .examples-section .gr-samples-table th {
756
+ background-color: var(--background-secondary) !important; /* Explicitly set background */
757
+ font-weight: 700 !important;
758
  color: var(--text-primary) !important;
759
  }
 
760
  .examples-section .gr-samples-table td {
761
+ background-color: var(--background-primary) !important; /* Explicitly set background */
762
  color: var(--text-primary) !important;
763
+ border-top: 1px solid var(--border-color) !important;
764
  cursor: pointer !important;
765
+ transition: background 0.2s ease, transform 0.1s ease !important; /* Smooth transitions */
766
  }
 
767
  .examples-section .gr-samples-table tr:hover td {
768
+ background-color: var(--background-secondary) !important; /* Explicitly set background */
769
+ transform: translateX(5px); /* Subtle slide on hover */
770
  }
771
+ /* Hide Gradio default elements for examples for cleaner look */
772
+ .gr-examples .gr-label,
773
+ .gr-examples .label-wrap,
774
+ .gr-examples .gr-accordion-header {
775
+ display: none !important;
776
+ }
777
+
778
+ /* Footer styling - centered text */
779
  .app-footer-wrapper {
780
+ background-color: var(--background-secondary) !important; /* Explicitly set background */
781
+ border: 2px solid var(--border-color) !important;
782
  border-radius: 12px !important;
783
+ padding: 1.75rem !important;
784
+ margin-top: 1.5rem !important;
785
+ margin-bottom: 1.5rem !important; /* Ensures space at the very bottom before the container padding */
786
+ text-align: center !important; /* Centered footer text */
787
  }
788
+ .app-footer p {
789
+ margin: 0.6rem 0 !important;
790
+ font-size: 0.95rem !important;
 
791
  color: var(--text-secondary) !important;
792
  line-height: 1.6 !important;
793
  }
794
+ .app-footer a {
 
795
  color: var(--primary-color) !important;
796
  text-decoration: none !important;
797
  font-weight: 600 !important;
798
  }
799
+ .app-footer a:hover {
 
800
  text-decoration: underline !important;
801
  }
802
 
803
+ /* Responsive design for smaller screens */
804
  @media (max-width: 768px) {
805
  .gradio-container {
806
  padding: 1rem !important;
807
  }
 
808
  .app-header-title {
809
+ font-size: 2.2rem !important;
810
  }
 
811
  .app-header-tagline {
812
  font-size: 1rem !important;
813
  }
814
+ .section-title {
815
+ font-size: 1.4rem !important;
 
816
  }
 
817
  .input-row {
818
+ flex-direction: column !important; /* Stack inputs vertically */
819
  }
 
820
  .button-row {
821
+ flex-direction: column !important; /* Stack buttons vertically */
822
  }
 
823
  .gradio-button {
824
+ width: 100% !important; /* Full width buttons */
825
+ }
826
+ .dashboard-card-section {
827
+ padding: 1.25rem !important;
828
+ }
829
+ .output-content-wrapper {
830
+ min-height: 120px !important;
831
+ }
832
+ .placeholder {
833
+ padding: 1.5rem 1rem !important;
834
+ font-size: 1rem !important;
835
  }
836
  }
837
  """
838
 
839
+ # Using gr.Blocks with custom CSS only to ensure no undesired colors are inherited from a theme.
840
  with gr.Blocks(css=custom_css, title="Landlord-Tenant Rights Assistant") as demo:
841
+ # Header Section - uses gr.Group for distinct card-like styling
842
  with gr.Group(elem_classes="app-header-wrapper"):
843
+ # Using a single Markdown component for header for easier robust centering
844
+ # The 'full-width-center' class applies flexbox centering to the Markdown content
845
  gr.Markdown(
846
  """
847
  <span class='app-header-logo'>⚖️</span>
848
  <h1 class='app-header-title'>Landlord-Tenant Rights Assistant</h1>
849
+ <p class='app-header-tagline'>Empowering You with State-Specific Legal Insights</p>
850
  """,
851
  elem_classes="full-width-center"
852
  )
853
 
854
+ # Main Dashboard Container - acts as a column to stack various sections
855
  with gr.Column(elem_classes="main-dashboard-container"):
856
 
857
+ # Introduction and Disclaimer Card
858
  with gr.Group(elem_classes="dashboard-card-section"):
859
+ # Apply 'full-width-center' for section titles
860
+ gr.Markdown("<h3 class='section-title'>Welcome & Disclaimer</h3>", elem_classes="full-width-center")
861
  gr.Markdown(
862
  """
863
+ Navigate landlord-tenant laws with ease. This assistant provides detailed, state-specific answers grounded in legal authority.
864
 
865
+ **Disclaimer:** This tool is for informational purposes only and does not constitute legal advice. For specific legal guidance, always consult a licensed attorney in your jurisdiction.
866
  """
867
  )
868
 
869
+ # OpenAI API Key Input Card
870
  with gr.Group(elem_classes="dashboard-card-section"):
871
+ # Apply 'full-width-center' for section titles
872
+ gr.Markdown("<h3 class='section-title'>OpenAI API Key</h3>", elem_classes="full-width-center")
873
  api_key_input = gr.Textbox(
874
+ label="API Key",
875
+ type="password", # Hides the input for security
876
+ placeholder="Enter your OpenAI API key (e.g., sk-...)",
877
+ info="Required to process your query. Get one from OpenAI: platform.openai.com/api-keys",
878
+ lines=1,
879
+ elem_classes=["input-field-group"] # Custom class for input styling
880
  )
881
 
882
+ # Query Input and State Selection Card
883
  with gr.Group(elem_classes="dashboard-card-section"):
884
+ # Apply 'full-width-center' for section titles
885
+ gr.Markdown("<h3 class='section-title'>Ask Your Question</h3>", elem_classes="full-width-center")
886
+ with gr.Row(elem_classes="input-row"): # Row for side-by-side query and state
887
+ with gr.Column(elem_classes="input-field", scale=3): # Query text area takes more space
888
  query_input = gr.Textbox(
889
+ label="Your Question",
890
+ placeholder="E.g., What are the rules for security deposit returns in my state?",
891
  lines=4,
892
+ max_lines=8,
893
+ elem_classes=["input-field-group"]
894
  )
895
+ with gr.Column(elem_classes="input-field", scale=1): # State radio buttons take less space
896
  state_input = gr.Radio(
897
+ label="Select State",
898
  choices=radio_choices,
899
+ value=initial_value_radio,
900
+ elem_classes=["input-field-group", "gradio-radio-custom"] # Added custom class for specific styling
901
  )
902
+ with gr.Row(elem_classes="button-row"): # Row for action buttons
903
+ clear_button = gr.Button("Clear", variant="secondary", elem_classes=["gr-button-secondary"])
904
+ submit_button = gr.Button("Submit Query", variant="primary", elem_classes=["gr-button-primary"])
905
 
906
+ # Output Display Card - Using gr.HTML for better animation control
907
  with gr.Group(elem_classes="dashboard-card-section"):
908
+ # Apply 'full-width-center' for section titles
909
+ gr.Markdown("<h3 class='section-title'>Legal Assistant's Response</h3>", elem_classes="full-width-center")
910
+ output = gr.HTML( # Changed to gr.HTML to wrap content with animation class
911
+ value="<div class='placeholder'>The answer will appear here after submitting your query.</div>",
912
+ elem_classes="output-content-wrapper" # Custom class for output styling
913
  )
914
 
915
+ # Example Questions Section
916
  with gr.Group(elem_classes="dashboard-card-section examples-section"):
917
+ # Apply 'full-width-center' for section titles
918
+ gr.Markdown("<h3 class='section-title'>Example Questions</h3>", elem_classes="full-width-center")
919
  if example_queries:
920
  gr.Examples(
921
  examples=example_queries,
922
  inputs=[query_input, state_input],
923
  examples_per_page=5,
924
+ label="" # Hide default Gradio label for examples to use our custom title
925
  )
926
  else:
927
+ gr.Markdown("<div class='placeholder'>Sample questions could not be loaded. Please ensure the vector database is populated.</div>")
928
 
929
+ # Footer Section - contains disclaimer and developer info
930
  with gr.Group(elem_classes="app-footer-wrapper"):
931
  gr.Markdown(
932
  """
933
+ This tool is for informational purposes only and does not constitute legal advice. For legal guidance, always consult with a licensed attorney in your jurisdiction.
934
+ Developed by **Nischal Subedi**. Connect on [LinkedIn](https://www.linkedin.com/in/nischal1/) or explore insights at [Substack](https://datascientistinsights.substack.com/).
 
935
  """
936
  )
937
 
938
+ # Event Listeners for buttons
939
  submit_button.click(
940
  fn=query_interface_wrapper,
941
  inputs=[api_key_input, query_input, state_input],
942
  outputs=output,
943
+ api_name="submit_query" # Useful for debugging / external calls
944
  )
945
 
946
  clear_button.click(
947
  fn=lambda: (
948
+ "", # Clear API key input
949
+ "", # Clear query input
950
+ initial_value_radio, # Reset state radio to default prompt
951
+ "<div class='placeholder'>Inputs cleared. Ready for your next question.</div>" # Reset output message
952
  ),
953
  inputs=[],
954
  outputs=[api_key_input, query_input, state_input, output]