Nischal Subedi commited on
Commit
b5e782c
·
1 Parent(s): a1e3519
Files changed (1) hide show
  1. app.py +158 -9
app.py CHANGED
@@ -243,6 +243,7 @@ Answer:"""
243
  raise RuntimeError(f"Failed to process PDF '{pdf_path}': {e}") from e
244
 
245
  # --- GRADIO INTERFACE (NEW UI DESIGN) ---
 
246
 
247
  def gradio_interface(self):
248
  def query_interface_wrapper(api_key: str, query: str, state: str) -> str:
@@ -274,6 +275,7 @@ Answer:"""
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"],
@@ -294,7 +296,7 @@ Answer:"""
294
  /* Import legible fonts from Google 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
- /* Root variables for consistent light theme */
298
  :root {
299
  --primary-color: #FF8C00;
300
  --primary-hover: #E07B00;
@@ -312,11 +314,30 @@ Answer:"""
312
  --error-text: #E05C00;
313
  }
314
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
315
  body, html {
316
  background-color: var(--background-secondary) !important;
317
  color: var(--text-primary) !important;
318
  transition: background-color 0.3s, color 0.3s;
319
  }
 
320
  .gradio-container {
321
  max-width: 900px !important;
322
  margin: 0 auto !important;
@@ -326,9 +347,11 @@ Answer:"""
326
  box-shadow: none !important;
327
  color: var(--text-primary) !important;
328
  }
 
329
  .main-dashboard-container > * {
330
  background-color: var(--background-primary) !important;
331
  }
 
332
  .app-header-wrapper {
333
  background: linear-gradient(145deg, var(--background-primary) 0%, var(--background-secondary) 100%) !important;
334
  border: 2px solid var(--border-color) !important;
@@ -341,6 +364,7 @@ Answer:"""
341
  text-align: center !important;
342
  color: var(--text-primary) !important;
343
  }
 
344
  .app-header-wrapper::before {
345
  content: '';
346
  position: absolute;
@@ -353,6 +377,7 @@ Answer:"""
353
  opacity: 0.8;
354
  pointer-events: none;
355
  }
 
356
  .app-header-logo {
357
  font-size: 8.5rem !important;
358
  margin-bottom: 0.75rem !important;
@@ -362,11 +387,13 @@ Answer:"""
362
  z-index: 1;
363
  animation: float-icon 3s ease-in-out infinite alternate;
364
  }
 
365
  @keyframes float-icon {
366
  0% { transform: translateY(0px); }
367
  50% { transform: translateY(-5px); }
368
  100% { transform: translateY(0px); }
369
  }
 
370
  .app-header-title {
371
  font-family: 'Poppins', sans-serif !important;
372
  font-size: 3rem !important;
@@ -380,6 +407,7 @@ Answer:"""
380
  display: inline-block;
381
  max-width: 100%;
382
  }
 
383
  .app-header-tagline {
384
  font-size: 1.25rem !important;
385
  color: var(--text-secondary) !important;
@@ -390,11 +418,13 @@ Answer:"""
390
  position: relative;
391
  z-index: 1;
392
  }
 
393
  .main-dashboard-container {
394
  display: flex !important;
395
  flex-direction: column !important;
396
  gap: 1.25rem !important;
397
  }
 
398
  .dashboard-card-section {
399
  background-color: var(--background-primary) !important;
400
  border: 2px solid var(--border-color) !important;
@@ -405,10 +435,12 @@ Answer:"""
405
  cursor: default;
406
  color: var(--text-primary) !important;
407
  }
 
408
  .dashboard-card-section:hover {
409
  box-shadow: var(--shadow-md) !important;
410
  transform: translateY(-3px) !important;
411
  }
 
412
  .full-width-center {
413
  display: flex !important;
414
  justify-content: center !important;
@@ -417,6 +449,7 @@ Answer:"""
417
  flex-direction: column !important;
418
  background-color: transparent !important;
419
  }
 
420
  .section-title-gradient-bar {
421
  background-color: var(--background-secondary) !important;
422
  padding: 1.25rem 1.75rem !important;
@@ -428,6 +461,7 @@ Answer:"""
428
  width: 100%;
429
  color: var(--text-primary) !important;
430
  }
 
431
  .section-title {
432
  font-family: 'Poppins', sans-serif !important;
433
  font-size: 1.7rem !important;
@@ -441,13 +475,15 @@ Answer:"""
441
  text-align: center !important;
442
  letter-spacing: -0.01em !important;
443
  }
 
