Imvirus commited on
Commit
47a2dd5
·
verified ·
1 Parent(s): 1376bef

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +26 -9
app.py CHANGED
@@ -525,8 +525,19 @@ button.preset-btn:hover,.preset-btn button:hover{background:var(--text)!importan
525
  .ctl-head{padding-bottom:8px}
526
  .ctl-head strong{display:block;font:500 15px/1.2 var(--sans);color:var(--text)}
527
  .ctl-head p{margin-top:4px!important;font-size:12px;color:var(--muted)}
528
- .param-group{border:0!important;border-top:1px solid var(--line)!important;border-radius:0!important;background:transparent!important;padding:12px 0 8px!important;margin:0!important;box-shadow:none!important}
529
- .param-group>button,.param-group>.label-wrap,.param-group button.label-wrap{font:500 11.5px/1.2 var(--sans)!important;letter-spacing:.02em;color:var(--text-2)!important;background:transparent!important;padding:4px 0!important}
 
 
 
 
 
 
 
 
 
 
 
530
  .control-panel [data-testid="block-info"],.control-panel label>span{font-size:12.5px!important;color:#D8D5CF!important}
531
  .control-panel [data-testid="block-info"]+div,.control-panel .info{color:var(--muted)!important}
532
  .control-panel input[type="number"]{font:400 12px var(--mono)!important;background:rgba(255,255,255,.04)!important;border:1px solid var(--line)!important;border-radius:6px!important;color:var(--text)!important}
@@ -645,8 +656,14 @@ button.compare-button:hover,.compare-button button:hover{background:var(--text)!
645
 
646
  /* methods */
647
  .methods{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px;margin-top:48px}
648
- .m-col{min-width:0;padding:20px}
649
- .m-num{display:inline-block;font:500 10.5px var(--mono);color:var(--text-2);padding:3px 8px;border-radius:999px;background:rgba(255,255,255,.06)}
 
 
 
 
 
 
650
  .gradio-container .m-col h3{margin:12px 0 10px!important;font:500 15px/1.3 var(--sans)!important;color:var(--text)!important}
651
  .gradio-container .m-col p{font-size:13px;line-height:1.6;color:var(--text-2);margin:0 0 10px!important;text-wrap:pretty}
652
  .fx{font:400 12.5px var(--mono);color:var(--text);padding:10px 12px;margin:4px 0 10px;border-radius:8px;background:rgba(0,0,0,.28);border:1px solid var(--line);white-space:nowrap;overflow-x:auto}
@@ -700,7 +717,7 @@ MASTHEAD = f"""
700
  <div class="intro">
701
  <div class="eyebrow">A laboratory for collective opinion</div>
702
  <h1>How opinions <em>move</em> through a network.</h1>
703
- <p>Set up a synthetic population, choose who talks to whom, add confirmation bias, committed minorities or a persistent external signal, then watch local influence rules produce consensus, drift or division.</p>
704
  </div>
705
  """
706
 
@@ -782,20 +799,20 @@ with gr.Blocks(title="SocialDynamics Lab — opinion dynamics simulator") as dem
782
  with gr.Row(equal_height=False, elem_classes=["lab-row"]):
783
  with gr.Column(scale=3, min_width=300, elem_classes=["control-panel"]):
784
  gr.HTML('<div class="ctl-head"><strong>Parameters</strong><p>Deterministic for a fixed seed.</p></div>')
785
- with gr.Accordion("Population & network", open=True, elem_classes=["param-group"]):
786
  n_agents = gr.Radio([100, 500, 1000], value=100, label="Population size")
787
  network = gr.Dropdown(["Random", "Small World", "Scale Free"], value="Small World", label="Network structure")
788
  initial_opinion = gr.Dropdown(["Random", "Neutral", "Polarized"], value="Random", label="Initial opinion state")
789
- with gr.Accordion("Dynamics", open=True, elem_classes=["param-group"]):
790
  confirmation_bias = gr.Slider(0, 1, value=0.45, step=0.01, label="Confirmation bias (β)", info="Suppresses influence from dissimilar neighbours.")
791
  social_influence = gr.Slider(0, 1, value=0.45, step=0.01, label="Social influence (α)", info="Speed of movement toward the neighbourhood target.")
792
  stubborn_fraction = gr.Slider(0, 0.30, value=0.05, step=0.01, label="Stubborn agents", info="Share of agents that never update.")
793
  stubborn_mode = gr.Dropdown(["Keep initial", "Positive (+1)", "Negative (-1)", "Split extremes"], value="Split extremes", label="Stubborn stance")
794
- with gr.Accordion("External signal", open=False, elem_classes=["param-group"]):
795
  misinformation_exposure = gr.Slider(0, 1, value=0.25, step=0.01, label="Misinformation exposure", info="Share of adaptive agents receiving the signal.")
796
  misinformation_strength = gr.Slider(0, 1, value=0.35, step=0.01, label="Signal strength")
797
  misinformation_direction = gr.Radio(["Positive (+1)", "Negative (-1)"], value="Positive (+1)", label="Signal direction")
798
- with gr.Accordion("Run settings", open=False, elem_classes=["param-group"]):
799
  noise = gr.Slider(0, 0.20, value=0.02, step=0.005, label="Random noise (σ)")
800
  steps = gr.Slider(50, 300, value=120, step=10, label="Simulation horizon (steps)")
801
  seed = gr.Number(value=42, precision=0, label="Random seed")
 
525
  .ctl-head{padding-bottom:8px}
526
  .ctl-head strong{display:block;font:500 15px/1.2 var(--sans);color:var(--text)}
527
  .ctl-head p{margin-top:4px!important;font-size:12px;color:var(--muted)}
528
+ .pg-pop{--acc:108,142,245}.pg-dyn{--acc:179,154,232}.pg-sig{--acc:217,164,65}.pg-run{--acc:95,184,138}
529
+ .param-group{position:relative;overflow:hidden;border:1px solid rgba(var(--acc),.18)!important;border-radius:12px!important;background:linear-gradient(180deg,rgba(var(--acc),.07),rgba(var(--acc),.015) 60%)!important;padding:4px 12px 10px!important;margin:0 0 10px!important;box-shadow:inset 0 1px 0 rgba(255,255,255,.04)!important}
530
+ .param-group:before{content:"";position:absolute;left:12px;right:12px;top:0;height:1px;background:linear-gradient(90deg,transparent,rgba(var(--acc),.7),transparent)}
531
+ .param-group>div,.param-group .form,.param-group .block{background:transparent!important;border:0!important}
532
+ .param-group>button,.param-group>.label-wrap,.param-group button.label-wrap{display:flex!important;align-items:center!important;gap:10px!important;width:100%!important;font:500 13px/1.2 var(--sans)!important;letter-spacing:0;color:var(--text)!important;background:transparent!important;border:0!important;padding:10px 0 6px!important}
533
+ .param-group>button:before,.param-group>.label-wrap:before,.param-group button.label-wrap:before{content:"";width:8px;height:8px;border-radius:50%;flex:none;background:rgb(var(--acc));box-shadow:0 0 10px rgba(var(--acc),.8)}
534
+ .param-group .label-wrap .icon,.param-group>button span.icon{color:rgb(var(--acc))!important;margin-left:auto}
535
+ .param-group input[type="range"]{--slider-color:rgb(var(--acc))!important;accent-color:rgb(var(--acc))}
536
+ .param-group input[type="range"]::-webkit-slider-thumb{background:rgb(var(--acc))!important;box-shadow:0 0 0 4px rgba(var(--acc),.18),0 2px 6px rgba(0,0,0,.6)!important}
537
+ .param-group input[type="range"]::-moz-range-thumb{background:rgb(var(--acc))!important}
538
+ .param-group input[type="range"]::-moz-range-progress{background:rgb(var(--acc))!important}
539
+ .param-group label:has(>input[type="radio"]:checked),.param-group label.selected:has(>input[type="radio"]){background:rgba(var(--acc),.22)!important;color:#fff!important}
540
+ .param-group input[type="number"]:focus,.param-group input[type="text"]:focus{border-color:rgba(var(--acc),.6)!important}
541
  .control-panel [data-testid="block-info"],.control-panel label>span{font-size:12.5px!important;color:#D8D5CF!important}
542
  .control-panel [data-testid="block-info"]+div,.control-panel .info{color:var(--muted)!important}
543
  .control-panel input[type="number"]{font:400 12px var(--mono)!important;background:rgba(255,255,255,.04)!important;border:1px solid var(--line)!important;border-radius:6px!important;color:var(--text)!important}
 
656
 
657
  /* methods */
658
  .methods{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px;margin-top:48px}
659
+ .m-col:nth-child(1){--acc:108,142,245}.m-col:nth-child(2){--acc:95,184,138}.m-col:nth-child(3){--acc:179,154,232}.m-col:nth-child(4){--acc:217,164,65}
660
+ .m-col{position:relative;overflow:hidden;min-width:0;padding:20px;background:radial-gradient(420px 180px at 0% 0%,rgba(var(--acc),.14),transparent 70%),var(--card-bg)!important;border-color:rgba(var(--acc),.16)!important}
661
+ .m-col:before{content:"";position:absolute;left:20px;right:20px;top:0;height:1px;background:linear-gradient(90deg,transparent,rgba(var(--acc),.8),transparent)}
662
+ .m-num{display:inline-flex;align-items:center;gap:7px;font:500 10.5px var(--mono);color:rgb(var(--acc));padding:4px 9px;border-radius:999px;background:rgba(var(--acc),.12);border:1px solid rgba(var(--acc),.25)}
663
+ .m-num:before{content:"";width:5px;height:5px;border-radius:50%;background:rgb(var(--acc));box-shadow:0 0 8px rgb(var(--acc))}
664
+ .m-col .m-list b{color:rgb(var(--acc))!important}
665
+ .m-col .fx{border-color:rgba(var(--acc),.25)!important;background:rgba(var(--acc),.06)!important}
666
+ .m-col .refs li::marker{color:rgb(var(--acc))}
667
  .gradio-container .m-col h3{margin:12px 0 10px!important;font:500 15px/1.3 var(--sans)!important;color:var(--text)!important}
668
  .gradio-container .m-col p{font-size:13px;line-height:1.6;color:var(--text-2);margin:0 0 10px!important;text-wrap:pretty}
669
  .fx{font:400 12.5px var(--mono);color:var(--text);padding:10px 12px;margin:4px 0 10px;border-radius:8px;background:rgba(0,0,0,.28);border:1px solid var(--line);white-space:nowrap;overflow-x:auto}
 
717
  <div class="intro">
718
  <div class="eyebrow">A laboratory for collective opinion</div>
719
  <h1>How opinions <em>move</em> through a network.</h1>
720
+ <p>Set up a synthetic population, choose who talks to whom, add confirmation bias, committed minorities or a persistent external signal — then watch local influence rules produce consensus, drift or division.</p>
721
  </div>
722
  """
723
 
 
799
  with gr.Row(equal_height=False, elem_classes=["lab-row"]):
800
  with gr.Column(scale=3, min_width=300, elem_classes=["control-panel"]):
801
  gr.HTML('<div class="ctl-head"><strong>Parameters</strong><p>Deterministic for a fixed seed.</p></div>')
802
+ with gr.Accordion("Population & network", open=True, elem_classes=["param-group", "pg-pop"]):
803
  n_agents = gr.Radio([100, 500, 1000], value=100, label="Population size")
804
  network = gr.Dropdown(["Random", "Small World", "Scale Free"], value="Small World", label="Network structure")
805
  initial_opinion = gr.Dropdown(["Random", "Neutral", "Polarized"], value="Random", label="Initial opinion state")
806
+ with gr.Accordion("Dynamics", open=True, elem_classes=["param-group", "pg-dyn"]):
807
  confirmation_bias = gr.Slider(0, 1, value=0.45, step=0.01, label="Confirmation bias (β)", info="Suppresses influence from dissimilar neighbours.")
808
  social_influence = gr.Slider(0, 1, value=0.45, step=0.01, label="Social influence (α)", info="Speed of movement toward the neighbourhood target.")
809
  stubborn_fraction = gr.Slider(0, 0.30, value=0.05, step=0.01, label="Stubborn agents", info="Share of agents that never update.")
810
  stubborn_mode = gr.Dropdown(["Keep initial", "Positive (+1)", "Negative (-1)", "Split extremes"], value="Split extremes", label="Stubborn stance")
811
+ with gr.Accordion("External signal", open=False, elem_classes=["param-group", "pg-sig"]):
812
  misinformation_exposure = gr.Slider(0, 1, value=0.25, step=0.01, label="Misinformation exposure", info="Share of adaptive agents receiving the signal.")
813
  misinformation_strength = gr.Slider(0, 1, value=0.35, step=0.01, label="Signal strength")
814
  misinformation_direction = gr.Radio(["Positive (+1)", "Negative (-1)"], value="Positive (+1)", label="Signal direction")
815
+ with gr.Accordion("Run settings", open=False, elem_classes=["param-group", "pg-run"]):
816
  noise = gr.Slider(0, 0.20, value=0.02, step=0.005, label="Random noise (σ)")
817
  steps = gr.Slider(50, 300, value=120, step=10, label="Simulation horizon (steps)")
818
  seed = gr.Number(value=42, precision=0, label="Random seed")