10081008 }
10091009 window . renderStoryTier = renderStoryTier ;
10101010
1011- function setActiveTier ( tier ) {
1011+ function updateTierInUrl ( tier ) {
1012+ if ( ! window . history || typeof window . history . replaceState !== "function" ) {
1013+ return ;
1014+ }
1015+ const params = new URLSearchParams ( window . location . search ) ;
1016+ params . set ( "tier" , tier ) ;
1017+ const query = params . toString ( ) ;
1018+ window . history . replaceState ( { } , "" , window . location . pathname + ( query ? "?" + query : "" ) ) ;
1019+ }
1020+
1021+ function setActiveTier ( tier , options = { } ) {
10121022 const validTiers = [ "story" , "explorer" , "observatory" ] ;
10131023 if ( ! validTiers . includes ( tier ) ) return ;
10141024
10151025 document . body . dataset . tier = tier ;
10161026 const tierButtons = Array . from ( document . querySelectorAll ( ".tier-button" ) ) ;
1017- tierButtons . forEach ( ( btn ) => btn . classList . toggle ( "is-active" , btn . dataset . tier === tier ) ) ;
1027+ tierButtons . forEach ( ( btn ) => {
1028+ const isActive = btn . dataset . tier === tier ;
1029+ btn . classList . toggle ( "is-active" , isActive ) ;
1030+ btn . setAttribute ( "aria-selected" , isActive ? "true" : "false" ) ;
1031+ } ) ;
10181032
10191033 const observatorySubtabs = document . getElementById ( "observatory-subtabs" ) ;
10201034 if ( observatorySubtabs ) {
@@ -1038,8 +1052,26 @@ function setActiveTier(tier) {
10381052 applyShellMode ( "observatory" , { updateUrl : false } ) ;
10391053 }
10401054 }
1055+
1056+ if ( options . updateUrl !== false ) {
1057+ updateTierInUrl ( tier ) ;
1058+ }
1059+ }
1060+
1061+ window . setActiveTier = setActiveTier ;
1062+
1063+ function applyTierFromUrl ( ) {
1064+ const params = new URLSearchParams ( window . location . search ) ;
1065+ const tier = params . get ( "tier" ) ;
1066+ if ( tier ) {
1067+ setActiveTier ( tier , { updateUrl : false } ) ;
1068+ return true ;
1069+ }
1070+ return false ;
10411071 }
10421072
1073+ window . applyTierFromUrl = applyTierFromUrl ;
1074+
10431075 async function initializePolyglotStudioVisualization ( entityId ) {
10441076 try {
10451077 const container = document . getElementById ( "polyglot-studio-visualization" ) ;
@@ -4405,6 +4437,9 @@ function setActiveTier(tier) {
44054437 return false ;
44064438 }
44074439 await applyShellMode ( mode , { updateUrl : false } ) ;
4440+ if ( ! params . get ( "tier" ) ) {
4441+ setActiveTier ( mode === "recit" ? "story" : "observatory" , { updateUrl : false } ) ;
4442+ }
44084443 return true ;
44094444 }
44104445
@@ -4546,35 +4581,61 @@ function setActiveTier(tier) {
45464581
45474582 // Search mode toggle in Explorer panel
45484583 let currentSearchMode = "entity" ;
4584+ window . getActiveSearchMode = function getActiveSearchMode ( ) {
4585+ return currentSearchMode ;
4586+ } ;
4587+
4588+ function updateSearchModeSurface ( mode ) {
4589+ document . querySelectorAll ( ".search-mode-btn" ) . forEach ( ( button ) => {
4590+ const isActive = button . dataset . searchMode === mode ;
4591+ button . classList . toggle ( "is-active" , isActive ) ;
4592+ button . setAttribute ( "aria-pressed" , isActive ? "true" : "false" ) ;
4593+ } ) ;
4594+ const hintEl = document . getElementById ( "search-mode-hint" ) ;
4595+ const searchInput = document . getElementById ( "search-input" ) ;
4596+ const hints = {
4597+ entity : "Search for any movement, artist, artwork, museum, or theme." ,
4598+ subject : "Enter a subject such as dog, cat, flower, sea, or portrait to find artworks depicting it." ,
4599+ nationality : "Enter a country to discover artists from that place. This guided query is staged next." ,
4600+ material : "Enter a material or technique such as oil, marble, bronze, or watercolor. This guided query is staged next."
4601+ } ;
4602+ const placeholders = {
4603+ entity : "Search movements, artists, works..." ,
4604+ subject : "Artworks depicting dog, cat, flower..." ,
4605+ nationality : "Artists from France, Japan, Mexico..." ,
4606+ material : "Works made with oil, marble, bronze..."
4607+ } ;
4608+ if ( hintEl ) {
4609+ hintEl . textContent = hints [ mode ] || hints . entity ;
4610+ }
4611+ if ( searchInput ) {
4612+ searchInput . placeholder = placeholders [ mode ] || placeholders . entity ;
4613+ }
4614+ }
4615+
45494616 document . addEventListener ( "click" , ( e ) => {
45504617 const btn = e . target . closest ( ".search-mode-btn" ) ;
45514618 if ( ! btn ) return ;
45524619 const mode = btn . dataset . searchMode ;
45534620 if ( ! mode ) return ;
45544621 currentSearchMode = mode ;
4555- document . querySelectorAll ( ".search-mode-btn" ) . forEach ( ( b ) => {
4556- b . classList . toggle ( "is-active" , b . dataset . searchMode === mode ) ;
4557- } ) ;
4558- const hintEl = document . getElementById ( "search-mode-hint" ) ;
4559- const hints = {
4560- entity : "Search for any movement, artist, or artwork" ,
4561- "artworks-of" : "Enter an artist name to see their artworks" ,
4562- "artists-from" : "Enter a country to discover its artists" ,
4563- "by-material" : "Enter a material (oil, marble, bronze…)"
4564- } ;
4565- if ( hintEl ) hintEl . textContent = hints [ mode ] || "" ;
4622+ updateSearchModeSurface ( mode ) ;
45664623 } ) ;
45674624
45684625 window . searchEntities = async function searchEntities ( query ) {
45694626 if ( ! query || query . length < 2 ) return [ ] ;
45704627 const lang = runtimeState . currentLanguage || "fr" ;
4628+ const mode = typeof window . getActiveSearchMode === "function" ? window . getActiveSearchMode ( ) : currentSearchMode ;
45714629 const queryLower = query . toLowerCase ( ) ;
45724630 const seen = new Set ( ) ;
45734631 const results = [ ] ;
4574- for ( const node of browserAdapterState . graphe . noeuds . values ( ) ) {
4575- if ( node . etiquette && node . etiquette . toLowerCase ( ) . includes ( queryLower ) ) {
4576- seen . add ( node . id ) ;
4577- results . push ( { id : node . id , label : node . etiquette , description : "(dans le graphe chargé)" , entityType : node . type || "" } ) ;
4632+
4633+ if ( mode === "entity" ) {
4634+ for ( const node of browserAdapterState . graphe . noeuds . values ( ) ) {
4635+ if ( node . etiquette && node . etiquette . toLowerCase ( ) . includes ( queryLower ) ) {
4636+ seen . add ( node . id ) ;
4637+ results . push ( { id : node . id , label : node . etiquette , description : "(dans le graphe chargé)" , entityType : node . type || "" , primaryAction : "Open" } ) ;
4638+ }
45784639 }
45794640 }
45804641 try {
@@ -4585,7 +4646,21 @@ function setActiveTier(tier) {
45854646 const id = item . id || "" ;
45864647 if ( id && ! seen . has ( id ) ) {
45874648 seen . add ( id ) ;
4588- results . push ( { id, label : item . label || id , description : item . description || "" , entityType : "" } ) ;
4649+ let entityType = "" ;
4650+ let primaryAction = "Open" ;
4651+ let description = item . description || "" ;
4652+ if ( mode === "subject" ) {
4653+ entityType = "subject" ;
4654+ primaryAction = "Find artworks" ;
4655+ description = description ? description + " · subject search" : "Subject search" ;
4656+ } else if ( mode === "nationality" ) {
4657+ primaryAction = "Use as country" ;
4658+ description = description ? description + " · artists-by-place is next" : "Artists-by-place is next" ;
4659+ } else if ( mode === "material" ) {
4660+ primaryAction = "Use as material" ;
4661+ description = description ? description + " · material query is next" : "Material query is next" ;
4662+ }
4663+ results . push ( { id, label : item . label || id , description, entityType, searchMode : mode , primaryAction } ) ;
45894664 }
45904665 }
45914666 } catch ( e ) {
@@ -4597,5 +4672,7 @@ function setActiveTier(tier) {
45974672 buildShellFilter ( ) ;
45984673 loadQueryInventory ( ) ;
45994674 updateLanguageSurface ( "fr" ) ;
4675+ updateSearchModeSurface ( currentSearchMode ) ;
46004676 // Render Story tier content on load (body starts as data-tier="story")
46014677 renderStoryTier ( ) ;
4678+ applyTierFromUrl ( ) ;
0 commit comments