444
  .dashboard-card-content-area {
445
  padding: 0 1.75rem 1.75rem 1.75rem !important;
446
  background-color: var(--background-primary) !important;
447
  box-sizing: border-box;
448
  width: 100%;
449
- color: var(--text-primary) !important;
450
  }
 
451
  .dashboard-card-section p {
452
  line-height: 1.7 !important;
453
  color: var(--text-primary) !important;
@@ -458,10 +494,12 @@ Answer:"""
458
  padding: 0 !important;
459
  white-space: normal !important;
460
  }
 
461
  .dashboard-card-section strong, .dashboard-card-section b {
462
  font-weight: 700 !important;
463
  color: var(--primary-color) !important;
464
  }
 
465
  .gr-block, .gr-box, .gr-prose, .gr-form, .gr-panel,
466
  .gr-columns, .gr-column,
467
  .gradio-html, .gradio-markdown, .gradio-textbox, .gradio-radio, .gradio-button {
@@ -471,6 +509,7 @@ Answer:"""
471
  overflow-wrap: break-word;
472
  word-break: break-word;
473
  }
 
474
  .gradio-textbox textarea,
475
  .gradio-textbox input,
476
  .gradio-radio label,
@@ -478,9 +517,11 @@ Answer:"""
478
  background-color: var(--background-primary) !important;
479
  color: var(--text-primary) !important;
480
  }
 
481
  .gradio-textbox {
482
  margin-bottom: 0.5rem !important;
483
  }
 
484
  .gradio-textbox textarea,
485
  .gradio-textbox input {
486
  border: 2px solid var(--border-color) !important;
@@ -492,22 +533,27 @@ Answer:"""
492
  transition: border-color 0.2s ease, box-shadow 0.2s ease !important;
493
  box-shadow: var(--shadow-sm) !important;
494
  }
 
495
  .gradio-textbox .scroll-hide {
496
  background-color: var(--background-primary) !important;
497
  }
 
498
  .gradio-textbox textarea:focus,
499
  .gradio-textbox input:focus {
500
  outline: none !important;
501
  border-color: var(--border-focus) !important;
502
  box-shadow: 0 0 0 4px rgba(255, 140, 0, 0.2) !important;
503
  }
 
504
  .gradio-radio {
505
  padding: 0 !important;
506
  margin-top: 1rem !important;
507
  }
 
508
  .gradio-radio input[type="radio"] {
509
  display: none !important;
510
  }
 
511
  .gradio-radio label {
512
  display: flex !important;
513
  justify-content: center !important;
@@ -524,17 +570,20 @@ Answer:"""
524
  width: 100 !important;
525
  box-sizing: border-box !important;
526
  }
 
527
  .gradio-radio label span.text-lg {
528
  font-weight: 600 !important;
529
  color: var(--text-primary) !important;
530
  font-size: 0.98rem !important;
531
  }
 
532
  .gradio-radio label:hover {
533
  background-color: var(--background-secondary) !important;
534
  border-color: var(--primary-color) !important;
535
  box-shadow: var(--shadow-md) !important;
536
  transform: translateY(-2px) !important;
537
  }
 
538
  .gradio-radio input[type="radio"]:checked + label {
539
  background-color: var(--primary-color) !important;
540
  color: var(--text-primary) !important;
@@ -542,12 +591,15 @@ Answer:"""
542
  box-shadow: var(--shadow-md) !important;
543
  transform: translateY(-1px) !important;
544
  }
 
545
  .gradio-radio input[type="radio"]:checked + label span.text-lg {
546
  color: var(--text-primary) !important;
547
  }
 
548
  .gradio-radio .gr-form {
549
  padding: 0 !important;
550
  }
 
551
  .gradio-textbox label,
552
  .gradio-radio > label {
553
  font-weight: 600 !important;
@@ -557,6 +609,7 @@ Answer:"""
557
  display: block !important;
558
  text-align: left !important;
559
  }
 
560
  .gr-prose {
561
  font-size: 0.9rem !important;
562
  color: var(--text-secondary) !important;
@@ -564,22 +617,26 @@ Answer:"""
564
  text-align: left !important;
565
  background-color: transparent !important;
566
  }
 
567
  .input-column {
568
  display: flex !important;
569
  flex-direction: column !important;
570
  gap: 1.25rem !important;
571
  margin-bottom: 0.5rem !important;
572
  }
 
