107107 .info h2 { color : # d4a050 ; font-size : 0.95em ; letter-spacing : 4px ; text-transform : uppercase; margin : 18px 0 8px ; }
108108 .info strong { color : # f0d89c ; }
109109 .add-row { margin : 6px 0 ; }
110+ # shareBtn .pulse { animation : sharePulse 1.2s ease-in-out infinite; border-color : # d4a050 ; color : # ffe8a8 ; }
111+ @keyframes sharePulse { 0% , 100% { box-shadow : 0 0 0 0 rgba (212 , 160 , 80 , 0.5 ); } 50% { box-shadow : 0 0 0 8px rgba (212 , 160 , 80 , 0 ); } }
112+ # shareToast { display : none; margin : 12px auto 0 ; max-width : 320px ; padding : 10px 14px ; background : # 1a1410 ; border : 1px solid # 5a4028 ; border-radius : 6px ; color : # e8d8b8 ; font-size : 0.82em ; line-height : 1.5 ; }
113+ # shareToast .show { display : block; }
114+ # shareToast button { margin-top : 8px ; width : 100% ; }
115+ .daily-sibling { margin : 0 0 14px ; font-size : 0.78em ; letter-spacing : 2px ; color : # 8a7858 ; }
116+ .daily-sibling a { color : # 94c3e8 ; text-decoration : none; }
117+ .daily-sibling a : hover { color : # ffd896 ; }
110118</ style >
111119</ head >
112120< body >
113121< div id ="wrap ">
114122 < h1 > DRIFT</ h1 >
115123 < div class ="tag "> DAILY WORD LADDER</ div >
124+ < div class ="daily-sibling "> Also play today's < a href ="Wordform.html "> Wordform</ a > · five letters, six guesses</ div >
116125 < div class ="theme " id ="theme "> Loading…</ div >
117126 < div class ="controls ">
118127 < button id ="dailyBtn " class ="active "> DAILY</ button >
@@ -127,6 +136,7 @@ <h1>DRIFT</h1>
127136 < button id ="rmRow "> – REMOVE STEP</ button >
128137 </ div >
129138 < div id ="msg "> </ div >
139+ < div id ="shareToast "> < span id ="shareToastText "> </ span > < button type ="button " id ="shareToastBtn "> Share result</ button > </ div >
130140 < div class ="stats "> STREAK < span id ="streak "> 0</ span > · SOLVES < span id ="solves "> 0</ span > </ div >
131141 < div id ="kb "> </ div >
132142 < nav > < a href ="index.html "> All games</ a > · < a href ="Wordform.html "> Wordform</ a > · < a href ="Sudoku.html "> Sudoku</ a > </ nav >
@@ -347,23 +357,48 @@ <h2>Tips</h2>
347357 }
348358 }
349359 updateStats ( ) ;
360+ if ( mode === 'daily' ) promptShare ( ) ;
350361 }
351362 function updateStats ( ) {
352363 const s = JSON . parse ( localStorage . getItem ( 'drift_stats' ) || '{"solves":0,"streak":0}' ) ;
353364 $ ( 'streak' ) . textContent = s . streak ; $ ( 'solves' ) . textContent = s . solves ;
354365 }
355- async function share ( ) {
356- if ( ! solved ) { $ ( 'msg' ) . textContent = 'SOLVE FIRST' ; return ; }
366+ const SHARE_URL = 'https://boardgaminghub.com/Drift.html' ;
367+ function shareText ( ) {
368+ if ( ! solved ) return '' ;
357369 const head = ( mode === 'daily' ? 'Drift #' + dailyIndex ( ) : 'Drift RANDOM' ) + ' — ' + ( rows . length - 1 ) + ' steps' + ( hintsUsed ? ' (+' + hintsUsed + ' hints)' : '' ) ;
358370 const grid = rows . map ( ( r , i ) => {
359371 if ( i === 0 || i === rows . length - 1 ) return '⬜⬜⬜⬜' ;
360372 const above = rows [ i - 1 ] ;
361373 return r . map ( ( ch , c ) => ch === above [ c ] ? '⬛' : '🟨' ) . join ( '' ) ;
362374 } ) . join ( '\n' ) ;
363- const text = head + '\n' + grid + '\nboardgaminghub.com/Drift.html' ;
364- try { await navigator . clipboard . writeText ( text ) ; $ ( 'msg' ) . textContent = 'COPIED' ; }
365- catch ( e ) { $ ( 'msg' ) . textContent = 'COPY FAILED' ; }
375+ return head + '\n' + grid + '\n' + SHARE_URL ;
366376 }
377+ async function doShare ( ) {
378+ const text = shareText ( ) ;
379+ if ( ! text ) { $ ( 'msg' ) . textContent = 'SOLVE FIRST' ; return ; }
380+ if ( navigator . share ) {
381+ try {
382+ await navigator . share ( { title : 'Drift' , text : text , url : SHARE_URL } ) ;
383+ $ ( 'msg' ) . textContent = 'SHARED' ;
384+ return ;
385+ } catch ( e ) { if ( e && e . name === 'AbortError' ) return ; }
386+ }
387+ try {
388+ await navigator . clipboard . writeText ( text ) ;
389+ $ ( 'msg' ) . textContent = 'COPIED — paste anywhere' ;
390+ } catch ( e ) { $ ( 'msg' ) . textContent = 'COPY FAILED' ; }
391+ }
392+ function promptShare ( ) {
393+ $ ( 'shareBtn' ) . classList . add ( 'pulse' ) ;
394+ const toast = $ ( 'shareToast' ) ;
395+ const tbtn = $ ( 'shareToastBtn' ) ;
396+ $ ( 'shareToastText' ) . textContent = 'Solved! Share your ladder grid — no spoilers in the words.' ;
397+ toast . classList . add ( 'show' ) ;
398+ tbtn . textContent = navigator . share ? 'Share result' : 'Copy result' ;
399+ tbtn . onclick = ( ) => { doShare ( ) ; toast . classList . remove ( 'show' ) ; $ ( 'shareBtn' ) . classList . remove ( 'pulse' ) ; } ;
400+ }
401+ async function share ( ) { await doShare ( ) ; }
367402
368403 $ ( 'dailyBtn' ) . onclick = ( ) => { mode = 'daily' ; $ ( 'dailyBtn' ) . classList . add ( 'active' ) ; $ ( 'randomBtn' ) . classList . remove ( 'active' ) ; init ( ) ; } ;
369404 $ ( 'randomBtn' ) . onclick = ( ) => { mode = 'random' ; $ ( 'randomBtn' ) . classList . add ( 'active' ) ; $ ( 'dailyBtn' ) . classList . remove ( 'active' ) ; init ( ) ; } ;
0 commit comments