573
  .input-field {
574
  flex: none !important;
575
  width: 100% !important;
576
  }
 
577
  .button-row {
578
  display: flex !important;
579
  gap: 1rem !important;
580
  justify-content: flex-end !important;
581
  margin-top: 1.5rem !important;
582
  }
 
583
  .gradio-button {
584
  padding: 0.85rem 1.8rem !important;
585
  border-radius: 9px !important;
@@ -591,34 +648,41 @@ Answer:"""
591
  text-align: center !important;
592
  color: var(--text-primary) !important;
593
  }
 
594
  .gr-button-primary {
595
  background-color: var(--primary-color) !important;
596
  color: white !important;
597
  box-shadow: var(--shadow-sm) !important;
598
  }
 
599
  .gr-button-primary:hover {
600
  background-color: var(--primary-hover) !important;
601
  box-shadow: var(--shadow-md) !important;
602
  transform: translateY(-2px) !important;
603
  }
 
604
  .gr-button-primary:active {
605
  transform: translateY(1px) !important;
606
  box-shadow: none !important;
607
  }
 
608
  .gr-button-secondary {
609
  background-color: transparent !important;
610
  color: var(--text-primary) !important;
611
  border-color: var(--border-color) !important;
612
  }
 
613
  .gr-button-secondary:hover {
614
  background-color: var(--background-secondary) !important;
615
  border-color: var(--primary-color) !important;
616
  transform: translateY(-2px) !important;
617
  }
 
618
  .gr-button-secondary:active {
619
  transform: translateY(1px) !important;
620
  box-shadow: none !important;
621
  }
 
622
  .output-content-wrapper {
623
  background-color: var(--background-primary) !important;
624
  border: 2px solid var(--border-color) !important;
@@ -631,6 +695,7 @@ Answer:"""
631
  justify-content: center;
632
  align-items: center;
633
  }
 
634
  .animated-output-content {
635
  opacity: 0;
636
  animation: fadeInAndSlideUp 0.7s ease-out forwards;
@@ -641,10 +706,12 @@ Answer:"""
641
  text-align: left !important;
642
  color: var(--text-primary) !important;
643
  }
 
644
  @keyframes fadeInAndSlideUp {
645
  from { opacity: 0; transform: translateY(15px); }
646
  to { opacity: 1; transform: translateY(0); }
647
  }
 
648
  .response-header {
649
  font-size: 1.3rem !important;
650
  font-weight: 700 !important;
@@ -657,15 +724,18 @@ Answer:"""
657
  width: 100%;
658
  justify-content: flex-start;
659
  }
 
660
  .response-icon {
661
  font-size: 1.5rem !important;
662
  color: var(--primary-color) !important;
663
  }
 
664
  .divider {
665
  border: none !important;
666
  border-top: 1px dashed var(--border-color) !important;
667
  margin: 1rem 0 !important;
668
  }
 
669
  .error-message {
670
  background-color: var(--error-bg) !important;
671
  border: 2px solid var(--error-border) !important;
@@ -682,21 +752,25 @@ Answer:"""
682
  width: 100%;
683
  box-sizing: border-box;
684
  }
 
685
  .error-message a {
686
  color: var(--error-text) !important;
687
  text-decoration: underline !important;
688
  }
 
689
  .error-icon {
690
  font-size: 1.4rem !important;
691
  line-height: 1 !important;
692
  margin-top: 0.1rem !important;
693
  }
 
694
  .error-details {
695
  font-size: 0.85rem !important;
696
  color: var(--error-text) !important;
697
  margin-top: 0.5rem !important;
698
  opacity: 0.8;
699
  }
 
700
  .placeholder {
701
  background-color: var(--background-primary) !important;
702
  border: 2px dashed var(--border-color) !important;
@@ -709,12 +783,14 @@ Answer:"""
709
  width: 100%;
710
  box-sizing: border-box;
711
  }
 
712
  .examples-section .gr-samples-table {
713
  border: 2px solid var(--border-color) !important;
714
  border-radius: 8px !important;
715
  overflow: hidden !important;
716
  margin-top: 1rem !important;
717
  }
 
718
  .examples-section .gr-samples-table th,
719
  .examples-section .gr-samples-table td {
720
  padding: 0.9rem !important;
@@ -723,11 +799,13 @@ Answer:"""
723
  text-align: left !important;
724
  color: var(--text-primary) !important;
725
  }
 
726
  .examples-section .gr-samples-table th {
727
  background-color: var(--background-secondary) !important;
728
  font-weight: 700 !important;
729
  color: var(--text-primary) !important;
730
  }
 
731
  .examples-section .gr-samples-table td {
732
  background-color: var(--background-primary) !important;
733
  color: var(--text-primary) !important;
@@ -735,15 +813,18 @@ Answer:"""
735
  cursor: pointer !important;
736
  transition: background 0.2s ease, transform 0.1s ease !important;
737
  }
 
738
  .examples-section .gr-samples-table tr:hover td {
739
  background-color: var(--background-secondary) !important;
740
  transform: translateX(5px);
741
  }
 
742
  .gr-examples .gr-label,
743
  .gr-examples .label-wrap,
744
  .gr-examples .gr-accordion-header {
745
  display: none !important;
746
  }
 
747
  .app-footer-wrapper {
748
  background: linear-gradient(145deg, var(--background-primary) 0%, var(--background-secondary) 100%) !important;
749
  border: 2px solid var(--border-color) !important;
@@ -754,6 +835,7 @@ Answer:"""
754
  text-align: center !important;
755
  color: var(--text-primary) !important;
756
  }
 
757
  .app-footer p {
758
  margin: 0 !important;
759
  max-width: 90% !important;
@@ -764,60 +846,128 @@ Answer:"""
764
  text-align: center !important;
765
  white-space: normal !important;
766
  }
 
767
  .app-footer strong, .app-footer b {
768
  font-weight: 700 !important;
769
  color: var(--primary-color) !important;
770
  }
 
771
  .app-footer a {
772
  color: var(--primary-color) !important;
773
  text-decoration: underline !important;
774
  font-weight: 600 !important;
775
  }
 
776
  .app-footer a:hover {
777
  text-decoration: none !important;
778
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
779
  @media (max-width: 768px) {
780
  .gradio-container {
781
  padding: 1rem !important;
782
  }
 
783
  .app-header-title {
784
  font-size: 2.2rem !important;
785
  }
 
786
  .app-header-tagline {
787
  font-size: 1rem !important;
788
  }
 
789
  .section-title {
790
  font-size: 1.4rem !important;
791
  }
 
792
  .input-column {
793
  flex-direction: column !important;
794
  }
 
795
  .button-row {
796
  flex-direction: column !important;
797
  }
 
798
  .gradio-button {
799
  width: 100% !important;
800
  }
801
- .dashboard-card-section {
802
- }
803
  .section-title-gradient-bar {
804
  padding: 0.1rem 1rem !important;
805
  }
 
806
  .dashboard-card-content-area {
807
  padding: 0 1rem 1rem 1rem !important;
808
  }
 
809
  .output-content-wrapper {
810
  min-height: 120px !important;
811
  }
 
812
  .placeholder {
813
  padding: 1.5rem 1rem !important;
814
  font-size: 1rem !important;
815
  }
 
 
 
 
 
 
 
816
  }
817
  """
818
 
819
- # MODIFIED LINE: Added theme_mode="light"
820
- with gr.Blocks(css=custom_css, title="Landlord-Tenant Rights Assistant", theme_mode="light") as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
821
  with gr.Group(elem_classes="app-header-wrapper"):
822
  gr.Markdown(
823
  """
@@ -910,7 +1060,7 @@ Answer:"""
910
  <style>
911
  .custom-link {{
912
  font-weight: bold !important;
913
- color: orange !important;
914
  text-decoration: underline;
915
  }}
916
  </style>
@@ -925,7 +1075,7 @@ Answer:"""
925
  outputs=output,
926
  api_name="submit_query"
927
  )
928
-
929
  clear_button.click(
930
  fn=lambda: (
931
  "", "", initial_value_radio, "<div class='placeholder'>Inputs cleared. Ready for your next question.</div>"
@@ -935,7 +1085,6 @@ Answer:"""
935
  )
936
 
937
  return demo
938
-
939
  # --- Main Execution Block (UNCHANGED from original logic) ---
940
  if __name__ == "__main__":
941
  logging.info("Starting Landlord-Tenant Rights Bot application...")
 
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
  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"],
 
296
  /* Import legible 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;800&display=swap');
298
 
299
+ /* Root variables for light theme */
300
  :root {
301
  --primary-color: #FF8C00;
302
  --primary-hover: #E07B00;
 
314
  --error-text: #E05C00;
315
  }
316
 
317
+ /* Dark theme variables */
318
+ [data-theme="dark"] {
319
+ --primary-color: #FF8C00;
320
+ --primary-hover: #FFB366;
321
+ --background-primary: #1A1A1A;
322
+ --background-secondary: #2D2D2D;
323
+ --text-primary: #E0E0E0;
324
+ --text-secondary: #A0A0A0;
325
+ --border-color: #454545;
326
+ --border-focus: #FF8C00;
327
+ --shadow-sm: 0 1px 3px rgba(0,0,0,0.3);
328
+ --shadow-md: 0 4px 10px rgba(0,0,0,0.4);
329
+ --shadow-lg: 0 10px 20px rgba(0,0,0,0.5);
330
+ --error-bg: #3A2A2A;
331
+ --error-border: #FF8C00;
332
+ --error-text: #FF8C00;
333
+ }
334
+
335
  body, html {
336
  background-color: var(--background-secondary) !important;
337
  color: var(--text-primary) !important;
338
  transition: background-color 0.3s, color 0.3s;
339
  }
340
+
341
  .gradio-container {
342
  max-width: 900px !important;
343
  margin: 0 auto !important;
 
347
  box-shadow: none !important;
348
  color: var(--text-primary) !important;
349
  }
350
+
351
  .main-dashboard-container > * {
352
  background-color: var(--background-primary) !important;
353
  }
354
+
355
  .app-header-wrapper {
356
  background: linear-gradient(145deg, var(--background-primary) 0%, var(--background-secondary) 100%) !important;
357
  border: 2px solid var(--border-color) !important;
 
364
  text-align: center !important;
365
  color: var(--text-primary) !important;
366
  }
367
+
368
  .app-header-wrapper::before {
369
  content: '';
370
  position: absolute;
 
377
  opacity: 0.8;
378
  pointer-events: none;
379
  }
380
+
381
  .app-header-logo {
382
  font-size: 8.5rem !important;
383
  margin-bottom: 0.75rem !important;
 
387
  z-index: 1;
388
  animation: float-icon 3s ease-in-out infinite alternate;
389
  }
390
+
391
  @keyframes float-icon {
392
  0% { transform: translateY(0px); }
393
  50% { transform: translateY(-5px); }
394
  100% { transform: translateY(0px); }
395
  }
396
+
397
  .app-header-title {
398
  font-family: 'Poppins', sans-serif !important;
399
  font-size: 3rem !important;
 
407
  display: inline-block;
408
  max-width: 100%;
409
  }
410
+
411
  .app-header-tagline {
412
  font-size: 1.25rem !important;
413
  color: var(--text-secondary) !important;
 
418
  position: relative;
419
  z-index: 1;
420
  }
421
+
422
  .main-dashboard-container {
423
  display: flex !important;
424
  flex-direction: column !important;
425
  gap: 1.25rem !important;
426
  }
427
+
428
  .dashboard-card-section {
429
  background-color: var(--background-primary) !important;
430
  border: 2px solid var(--border-color) !important;
 
435
  cursor: default;
436
  color: var(--text-primary) !important;
437
  }
438
+
439
  .dashboard-card-section:hover {
440
  box-shadow: var(--shadow-md) !important;
441
  transform: translateY(-3px) !important;
442
  }
443
+
444
  .full-width-center {
445
  display: flex !important;
446
  justify-content: center !important;
 
449
  flex-direction: column !important;
450
  background-color: transparent !important;
451
  }
452
+
453
  .section-title-gradient-bar {
454
  background-color: var(--background-secondary) !important;
455
  padding: 1.25rem 1.75rem !important;
 
461
  width: 100%;
462
  color: var(--text-primary) !important;
463
  }
464
+
465
  .section-title {
466
  font-family: 'Poppins', sans-serif !important;
467
  font-size: 1.7rem !important;
 
475
  text-align: center !important;
476
  letter-spacing: -0.01em !important;
477
  }
478
+
479
  .dashboard-card-content-area {
480
  padding: 0 1.75rem 1.75rem 1.75rem !important;
481
  background-color: var(--background-primary) !important;
482
  box-sizing: border-box;
483
  width: 100%;
484
+ color部分: color: var(--text-primary) !important;
485
  }
486
+
487
  .dashboard-card-section p {
488
  line-height: 1.7 !important;
489
  color: var(--text-primary) !important;
 
494
  padding: 0 !important;
495
  white-space: normal !important;
496
  }
497
+
498
  .dashboard-card-section strong, .dashboard-card-section b {
499
  font-weight: 700 !important;
500
  color: var(--primary-color) !important;
501
  }
502
+
503
  .gr-block, .gr-box, .gr-prose, .gr-form, .gr-panel,
504
  .gr-columns, .gr-column,
505
  .gradio-html, .gradio-markdown, .gradio-textbox, .gradio-radio, .gradio-button {
 
509
  overflow-wrap: break-word;
510
  word-break: break-word;
511
  }
512
+
513
  .gradio-textbox textarea,
514
  .gradio-textbox input,
515
  .gradio-radio label,
 
517
  background-color: var(--background-primary) !important;
518
  color: var(--text-primary) !important;
519
  }
520
+
521
  .gradio-textbox {
522
  margin-bottom: 0.5rem !important;
523
  }
524
+
525
  .gradio-textbox textarea,
526
  .gradio-textbox input {
527
  border: 2px solid var(--border-color) !important;
 
533
  transition: border-color 0.2s ease, box-shadow 0.2s ease !important;
534
  box-shadow: var(--shadow-sm) !important;
535
  }
536
+
537
  .gradio-textbox .scroll-hide {
538
  background-color: var(--background-primary) !important;
539
  }
540
+
541
  .gradio-textbox textarea:focus,
542
  .gradio-textbox input:focus {
543
  outline: none !important;
544
  border-color: var(--border-focus) !important;
545
  box-shadow: 0 0 0 4px rgba(255, 140, 0, 0.2) !important;
546
  }
547
+
548
  .gradio-radio {
549
  padding: 0 !important;
550
  margin-top: 1rem !important;
551
  }
552
+
553
  .gradio-radio input[type="radio"] {
554
  display: none !important;
555
  }
556
+
557
  .gradio-radio label {
558
  display: flex !important;
559
  justify-content: center !important;
 
570
  width: 100 !important;
571
  box-sizing: border-box !important;
572
  }
573
+
574
  .gradio-radio label span.text-lg {
575
  font-weight: 600 !important;
576
  color: var(--text-primary) !important;
577
  font-size: 0.98rem !important;
578
  }
579
+
580
  .gradio-radio label:hover {
581
  background-color: var(--background-secondary) !important;
582
  border-color: var(--primary-color) !important;
583
  box-shadow: var(--shadow-md) !important;
584
  transform: translateY(-2px) !important;
585
  }
586
+
587
  .gradio-radio input[type="radio"]:checked + label {
588
  background-color: var(--primary-color) !important;
589
  color: var(--text-primary) !important;
 
591
  box-shadow: var(--shadow-md) !important;
592
  transform: translateY(-1px) !important;
593
  }
594
+
595
  .gradio-radio input[type="radio"]:checked + label span.text-lg {
596
  color: var(--text-primary) !important;
597
  }
598
+
599
  .gradio-radio .gr-form {
600
  padding: 0 !important;
601
  }
602
+
603
  .gradio-textbox label,
604
  .gradio-radio > label {
605
  font-weight: 600 !important;
 
609
  display: block !important;
610
  text-align: left !important;
611
  }
612
+
613
  .gr-prose {
614
  font-size: 0.9rem !important;
615
  color: var(--text-secondary) !important;
 
617
  text-align: left !important;
618
  background-color: transparent !important;
619
  }
620
+
621
  .input-column {
622
  display: flex !important;
623
  flex-direction: column !important;
624
  gap: 1.25rem !important;
625
  margin-bottom: 0.5rem !important;
626
  }
627
+
628
  .input-field {
629
  flex: none !important;
630
  width: 100% !important;
631
  }
632
+
633
  .button-row {
634
  display: flex !important;
635
  gap: 1rem !important;
636
  justify-content: flex-end !important;
637
  margin-top: 1.5rem !important;
638
  }
639
+
640
  .gradio-button {
641
  padding: 0.85rem 1.8rem !important;
642
  border-radius: 9px !important;
 
648
  text-align: center !important;
649
  color: var(--text-primary) !important;
650
  }
651
+
652
  .gr-button-primary {
653
  background-color: var(--primary-color) !important;
654
  color: white !important;
655
  box-shadow: var(--shadow-sm) !important;
656
  }
657
+
658
  .gr-button-primary:hover {
659
  background-color: var(--primary-hover) !important;
660
  box-shadow: var(--shadow-md) !important;
661
  transform: translateY(-2px) !important;
662
  }
663
+
664
  .gr-button-primary:active {
665
  transform: translateY(1px) !important;
666
  box-shadow: none !important;
667
  }
668
+
669
  .gr-button-secondary {
670
  background-color: transparent !important;
671
  color: var(--text-primary) !important;
672
  border-color: var(--border-color) !important;
673
  }
674
+
675
  .gr-button-secondary:hover {
676
  background-color: var(--background-secondary) !important;
677
  border-color: var(--primary-color) !important;
678
  transform: translateY(-2px) !important;
679
  }
680
+
681
  .gr-button-secondary:active {
682
  transform: translateY(1px) !important;
683
  box-shadow: none !important;
684
  }
685
+
686
  .output-content-wrapper {
687
  background-color: var(--background-primary) !important;
688
  border: 2px solid var(--border-color) !important;
 
695
  justify-content: center;
696
  align-items: center;
697
  }
698
+
699
  .animated-output-content {
700
  opacity: 0;
701
  animation: fadeInAndSlideUp 0.7s ease-out forwards;
 
706
  text-align: left !important;
707
  color: var(--text-primary) !important;
708
  }
709
+
710
  @keyframes fadeInAndSlideUp {
711
  from { opacity: 0; transform: translateY(15px); }
712
  to { opacity: 1; transform: translateY(0); }
713
  }
714
+
715
  .response-header {
716
  font-size: 1.3rem !important;
717
  font-weight: 700 !important;
 
724
  width: 100%;
725
  justify-content: flex-start;
726
  }
727
+
728
  .response-icon {
729
  font-size: 1.5rem !important;
730
  color: var(--primary-color) !important;
731
  }
732
+
733
  .divider {
734
  border: none !important;
735
  border-top: 1px dashed var(--border-color) !important;
736
  margin: 1rem 0 !important;
737
  }
738
+
739
  .error-message {
740
  background-color: var(--error-bg) !important;
741
  border: 2px solid var(--error-border) !important;
 
752
  width: 100%;
753
  box-sizing: border-box;
754
  }
755
+
756
  .error-message a {
757
  color: var(--error-text) !important;
758
  text-decoration: underline !important;
759
  }
760
+
761
  .error-icon {
762
  font-size: 1.4rem !important;
763
  line-height: 1 !important;
764
  margin-top: 0.1rem !important;
765
  }
766
+
767
  .error-details {
768
  font-size: 0.85rem !important;
769
  color: var(--error-text) !important;
770
  margin-top: 0.5rem !important;
771
  opacity: 0.8;
772
  }
773
+
774
  .placeholder {
775
  background-color: var(--background-primary) !important;
776
  border: 2px dashed var(--border-color) !important;
 
783
  width: 100%;
784
  box-sizing: border-box;
785
  }
786
+
787
  .examples-section .gr-samples-table {
788
  border: 2px solid var(--border-color) !important;
789
  border-radius: 8px !important;
790
  overflow: hidden !important;
791
  margin-top: 1rem !important;
792
  }
793
+
794
  .examples-section .gr-samples-table th,
795
  .examples-section .gr-samples-table td {
796
  padding: 0.9rem !important;
 
799
  text-align: left !important;
800
  color: var(--text-primary) !important;
801
  }
802
+
803
  .examples-section .gr-samples-table th {
804
  background-color: var(--background-secondary) !important;
805
  font-weight: 700 !important;
806
  color: var(--text-primary) !important;
807
  }
808
+
809
  .examples-section .gr-samples-table td {
810
  background-color: var(--background-primary) !important;
811
  color: var(--text-primary) !important;
 
813
  cursor: pointer !important;
814
  transition: background 0.2s ease, transform 0.1s ease !important;
815
  }
816
+
817
  .examples-section .gr-samples-table tr:hover td {
818
  background-color: var(--background-secondary) !important;
819
  transform: translateX(5px);
820
  }
821
+
822
  .gr-examples .gr-label,
823
  .gr-examples .label-wrap,
824
  .gr-examples .gr-accordion-header {
825
  display: none !important;
826
  }
827
+
828
  .app-footer-wrapper {
829
  background: linear-gradient(145deg, var(--background-primary) 0%, var(--background-secondary) 100%) !important;
830
  border: 2px solid var(--border-color) !important;
 
835
  text-align: center !important;
836
  color: var(--text-primary) !important;
837
  }
838
+
839
  .app-footer p {
840
  margin: 0 !important;
841
  max-width: 90% !important;
 
846
  text-align: center !important;
847
  white-space: normal !important;
848
  }
849
+
850
  .app-footer strong, .app-footer b {
851
  font-weight: 700 !important;
852
  color: var(--primary-color) !important;
853
  }
854
+
855
  .app-footer a {
856
  color: var(--primary-color) !important;
857
  text-decoration: underline !important;
858
  font-weight: 600 !important;
859
  }
860
+
861
  .app-footer a:hover {
862
  text-decoration: none !important;
863
  }
864
+
865
+ /* Theme toggle button styles */
866
+ .theme-toggle {
867
+ position: fixed;
868
+ top: 1rem;
869
+ right: 1rem;
870
+ padding: 0.5rem 1rem;
871
+ background-color: var(--primary-color);
872
+ color: white;
873
+ border: none;
874
+ border-radius: 8px;
875
+ cursor: pointer;
876
+ font-size: 0.9rem;
877
+ font-weight: 600;
878
+ transition: background-color 0.2s ease;
879
+ }
880
+
881
+ .theme-toggle:hover {
882
+ background-color: var(--primary-hover);
883
+ }
884
+
885
  @media (max-width: 768px) {
886
  .gradio-container {
887
  padding: 1rem !important;
888
  }
889
+
890
  .app-header-title {
891
  font-size: 2.2rem !important;
892
  }
893
+
894
  .app-header-tagline {
895
  font-size: 1rem !important;
896
  }
897
+
898
  .section-title {
899
  font-size: 1.4rem !important;
900
  }
901
+
902
  .input-column {
903
  flex-direction: column !important;
904
  }
905
+
906
  .button-row {
907
  flex-direction: column !important;
908
  }
909
+
910
  .gradio-button {
911
  width: 100% !important;
912
  }
913
+
 
914
  .section-title-gradient-bar {
915
  padding: 0.1rem 1rem !important;
916
  }
917
+
918
  .dashboard-card-content-area {
919
  padding: 0 1rem 1rem 1rem !important;
920
  }
921
+
922
  .output-content-wrapper {
923
  min-height: 120px !important;
924
  }
925
+
926
  .placeholder {
927
  padding: 1.5rem 1rem !important;
928
  font-size: 1rem !important;
929
  }
930
+
931
+ .theme-toggle {
932
+ top: 0.5rem;
933
+ right: 0.5rem;
934
+ padding: 0.4rem 0.8rem;
935
+ font-size: 0.8rem;
936
+ }
937
  }
938
  """
939
 
940
+ with gr.Blocks(css=custom_css, title="Landlord-Tenant Rights Assistant") as demo:
941
+ # Theme toggle button
942
+ gr.HTML(
943
+ """
944
+ <button class="theme-toggle" onclick="toggleTheme()">Toggle Theme</button>
945
+ <script>
946
+ function setTheme(theme) {
947
+ document.documentElement.setAttribute('data-theme', theme);
948
+ localStorage.setItem('theme', theme);
949
+ }
950
+
951
+ function toggleTheme() {
952
+ const currentTheme = document.documentElement.getAttribute('data-theme') || 'light';
953
+ const newTheme = currentTheme === 'light' ? 'dark' : 'light';
954
+ setTheme(newTheme);
955
+ }
956
+
957
+ // Check system preference or saved preference
958
+ const savedTheme = localStorage.getItem('theme');
959
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
960
+ const initialTheme = savedTheme || (prefersDark ? 'dark' : 'light');
961
+ setTheme(initialTheme);
962
+
963
+ // Listen for system theme changes
964
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
965
+ setTheme(e.matches ? 'dark' : 'light');
966
+ });
967
+ </script>
968
+ """
969
+ )
970
+
971
  with gr.Group(elem_classes="app-header-wrapper"):
972
  gr.Markdown(
973
  """
 
1060
  <style>
1061
  .custom-link {{
1062
  font-weight: bold !important;
1063
+ color: var(--primary-color) !important;
1064
  text-decoration: underline;
1065
  }}
1066
  </style>
 
1075
  outputs=output,
1076
  api_name="submit_query"
1077
  )
1078
+
1079
  clear_button.click(
1080
  fn=lambda: (
1081
  "", "", initial_value_radio, "<div class='placeholder'>Inputs cleared. Ready for your next question.</div>"
 
1085
  )
1086
 
1087
  return demo
 
1088
  # --- Main Execution Block (UNCHANGED from original logic) ---
1089
  if __name__ == "__main__":
1090
  logging.info("Starting Landlord-Tenant Rights Bot application...")