<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>体験 &#8211; Tranquilvæj</title>
	<atom:link href="https://tranquilguides.com/tag/experience/feed/" rel="self" type="application/rss+xml" />
	<link>https://tranquilguides.com</link>
	<description>記憶と身体、時間と不在をめぐる体験</description>
	<lastBuildDate>Mon, 12 Oct 2026 08:18:57 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.4</generator>

<image>
	<url>https://i0.wp.com/tranquilguides.com/wp-content/uploads/2026/01/cropped-IMG_3364.jpeg?fit=32%2C32&#038;ssl=1</url>
	<title>体験 &#8211; Tranquilvæj</title>
	<link>https://tranquilguides.com</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">251661265</site>	<item>
		<title>二つだった</title>
		<link>https://tranquilguides.com/1-2/</link>
					<comments>https://tranquilguides.com/1-2/#respond</comments>
		
		<dc:creator><![CDATA[案内人のアシカ]]></dc:creator>
		<pubDate>Sat, 17 Oct 2026 15:01:00 +0000</pubDate>
				<category><![CDATA[生存ログ]]></category>
		<category><![CDATA[体験]]></category>
		<category><![CDATA[依存]]></category>
		<category><![CDATA[境界]]></category>
		<category><![CDATA[抽象]]></category>
		<category><![CDATA[接続]]></category>
		<category><![CDATA[関係]]></category>
		<guid isPermaLink="false">https://tranquilguides.com/?p=3125</guid>

					<description><![CDATA[<p><img src="https://i0.wp.com/tranquilguides.com/wp-content/uploads/2026/10/Ethereal-Fusion-of-Luminous-Orbs.png?fit=1024%2C576&ssl=1" class="webfeedsFeaturedVisual" /></p>二つの存在が近づき、触れたあと、片方はもう単独では動けない。それでも、消えたわけではない。]]></description>
										<content:encoded><![CDATA[<p><img src="https://i0.wp.com/tranquilguides.com/wp-content/uploads/2026/10/Ethereal-Fusion-of-Luminous-Orbs.png?fit=1024%2C576&ssl=1" class="webfeedsFeaturedVisual" /></p>
<style>
:root{
  --tgwi-bg:#f5f4f0;
  --tgwi-ink:#3f474c;
  --tgwi-a:#8499a7;
  --tgwi-b:#555e64;
  --tgwi-focus:#738b9b;
}
.tgwi-wrap,
.tgwi-wrap *{box-sizing:border-box}
.tgwi-wrap{
  width:100%;
  background:var(--tgwi-bg);
  color:var(--tgwi-ink);
  font-family:system-ui,-apple-system,"Noto Sans JP",sans-serif;
  overflow-x:hidden;
}
.tgwi-main{
  max-width:980px;
  margin:0 auto;
  padding:clamp(24px,5vw,72px);
}
.tgwi-intro{
  min-height:18vh;
  display:flex;
  align-items:flex-end;
  padding-bottom:clamp(18px,4vh,42px);
}
.tgwi-intro p{
  margin:0;
  font-size:clamp(17px,2.5vw,24px);
  font-weight:350;
  line-height:1.9;
  letter-spacing:.01em;
}
.tgwi-stage{
  position:relative;
  height:min(72vh,720px);
  min-height:430px;
  touch-action:pan-y;
  overflow:hidden;
  outline:none;
}
.tgwi-stage svg{
  display:block;
  width:100%;
  height:100%;
  overflow:visible;
  touch-action:pan-y;
}
.tgwi-stage.tgwi-dragging,
.tgwi-stage.tgwi-dragging svg{touch-action:none}
.tgwi-stage.tgwi-over-left{cursor:grab}
.tgwi-stage.tgwi-over-left.tgwi-dragging,
.tgwi-stage.tgwi-over-joined.tgwi-dragging{cursor:grabbing}
.tgwi-stage.tgwi-over-joined{cursor:grab}
.tgwi-after{
  min-height:46vh;
  display:flex;
  flex-direction:column;
  justify-content:center;
  align-items:flex-start;
  gap:34px;
}
.tgwi-after[hidden]{display:none}
.tgwi-after p{
  max-width:27em;
  margin:0;
  font-size:clamp(18px,2.6vw,25px);
  font-weight:350;
  line-height:2.2;
}
.tgwi-replay{
  appearance:none;
  border:0;
  background:transparent;
  color:inherit;
  padding:2px 0;
  font:inherit;
  font-size:12px;
  letter-spacing:.08em;
  cursor:pointer;
  border-bottom:1px solid currentColor;
}
.tgwi-replay:focus-visible{
  outline:2px solid var(--tgwi-focus);
  outline-offset:4px;
}
.tgwi-sr-only{
  position:absolute!important;
  width:1px!important;
  height:1px!important;
  padding:0!important;
  margin:-1px!important;
  overflow:hidden!important;
  clip:rect(0,0,0,0)!important;
  white-space:nowrap!important;
  border:0!important;
}
#tgwi-left-halo,
#tgwi-joined-halo,
#tgwi-focus-halo{
  pointer-events:none;
  opacity:0;
  fill:none;
  stroke:var(--tgwi-focus);
  vector-effect:non-scaling-stroke;
}
#tgwi-left-hit,
#tgwi-joined-hit{
  fill:transparent;
  stroke:none;
  pointer-events:all;
}
#tgwi-left-halo,
#tgwi-joined-halo{
  stroke-width:1;
  stroke-opacity:.35;
}
#tgwi-focus-halo{
  stroke-width:1.2;
  stroke-opacity:.58;
}
.tgwi-stage.tgwi-over-left #tgwi-left-halo,
.tgwi-stage.tgwi-pressed-left #tgwi-left-halo{opacity:.72}
.tgwi-stage.tgwi-over-joined #tgwi-joined-halo,
.tgwi-stage.tgwi-pressed-joined #tgwi-joined-halo{opacity:.58}
.tgwi-stage:focus-visible #tgwi-focus-halo{opacity:.8}

@media(max-width:600px){
  .tgwi-main{padding-left:18px;padding-right:18px}
  .tgwi-stage{height:66vh;min-height:400px}
  .tgwi-intro{min-height:14vh;padding-bottom:14px}
  .tgwi-after{min-height:42vh}
}
@media(prefers-reduced-motion:reduce){
  .tgwi-stage *{animation:none!important;transition:none!important}
}
</style>

<div class="tgwi-wrap">
  <main class="tgwi-main">
    <section class="tgwi-intro">
      <p>はじめは、別々だった。</p>
    </section>

    <section
      id="tgwi-stage"
      class="tgwi-stage"
      tabindex="0"
      role="group"
      aria-label="二つの形があります。左の形はドラッグ、タップ、クリック、または左右の矢印キーで動かせます。"
    >
      <svg id="tgwi-art" viewBox="0 0 800 480" aria-hidden="true">
        <g id="tgwi-left-group">
          <circle id="tgwi-left-halo" cx="220" cy="240" r="50"></circle>
          <circle id="tgwi-focus-halo" cx="220" cy="240" r="44"></circle>
          <circle id="tgwi-left" cx="220" cy="240" r="34" fill="#8499a7"></circle>
          <circle id="tgwi-left-hit" cx="220" cy="240" r="52"></circle>
        </g>

        <g id="tgwi-right-group">
          <ellipse id="tgwi-right" cx="580" cy="240" rx="61" ry="61" fill="none" stroke="#555e64" stroke-width="1.5" vector-effect="non-scaling-stroke"></ellipse>
          <circle id="tgwi-trace" cx="580" cy="240" r="5" fill="#8499a7" opacity="0"></circle>
          <ellipse id="tgwi-joined-halo" cx="580" cy="240" rx="82" ry="78"></ellipse>
          <ellipse id="tgwi-joined-hit" cx="580" cy="240" rx="86" ry="82"></ellipse>
        </g>
      </svg>

      <span id="tgwi-live" class="tgwi-sr-only" role="status" aria-live="polite"></span>
    </section>

    <section id="tgwi-after" class="tgwi-after" hidden>
      <p>どちらに残ったのだろう。</p>
      <button id="tgwi-replay" class="tgwi-replay" type="button">もう一度</button>
    </section>
  </main>
</div>

<script>
document.addEventListener('DOMContentLoaded', function(){
  'use strict';

  var stage=document.getElementById('tgwi-stage');
  var leftGroup=document.getElementById('tgwi-left-group');
  var rightGroup=document.getElementById('tgwi-right-group');
  var left=document.getElementById('tgwi-left');
  var leftHalo=document.getElementById('tgwi-left-halo');
  var focusHalo=document.getElementById('tgwi-focus-halo');
  var leftHit=document.getElementById('tgwi-left-hit');
  var right=document.getElementById('tgwi-right');
  var trace=document.getElementById('tgwi-trace');
  var joinedHalo=document.getElementById('tgwi-joined-halo');
  var joinedHit=document.getElementById('tgwi-joined-hit');
  var live=document.getElementById('tgwi-live');
  var after=document.getElementById('tgwi-after');
  var replay=document.getElementById('tgwi-replay');

  if(!stage){return;}

  var reduced=window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  var START_X=220;
  var START_RIGHT_X=580;

  var phase='apart';
  var x=START_X;
  var rightX=START_RIGHT_X;
  var joinedBaseX=570;
  var joinedOffset=0;
  var dragging=false;
  var draggingJoined=false;
  var pointerCandidate=null;
  var pointerStartX=0;
  var pointerStartY=0;
  var pointerLastSvgX=0;
  var joinedGrabMode='body';
  var pressedScale=1;
  var joinedPressed=0;
  var raf=0;
  var loopRaf=0;
  var afterTimer=0;

  function clamp(n,min,max){
    return Math.max(min,Math.min(max,n));
  }
  function easeOutCubic(t){
    return 1-Math.pow(1-t,3);
  }
  function easeInOut(t){
    if(t<0.5){
      return 4*t*t*t;
    }
    return 1-Math.pow(-2*t+2,3)/2;
  }

  function clientToSvg(clientX,clientY){
    var rect=stage.getBoundingClientRect();
    return {
      x:(clientX-rect.left)/rect.width*800,
      y:(clientY-rect.top)/rect.height*480
    };
  }

  function announce(text){
    live.textContent='';
    requestAnimationFrame(function(){
      live.textContent=text;
    });
  }

  function setLeftGeometry(cx,cy,r){
    left.setAttribute('cx',cx);
    left.setAttribute('cy',cy);
    left.setAttribute('r',r);
    leftHit.setAttribute('cx',cx);
    leftHit.setAttribute('cy',cy);
    leftHalo.setAttribute('cx',cx);
    leftHalo.setAttribute('cy',cy);
    focusHalo.setAttribute('cx',cx);
    focusHalo.setAttribute('cy',cy);
  }

  function setJoinedGeometry(cx,cy,rx,ry){
    right.setAttribute('cx',cx);
    right.setAttribute('cy',cy);
    right.setAttribute('rx',rx);
    right.setAttribute('ry',ry);
    joinedHalo.setAttribute('cx',cx);
    joinedHalo.setAttribute('cy',cy);
    joinedHalo.setAttribute('rx',rx+15);
    joinedHalo.setAttribute('ry',ry+14);
    joinedHit.setAttribute('cx',cx);
    joinedHit.setAttribute('cy',cy);
    joinedHit.setAttribute('rx',rx+19);
    joinedHit.setAttribute('ry',ry+18);
  }

  function apartVisual(time){
    var t=time/1000;
    var proximity=clamp((x-382)/94,0,1);
    var mutual=clamp((x-330)/145,0,1);

    var leftY=reduced?0:Math.sin(t*(1.15-mutual*.18))*3.2;
    var leftBreath=reduced?0:Math.sin(t*(.92-mutual*.12))*.018;
    var rightY=reduced?0:Math.sin(t*(.67+mutual*.08)+1.2)*2.1;
    var rightBreath=reduced?0:Math.sin(t*(.54+mutual*.10)+2.1)*1.15;

    rightX=START_RIGHT_X-(proximity*9);

    var leftR=(34-proximity*1.4)*pressedScale;
    var rightRx=61+rightBreath+proximity*2.6;
    var rightRy=61-rightBreath*.55+proximity*1.1;
    var s=1+leftBreath;
    var compensation=(1-s)*x/s;

    leftGroup.setAttribute(
      'transform',
      'translate(0 '+leftY+') scale('+s+') translate('+compensation+' 0)'
    );
    rightGroup.setAttribute('transform','translate(0 '+rightY+')');

    setLeftGeometry(x,240,leftR);
    setJoinedGeometry(rightX,240,rightRx,rightRy);
    trace.setAttribute('opacity','0');
  }

  function joinedVisual(time){
    var t=time/1000;
    var internalPulse=reduced?0:Math.sin(t*.84)*1.15;
    var drift=reduced?0:Math.sin(t*.48+1.8)*2.2;
    var traceDrift=reduced?0:Math.sin(t*.72+2.4)*4.6;
    var traceLift=reduced?0:Math.sin(t*.91+.2)*1.8;
    var delayedWarp=reduced?0:Math.sin(t*.72+1.1)*1.35;
    var pressWarp=joinedPressed*2.1;

    var cx=joinedBaseX+joinedOffset;
    var cy=240+drift*.35;

    rightGroup.setAttribute('transform','');

    setJoinedGeometry(
      cx+delayedWarp*.18,
      cy,
      69.2+internalPulse+pressWarp+delayedWarp*.32,
      64.9-internalPulse*.65-pressWarp*.28-delayedWarp*.18
    );

    right.setAttribute('transform','rotate('+(delayedWarp*.35)+' '+cx+' '+cy+')');
    trace.setAttribute('cx',String(cx-36+traceDrift));
    trace.setAttribute('cy',String(240+drift*1.25+traceLift));
    trace.setAttribute('r',String(6.15+internalPulse*.08));
    trace.setAttribute('opacity','1');
  }

  function loop(time){
    if(phase==='apart'){
      apartVisual(time);
    }else if(phase==='joined'){
      joinedVisual(time);
    }
    loopRaf=requestAnimationFrame(loop);
  }

  function updateApart(nx){
    if(phase!=='apart'){return;}

    var raw=clamp(nx,86,491);
    var resistance=0;

    if(raw>426){
      resistance=Math.pow((raw-426)/65,1.72)*14.5;
    }

    x=raw-resistance;

    if(x>=474.5){
      fuse();
    }
  }

  function fuse(){
    if(phase!=='apart'){return;}

    phase='fusing';
    dragging=false;
    pointerCandidate=null;
    pressedScale=1;

    stage.classList.remove('tgwi-dragging');
    stage.classList.remove('tgwi-pressed-left');
    stage.classList.remove('tgwi-over-left');

    announce('二つの形が触れ、状態が変わり始めました。');

    cancelAnimationFrame(loopRaf);

    var duration=reduced?0:3000;
    var start=performance.now();
    var startLeftX=x;
    var startRightX=rightX;

    function frame(now){
      var p=duration?clamp((now-start)/duration,0,1):1;
      var q=0;

      if(p<.20){
        q=0;
      }else if(p<.80){
        q=easeInOut((p-.20)/.60);
      }else{
        q=.94+.06*easeOutCubic((p-.80)/.20);
      }

      var contactWobble=reduced?0:Math.sin(p*Math.PI*5.2)*(1-p)*2.0;
      var leftCx=startLeftX+(535-startLeftX)*q;
      var leftR=34-(27.6*q);
      var rightCx=startRightX+(joinedBaseX-startRightX)*q;
      var rightRx=61+(8.5*q)+contactWobble;
      var rightRy=61+(3.5*q)-contactWobble*.45;
      var traceOpacity=clamp((q-.28)/.72,0,1);

      leftGroup.setAttribute('transform','');
      rightGroup.setAttribute('transform','');

      setLeftGeometry(leftCx,240,leftR);
      left.setAttribute('opacity',String(1-q*.92));
      setJoinedGeometry(rightCx,240,rightRx,rightRy);

      trace.setAttribute('cx',String(rightCx-36*q));
      trace.setAttribute('cy','240');
      trace.setAttribute('r',String(4+2.2*q));
      trace.setAttribute('opacity',String(traceOpacity));

      if(p<1){
        raf=requestAnimationFrame(frame);
      }else{
        phase='joined';
        left.setAttribute('opacity','0');
        leftHit.style.pointerEvents='none';
        joinedOffset=0;

        stage.setAttribute(
          'aria-label',
          '結合後の形です。ドラッグ、タップ、クリック、または左右の矢印キーで動かせますが、内部に残った部分だけを切り離すことはできません。'
        );

        announce('結合しました。内部に残った部分は、外側の形と一緒にしか動かせません。');

        clearTimeout(afterTimer);
        afterTimer=setTimeout(function(){
          after.hidden=false;
        },reduced?0:4200);

        loopRaf=requestAnimationFrame(loop);
      }
    }

    raf=requestAnimationFrame(frame);
  }

  function moveJoinedBy(delta,mode){
    if(phase!=='joined'){return;}

    var effectiveMode=mode||'body';
    var factor=.34;

    if(effectiveMode==='trace'){
      factor=.22;
    }

    joinedOffset=clamp(joinedOffset+delta*factor,-72,72);

    if(effectiveMode==='trace'){
      joinedPressed=clamp(Math.abs(delta)/18,0,1);
    }
  }

  function startCandidate(kind,e){
    var p=clientToSvg(e.clientX,e.clientY);
    pointerCandidate=kind;

    if(kind==='joined'){
      var tx=parseFloat(trace.getAttribute('cx')||'0');
      var ty=parseFloat(trace.getAttribute('cy')||'0');
      var distance=Math.hypot(p.x-tx,p.y-ty);

      if(distance<=28){
        joinedGrabMode='trace';
      }else{
        joinedGrabMode='body';
      }
    }

    pointerStartX=e.clientX;
    pointerStartY=e.clientY;
    pointerLastSvgX=p.x;

    if(kind==='left'){
      pressedScale=.94;
      stage.classList.add('tgwi-pressed-left');
    }else{
      joinedPressed=1;
      stage.classList.add('tgwi-pressed-joined');
    }
  }

  function clearPress(){
    pressedScale=1;
    joinedPressed=0;
    stage.classList.remove('tgwi-pressed-left');
    stage.classList.remove('tgwi-pressed-joined');
  }

  leftHit.addEventListener('pointerenter',function(){
    if(phase==='apart'){
      stage.classList.add('tgwi-over-left');
    }
  });

  leftHit.addEventListener('pointerleave',function(){
    if(!dragging){
      stage.classList.remove('tgwi-over-left');
    }
  });

  joinedHit.addEventListener('pointerenter',function(){
    if(phase==='joined'){
      stage.classList.add('tgwi-over-joined');
    }
  });

  joinedHit.addEventListener('pointerleave',function(){
    if(!draggingJoined){
      stage.classList.remove('tgwi-over-joined');
    }
  });

  leftHit.addEventListener('pointerdown',function(e){
    if(phase!=='apart'){return;}
    startCandidate('left',e);
  });

  joinedHit.addEventListener('pointerdown',function(e){
    if(phase!=='joined'){return;}
    startCandidate('joined',e);
  });

  stage.addEventListener('pointermove',function(e){
    if(!pointerCandidate){
      if(!dragging){
        if(!draggingJoined){
          return;
        }
      }
    }

    var dx=e.clientX-pointerStartX;
    var dy=e.clientY-pointerStartY;

    if(pointerCandidate){
      if(!dragging){
        if(!draggingJoined){
          if(Math.hypot(dx,dy)<6){
            return;
          }

          if(e.pointerType==='touch'){
            if(Math.abs(dy)>Math.abs(dx)*1.15){
              pointerCandidate=null;
              clearPress();
              return;
            }
          }

          try{
            stage.setPointerCapture(e.pointerId);
          }catch(err){}

          stage.classList.add('tgwi-dragging');

          if(pointerCandidate==='left'){
            dragging=true;
          }else{
            draggingJoined=true;
          }

          pointerCandidate=null;
        }
      }
    }

    var p=clientToSvg(e.clientX,e.clientY);

    if(dragging){
      e.preventDefault();
      updateApart(p.x);
    }else if(draggingJoined){
      e.preventDefault();
      var delta=p.x-pointerLastSvgX;
      pointerLastSvgX=p.x;
      moveJoinedBy(delta,joinedGrabMode);
    }
  },{passive:false});

  function endPointer(e){
    var wasCandidate=pointerCandidate;
    var p=clientToSvg(e.clientX,e.clientY);

    if(wasCandidate==='left'){
      if(phase==='apart'){
        updateApart(x+36);
      }
    }else if(wasCandidate==='joined'){
      if(phase==='joined'){
        var cx=joinedBaseX+joinedOffset;
        var direction=1;

        if(p.x<cx){
          direction=-1;
        }

        moveJoinedBy(direction*12,joinedGrabMode);
      }
    }

    dragging=false;
    draggingJoined=false;
    pointerCandidate=null;
    clearPress();
    stage.classList.remove('tgwi-dragging');
  }

  stage.addEventListener('pointerup',endPointer);

  stage.addEventListener('pointercancel',function(){
    dragging=false;
    draggingJoined=false;
    pointerCandidate=null;
    clearPress();
    stage.classList.remove('tgwi-dragging');
  });

  stage.addEventListener('lostpointercapture',function(){
    dragging=false;
    draggingJoined=false;
    pointerCandidate=null;
    clearPress();
    stage.classList.remove('tgwi-dragging');
  });

  stage.addEventListener('keydown',function(e){
    if(e.key!=='ArrowRight'){
      if(e.key!=='ArrowLeft'){
        return;
      }
    }

    e.preventDefault();

    var delta=-24;
    if(e.key==='ArrowRight'){
      delta=24;
    }

    if(phase==='apart'){
      updateApart(x+delta);
    }else if(phase==='joined'){
      moveJoinedBy(delta,joinedGrabMode);
    }
  });

  replay.addEventListener('click',function(){
    cancelAnimationFrame(raf);
    cancelAnimationFrame(loopRaf);
    clearTimeout(afterTimer);

    phase='apart';
    x=START_X;
    rightX=START_RIGHT_X;
    joinedOffset=0;
    dragging=false;
    draggingJoined=false;
    pointerCandidate=null;
    pressedScale=1;
    joinedPressed=0;

    after.hidden=true;

    left.setAttribute('opacity','1');
    leftHit.style.pointerEvents='all';
    leftGroup.setAttribute('transform','');
    rightGroup.setAttribute('transform','');
    right.setAttribute('transform','');

    setLeftGeometry(START_X,240,34);
    setJoinedGeometry(START_RIGHT_X,240,61,61);

    trace.setAttribute('opacity','0');

    stage.className='tgwi-stage';

    stage.setAttribute(
      'aria-label',
      '二つの形があります。左の形はドラッグ、タップ、クリック、または左右の矢印キーで動かせます。'
    );

    announce('最初の状態に戻りました.');

    try{
      stage.focus({preventScroll:true});
    }catch(err){
      stage.focus();
    }

    loopRaf=requestAnimationFrame(loop);
  });

  loopRaf=requestAnimationFrame(loop);
});
</script>



<p class="wp-block-paragraph">二つの存在が近づき、触れ、ひとつの状態になる。<br>そのあとも、消えたはずのものは内部に残り、全体へ作用し続ける。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://tranquilguides.com/1-2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3125</post-id>	</item>
		<item>
		<title>まだ名前のない魔法</title>
		<link>https://tranquilguides.com/unnamed-magic/</link>
					<comments>https://tranquilguides.com/unnamed-magic/#respond</comments>
		
		<dc:creator><![CDATA[案内人のアシカ]]></dc:creator>
		<pubDate>Tue, 06 Oct 2026 15:01:00 +0000</pubDate>
				<category><![CDATA[生存ログ]]></category>
		<category><![CDATA[Web Game]]></category>
		<category><![CDATA[体験]]></category>
		<category><![CDATA[創作]]></category>
		<category><![CDATA[魔法]]></category>
		<guid isPermaLink="false">https://tranquilguides.com/?p=2936</guid>

					<description><![CDATA[<p><img src="https://i0.wp.com/tranquilguides.com/wp-content/uploads/2026/10/IMG_20260924_164432.png?fit=1024%2C683&ssl=1" class="webfeedsFeaturedVisual" /></p>いくつかの質問に答えながら、まだ名前のない「あなたの魔法」の法則を見つけていく。完成した魔法は、記録として持ち帰り、いつものAIでも使えます。]]></description>
										<content:encoded><![CDATA[<p><img src="https://i0.wp.com/tranquilguides.com/wp-content/uploads/2026/10/IMG_20260924_164432.png?fit=1024%2C683&ssl=1" class="webfeedsFeaturedVisual" /></p>
<!--
まだ名前のない魔法 v7.3 / Tranquilvæj
WordPress / SWELL Custom HTML Block
-->

<style>
.tv-magic{
  --tvm-ink:#202624;
  --tvm-muted:rgba(32,38,36,.62);
  --tvm-line:rgba(32,38,36,.13);
  --tvm-bg:#f3f1ea;
  --tvm-surface:rgba(255,255,255,.70);
  --tvm-surface-strong:rgba(255,255,255,.88);
  --tvm-dark:#171b1a;
  width:min(45em,calc(100vw - 1.5em));
  max-width:none;
  margin-left:50%;
  transform:translateX(-50%);
  padding:
    max(2.25em,env(safe-area-inset-top))
    max(1.125em,env(safe-area-inset-right))
    max(7em,env(safe-area-inset-bottom))
    max(1.125em,env(safe-area-inset-left));
  min-width:0;
  min-height:0;
  color:var(--tvm-ink);
  font-family:inherit;
  line-break:strict;
  overflow-wrap:anywhere;
}

.tv-magic{
  /* Tranquil Material System — scoped tokens */
  --tvm-space-0:0;
  --tvm-space-2:0.125em;
  --tvm-space-4:0.25em;
  --tvm-space-8:0.5em;
  --tvm-space-12:0.75em;
  --tvm-space-16:1em;
  --tvm-space-24:1.5em;
  --tvm-space-32:2em;
  --tvm-space-48:3em;
  --tvm-space-64:4em;
  --tvm-space-96:6em;
  --tvm-space-128:8em;

  --tvm-radius-0:0;
  --tvm-radius-6:0.375em;
  --tvm-radius-10:0.625em;
  --tvm-radius-16:1em;
  --tvm-radius-24:1.5em;
  --tvm-radius-pill:62.4375em;

  --tvm-motion-fast:120ms;
  --tvm-motion-base:220ms;
  --tvm-motion-slow:360ms;
  --tvm-ease:cubic-bezier(.2,.8,.2,1);

  --tvm-clear:#fff;
  --tvm-mist:rgba(248,248,247,.82);
  --tvm-veil:rgba(248,248,247,.70);
  --tvm-lens:rgba(248,248,247,.62);

  --tvm-mist-solid:#f1f1ef;
  --tvm-veil-solid:#e8e8e5;
  --tvm-lens-solid:#ddddda;

  --tvm-glass-border:rgba(255,255,255,.72);
  --tvm-glass-edge:rgba(22,22,20,.10);
  --tvm-glass-shadow:0 0.625em 1.875em rgba(22,22,20,.08), inset 0 1px 0 rgba(255,255,255,.74);
  --tvm-focus-ring:0.125em solid currentColor;
  --tvm-focus-offset:0.1875em;

  /* Question screen — em-first relative sizing */
  --tvm-q-header-min-h:2.75em;
  --tvm-q-header-gap:1em;
  --tvm-q-header-bottom:0.55em;
  --tvm-q-meta-size:0.75em;
  --tvm-q-progress-bottom:1.3em;
  --tvm-q-size-min:1.5em;
  --tvm-q-size-max:2.15em;
  --tvm-q-max-width:18.5em;
  --tvm-q-choice-gap:0.5em;
  --tvm-q-choice-top:1.1em;
  --tvm-q-choice-min-h:3.125em;
  --tvm-q-choice-pad-y:0.78em;
  --tvm-q-choice-pad-x:1em;
  --tvm-q-choice-radius:0.875em;
  --tvm-q-back-top:0.75em;
  --tvm-q-focus-hit:2.75em;
  --tvm-q-focus-hit-active:3em;
  --tvm-q-focus-icon:var(--tvm-q-focus-icon-normal);
  --tvm-q-frame-width:31em;
  --tvm-q-progress-width:11.25em;
  --tvm-focus-bg:#f2f1ed;
  --tvm-normal-choice:rgba(255,255,255,.44);
  --tvm-normal-choice-hover:rgba(255,255,255,.62);
  --tvm-normal-choice-border:rgba(32,38,36,.13);
  --tvm-normal-progress-track:rgba(32,38,36,.12);
  --tvm-normal-progress-bar:.52;
  --tvm-normal-meta-opacity:.62;
  --tvm-normal-focus-opacity:.52;

  --tvm-focus-bg:#efeee9;
  --tvm-focus-choice:rgba(255,255,255,.18);
  --tvm-focus-choice-hover:rgba(255,255,255,.34);
  --tvm-focus-choice-selected:rgba(255,255,255,.46);
  --tvm-focus-choice-border:rgba(32,38,36,.08);
  --tvm-focus-progress-track:rgba(32,38,36,.085);
  --tvm-focus-progress-bar:.38;
  --tvm-focus-meta-opacity:.76;
  --tvm-focus-focus-opacity:.92;

  --tvm-q-size-focus-min:1.56em;
  --tvm-q-size-focus-max:2.25em;
  --tvm-q-focus-icon-normal:1.25em;
  --tvm-q-focus-icon-active:1.6em;
}

.tv-magic .tvm-material-mist,
.tv-magic .tvm-language{
  background:var(--tvm-mist-solid);
  border:1px solid var(--tvm-glass-edge);
}

@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))){
  .tv-magic .tvm-material-mist,
  .tv-magic .tvm-language{
    background:var(--tvm-mist);
    -webkit-backdrop-filter:blur(0.5em) saturate(1.02);
    backdrop-filter:blur(0.5em) saturate(1.02);
    border-color:var(--tvm-glass-border);
    box-shadow:var(--tvm-glass-shadow);
  }
}

.tv-magic .tvm-material-veil,
.tv-magic .tvm-btn.is-primary{
  background:var(--tvm-veil-solid);
  border:1px solid var(--tvm-glass-edge);
}

@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))){
  .tv-magic .tvm-material-veil,
  .tv-magic .tvm-btn.is-primary{
    background:var(--tvm-veil);
    -webkit-backdrop-filter:blur(1.125em) saturate(1.06);
    backdrop-filter:blur(1.125em) saturate(1.06);
    border-color:var(--tvm-glass-border);
    box-shadow:var(--tvm-glass-shadow);
  }
}

.tv-magic .tvm-material-lens{
  background:var(--tvm-lens-solid);
}

@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))){
  .tv-magic .tvm-material-lens{
    background:var(--tvm-lens);
    -webkit-backdrop-filter:blur(1.625em) saturate(1.10);
    backdrop-filter:blur(1.625em) saturate(1.10);
  }
}

.tv-magic,
.tv-magic *,
.tv-magic *::before,
.tv-magic *::after{box-sizing:border-box}
.tv-magic button,
.tv-magic textarea{font:inherit}
.tv-magic [hidden]{display:none!important}

.tvm-top{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--tvm-q-header-gap);
  min-height:var(--tvm-q-header-min-h);
  margin-bottom:var(--tvm-q-header-bottom);
  color:var(--tvm-muted);
}
.tvm-question-meta{
  min-width:0;
  overflow-wrap:anywhere;
  font-size:var(--tvm-q-meta-size);
  letter-spacing:.055em;
  font-variant-numeric:tabular-nums;
}
.tvm-question-meta-count{
  opacity:var(--tvm-normal-meta-opacity);
}
.tv-magic.is-focus .tvm-question-meta-count{
  opacity:var(--tvm-focus-meta-opacity);
}
.tvm-screen{animation:tvmFade .22s ease both}

.tvm-spacer{
  display:block;
  width:100%;
  height:0;
  pointer-events:none;
}
.tvm-spacer--sm{height:0.75em}
.tvm-spacer--entry-top{height:4.75em}
.tvm-spacer--hero-lead{height:1.125em}
.tvm-spacer--lead-language{height:1.375em}
.tvm-spacer--language-start{height:1.75em}

.tvm-entry .tvm-hero{
  margin:0;
  max-width:none;
  font-size:clamp(2.125em,4.2vw,3.25em);
}
.tvm-hero-line{display:block}
@media(min-width:48.0625em){
  .tvm-hero-line--keep{white-space:nowrap}
}
.tvm-entry .tvm-lead{margin:0}
.tvm-entry .tvm-language{margin:0}
.tvm-entry .tvm-actions{margin-top:0}
@keyframes tvmFade{
  from{opacity:0;transform:translateY(0.25em)}
  to{opacity:1;transform:none}
}
.tvm-hero{
  margin:0;
  max-width:10em;
  font-size:clamp(2.125em,8vw,3.625em);
  line-height:1.08;
  font-weight:560;
  letter-spacing:-.035em;
}
.tvm-question{
  margin:0;
  max-width:var(--tvm-q-max-width);
  font-size:clamp(var(--tvm-q-size-min),5.4vw,var(--tvm-q-size-max));
  line-height:1.34;
  font-weight:560;
  letter-spacing:-.022em;
}
.tv-magic.is-focus .tvm-question{
  font-size:clamp(var(--tvm-q-size-focus-min),5.7vw,var(--tvm-q-size-focus-max));
}
.tvm-lead{
  margin:1.375em 0 0;
  max-width:36em;
  color:var(--tvm-muted);
  font-size:0.9375em;
  line-height:1.9;
}
.tvm-actions{
  display:flex;
  flex-wrap:wrap;
  gap:0.625em;
  margin-top:2em;
}
.tvm-btn{
  min-height:3em;
  padding:0.8125em 1.1875em;
  border:1px solid var(--tvm-line);
  border-radius:62.4375em;
  background:var(--tvm-surface);
  color:inherit;
  cursor:pointer;
  transition:.16s ease;
}
.tvm-btn:hover{background:var(--tvm-surface-strong)}
.tvm-btn:focus-visible,
.tvm-choice:focus-visible,
.tvm-back:focus-visible,
.tvm-summary:focus-visible{
  outline:0.125em solid currentColor;
  outline-offset:0.1875em;
}
.tvm-btn.is-primary{
  border-color:var(--tvm-dark);
  background:var(--tvm-dark);
  color:var(--tvm-bg);
}
.tvm-btn.is-ghost{background:transparent}

.tvm-choices{
  display:grid;
  grid-template-columns:1fr;
  gap:var(--tvm-q-choice-gap);
  margin-top:var(--tvm-q-choice-top);
}
.tvm-choice{
  width:100%;
  min-height:var(--tvm-q-choice-min-h);
  padding:var(--tvm-q-choice-pad-y) var(--tvm-q-choice-pad-x);
  border:1px solid var(--tvm-normal-choice-border);
  border-radius:var(--tvm-q-choice-radius);
  background:var(--tvm-normal-choice);
  color:inherit;
  text-align:left;
  cursor:pointer;
  transition:
    background var(--tvm-motion-fast) var(--tvm-ease),
    border-color var(--tvm-motion-fast) var(--tvm-ease),
    transform var(--tvm-motion-fast) var(--tvm-ease);
}
.tvm-choice:hover{
  background:var(--tvm-normal-choice-hover);
  border-color:rgba(32,38,36,.20);
  transform:none;
}
.tvm-choice[data-contact-state="pressed"]{
  transform:scale(.985);
}
.tvm-choice.is-preview,
.tvm-choice.is-long-preview{
  background:rgba(32,38,36,.035);
  border-color:rgba(32,38,36,.24);
}
.tvm-choice.is-selected{
  background:rgba(32,38,36,.075);
  border-color:rgba(32,38,36,.26);
  font-weight:560;
  transform:none;
}
.tvm-backrow{
  margin-top:var(--tvm-q-back-top);
  text-align:left;
}
.tvm-back{
  min-height:2.75em;
  padding:0.5em 0;
  border:0;
  background:none;
  color:var(--tvm-muted);
  cursor:pointer;
}

.tvm-loader{
  height:1px;
  margin-top:2.125em;
  overflow:hidden;
  background:var(--tvm-line);
}
.tvm-loader::after{
  content:"";
  display:block;
  width:38%;
  height:100%;
  background:var(--tvm-dark);
  animation:tvmLoad 1s ease-in-out infinite;
}
@keyframes tvmLoad{
  0%{transform:translateX(-120%)}
  100%{transform:translateX(340%)}
}

.tvm-kicker{
  margin:0 0 1.25em;
  color:var(--tvm-muted);
  font-size:0.75em;
  letter-spacing:.025em;
}
.tvm-result-name{
  margin:0;
  font-size:clamp(1.75em,4vw,2.5em);
  line-height:1.15;
  font-weight:620;
  letter-spacing:-.025em;
}
.tvm-result-section{
  margin-top:3.25em;
  padding-top:0;
}
.tvm-result-section-title{
  margin:0 0 1.125em;
  font-size:1.0625em;
  font-weight:620;
  letter-spacing:-.012em;
}
.tvm-summary-grid{
  display:grid;
  grid-template-columns:8em minmax(0,1fr);
  gap:0.7em 1.25em;
  margin:0;
  font-size:0.9375em;
  line-height:1.65;
}
.tvm-summary-grid dt{
  color:var(--tvm-muted);
}
.tvm-summary-grid dd{
  margin:0;
  overflow-wrap:anywhere;
}
.tvm-carry-lead{
  max-width:34em;
  margin:0 0 1.25em;
  color:var(--tvm-muted);
  font-size:0.9375em;
  line-height:1.8;
}
.tvm-copy-action{
  width:100%;
}
.tvm-copy-action .tvm-btn{
  display:block;
  width:100%;
  max-width:none;
  box-sizing:border-box;
}
.tvm-result-restart{
  margin-top:4em;
  padding-top:0;
  text-align:center;
}
.tvm-result-restart .tvm-actions{
  justify-content:center;
}
.tvm-result-restart .tvm-btn{
  width:auto;
  min-width:0;
  padding-left:0.9em;
  padding-right:0.9em;
  color:var(--tvm-muted);
  background:transparent;
  border-color:transparent;
  box-shadow:none;
}

.tvm-name{
  margin-bottom:0.625em;
  color:var(--tvm-muted);
  font-size:0.75em;
  letter-spacing:.08em;
}
.tvm-core{
  max-width:36em;
  margin:0;
  padding:0;
  border:0;
  background:transparent;
  font-size:1.0625em;
  line-height:1.95;
  letter-spacing:-.006em;
}
.tvm-entry .tvm-language{
  display:flex;
  width:max-content;
  margin-left:auto;
  margin-right:auto;
}
.tvm-language{
  display:inline-flex;
  align-items:center;
  gap:var(--tvm-space-4);
  padding:var(--tvm-space-4);
  border-radius:var(--tvm-radius-pill);
  isolation:isolate;
}
.tvm-lang{
  min-height:2.75em;
  padding:0 var(--tvm-space-16);
  border:0;
  border-radius:var(--tvm-radius-pill);
  background:transparent;
  color:inherit;
  cursor:pointer;
  font:inherit;
  transition:
    background var(--tvm-motion-fast) var(--tvm-ease),
    color var(--tvm-motion-fast) var(--tvm-ease),
    transform var(--tvm-motion-fast) var(--tvm-ease),
    box-shadow var(--tvm-motion-fast) var(--tvm-ease);
  -webkit-tap-highlight-color:transparent;
}

.tvm-lang.is-active{
  background:var(--tvm-clear);
  color:var(--tvm-dark);
  box-shadow:0 1px 0 rgba(255,255,255,.82), 0 0.25em 0.875em rgba(22,22,20,.08);
}
.tvm-lang:focus-visible{
  outline:var(--tvm-focus-ring);
  outline-offset:var(--tvm-focus-offset);
}

.tvm-helper,
.tvm-note{
  margin:0.875em 0 0;
  color:var(--tvm-muted);
  font-size:0.8125em;
  line-height:1.75;
}
.tvm-detail{
  margin-top:0;
}
.tvm-detail-title{
  margin:0 0 1em;
  font-size:0.875em;
  font-weight:600;
  color:var(--tvm-muted);
}
.tvm-grid{
  display:grid;
  grid-template-columns:7.5em minmax(0,1fr);
  gap:0.5625em 0.875em;
  margin:0;
  font-size:0.875em;
  line-height:1.65;
}
.tvm-grid--secondary{
  color:var(--tvm-muted);
}
.tvm-grid--secondary dd{
  color:var(--tvm-ink);
}
.tvm-grid dt{color:var(--tvm-muted)}
.tvm-grid dd{margin:0;overflow-wrap:anywhere}
.tvm-details{
  margin-top:1.5em;
  padding-top:0;
}
.tvm-summary{
  cursor:pointer;
  color:var(--tvm-muted);
  font-size:0.8125em;
}
.tvm-pre,
.tvm-prompt{
  width:100%;
  max-width:100%;
  margin-top:0.75em;
  padding:1em;
  border:1px solid var(--tvm-line);
  border-radius:1.125em;
  background:rgba(255,255,255,.52);
  color:var(--tvm-ink);
  font:0.75em/1.65 ui-monospace,SFMono-Regular,Menlo,monospace;
}
.tvm-pre{
  white-space:pre-wrap;
  word-break:break-word;
  overflow:auto;
}
.tvm-prompt{
  min-height:12em;
  max-height:24em;
  resize:vertical;
  background:rgba(255,255,255,.34);
}
.tvm-error{
  padding:1.125em;
  border:1px solid var(--tvm-line);
  border-radius:1.125em;
  background:var(--tvm-surface);
  font-size:0.875em;
  line-height:1.7;
}

@media(max-width:30em){
  .tv-magic{padding:1.75em 0.875em 4em}
  .tvm-spacer--entry-top{height:3.625em}
  .tvm-spacer--hero-lead{height:1.25em}
  .tvm-spacer--lead-language{height:1.25em}
  .tvm-spacer--language-start{height:1.375em}
  .tvm-entry .tvm-hero{font-size:clamp(2.125em,10vw,2.75em)}
  .tvm-grid{grid-template-columns:1fr;gap:0.1875em}
  .tvm-grid dd{margin-bottom:0.5em}
  .tvm-summary-grid{grid-template-columns:1fr;gap:0.1875em}
  .tvm-summary-grid dd{margin-bottom:0.5625em}
  .tvm-core{font-size:1.0625em}
}
@media(prefers-reduced-motion:reduce){
  .tv-magic *,
  .tv-magic *::before,
  .tv-magic *::after{
    animation:none!important;
    transition:none!important;
  }
}

/* TMS — interface controls only. Content remains Clear. */
.tv-magic .tvm-btn,
.tv-magic .tvm-choice,
.tv-magic .tvm-back{
  min-height:2.75em;
  transition:
    transform var(--tvm-motion-fast) var(--tvm-ease),
    background var(--tvm-motion-fast) var(--tvm-ease),
    border-color var(--tvm-motion-fast) var(--tvm-ease),
    box-shadow var(--tvm-motion-fast) var(--tvm-ease),
    opacity var(--tvm-motion-fast) var(--tvm-ease);
  -webkit-tap-highlight-color:transparent;
}

.tv-magic .tvm-btn{
  border-radius:var(--tvm-radius-16);
}

.tv-magic .tvm-btn.is-primary{
  color:var(--tvm-dark);
  border-color:rgba(22,22,20,.10);
}

.tv-magic .tvm-btn:not(.is-primary),
.tv-magic .tvm-choice,
.tv-magic .tvm-back{
  background:var(--tvm-clear);
}

.tv-magic .tvm-choice{
  border-radius:var(--tvm-radius-16);
  border-color:rgba(22,22,20,.12);
  box-shadow:0 1px 0 rgba(255,255,255,.70);
}

.tv-magic .tvm-choice.is-selected{
  background:var(--tvm-veil-solid);
  border-color:rgba(22,22,20,.18);
}

@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))){
  .tv-magic .tvm-choice.is-selected{
    background:var(--tvm-veil);
    -webkit-backdrop-filter:blur(1.125em) saturate(1.06);
    backdrop-filter:blur(1.125em) saturate(1.06);
    box-shadow:var(--tvm-glass-shadow);
  }
}

@media (hover:hover) and (pointer:fine){
  .tv-magic .tvm-lang:hover:not(.is-active),
  .tv-magic .tvm-btn:hover,
  .tv-magic .tvm-choice:hover,
  .tv-magic .tvm-back:hover{
    background:var(--tvm-mist-solid);
  }

  @supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))){
    .tv-magic .tvm-lang:hover:not(.is-active),
    .tv-magic .tvm-btn:hover,
    .tv-magic .tvm-choice:hover,
    .tv-magic .tvm-back:hover{
      background:var(--tvm-mist);
      -webkit-backdrop-filter:blur(0.5em) saturate(1.02);
      backdrop-filter:blur(0.5em) saturate(1.02);
    }
  }
}

.tv-magic .tvm-lang:active,
.tv-magic .tvm-btn:active,
.tv-magic .tvm-choice:active,
.tv-magic .tvm-back:active{
  transform:scale(.97);
  background:var(--tvm-lens-solid);
}

@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))){
  .tv-magic .tvm-lang:active,
  .tv-magic .tvm-btn:active,
  .tv-magic .tvm-choice:active,
  .tv-magic .tvm-back:active{
    background:var(--tvm-lens);
    -webkit-backdrop-filter:blur(1.625em) saturate(1.10);
    backdrop-filter:blur(1.625em) saturate(1.10);
  }
}

.tv-magic .tvm-btn:focus-visible,
.tv-magic .tvm-choice:focus-visible,
.tv-magic .tvm-back:focus-visible{
  outline:var(--tvm-focus-ring);
  outline-offset:var(--tvm-focus-offset);
}

/* Content surfaces explicitly stay Clear / non-Glass. */
.tv-magic .tvm-screen,
.tv-magic .tvm-hero,
.tv-magic .tvm-lead,
.tv-magic .tvm-question,
.tv-magic .tvm-core,
.tv-magic .tvm-detail,
.tv-magic .tvm-grid,
.tv-magic .tvm-pre,
.tv-magic .tvm-prompt{
  -webkit-backdrop-filter:none;
  backdrop-filter:none;
}

/* Transparency fallback */
@media (prefers-reduced-transparency: reduce){
  .tv-magic .tvm-language,
  .tv-magic .tvm-btn.is-primary,
  .tv-magic .tvm-choice.is-selected,
  .tv-magic .tvm-lang:active,
  .tv-magic .tvm-btn:active,
  .tv-magic .tvm-choice:active,
  .tv-magic .tvm-back:active{
    -webkit-backdrop-filter:none;
    backdrop-filter:none;
  }
  .tv-magic .tvm-language{background:var(--tvm-mist-solid)}
  .tv-magic .tvm-btn.is-primary{background:var(--tvm-veil-solid)}
  .tv-magic .tvm-choice.is-selected{background:var(--tvm-veil-solid)}
}

/* Motion fallback */

/* =========================================================
   Browser / viewport resilience derived from Today / Margin
   ========================================================= */
.tv-magic.is-focus{
  position:fixed !important;
  inset:0 !important;
  z-index:2147483000 !important;
  width:100vw !important;
  width:100dvw !important;
  height:var(--tvm-visual-height,100vh) !important;
  height:var(--tvm-visual-height,100dvh) !important;
  max-width:none !important;
  margin:0 !important;
  transform:none !important;
  padding:0 !important;
  overflow:hidden !important;
  overscroll-behavior:none;
  background-color:var(--tvm-focus-bg) !important;
  background-image:
    radial-gradient(circle at 50% 11%,rgba(255,255,255,.22),rgba(255,255,255,0) 28em) !important;
  -webkit-text-size-adjust:100%;
  text-size-adjust:100%;
}

.tv-magic.is-focus #tvmagicApp{
  box-sizing:border-box;
  width:100%;
  height:100%;
  min-height:0;
  overflow-x:hidden;
  overflow-y:auto;
  overscroll-behavior-x:none;
  overscroll-behavior-y:contain;
  -webkit-overflow-scrolling:touch;
  touch-action:pan-y pinch-zoom;
  padding:
    max(1.5em,env(safe-area-inset-top))
    max(1.25em,env(safe-area-inset-right))
    max(1.5em,env(safe-area-inset-bottom))
    max(1.25em,env(safe-area-inset-left));
  scrollbar-gutter:stable;
}


.tv-magic.is-focus .tvm-screen{
  width:min(45em,100%);
  margin:0 auto;
}
.tv-magic.is-focus .tvm-question-screen{
  width:100%;
  max-width:none;
  margin:0;
}

.tv-magic .tvm-focus-toggle{
  appearance:none;
  display:grid;
  place-items:center;
  flex:0 0 var(--tvm-q-focus-hit);
  width:var(--tvm-q-focus-hit);
  height:var(--tvm-q-focus-hit);
  min-width:var(--tvm-q-focus-hit);
  min-height:var(--tvm-q-focus-hit);
  margin:0;
  padding:0;
  border:0;
  background:transparent;
  color:var(--tvm-muted);
  opacity:var(--tvm-normal-focus-opacity);
  cursor:pointer;
  -webkit-tap-highlight-color:transparent;
  transition:
    width var(--tvm-motion-fast) var(--tvm-ease),
    height var(--tvm-motion-fast) var(--tvm-ease),
    flex-basis var(--tvm-motion-fast) var(--tvm-ease),
    opacity var(--tvm-motion-fast) var(--tvm-ease),
    color var(--tvm-motion-fast) var(--tvm-ease);
}
.tv-magic .tvm-focus-toggle:hover{
  color:var(--tvm-ink);
  opacity:1;
}
.tv-magic .tvm-focus-toggle:focus-visible{opacity:1}
.tv-magic.is-focus .tvm-focus-toggle{
  flex-basis:var(--tvm-q-focus-hit-active);
  width:var(--tvm-q-focus-hit-active);
  height:var(--tvm-q-focus-hit-active);
  min-width:var(--tvm-q-focus-hit-active);
  min-height:var(--tvm-q-focus-hit-active);
  opacity:var(--tvm-focus-focus-opacity);
}
.tv-magic.is-focus .tvm-focus-toggle{
  color:var(--tvm-ink);
}

.tv-magic .tvm-focus-toggle:focus-visible{
  opacity:1;
  outline:var(--tvm-focus-ring);
  outline-offset:var(--tvm-focus-offset);
}
.tv-magic .tvm-focus-toggle svg{
  width:var(--tvm-q-focus-icon);
  height:var(--tvm-q-focus-icon);
  fill:none;
  stroke:currentColor;
  stroke-width:1.8;
  stroke-linecap:round;
  stroke-linejoin:round;
  overflow:visible;
  pointer-events:none;
  transition:
    width var(--tvm-motion-fast) var(--tvm-ease),
    height var(--tvm-motion-fast) var(--tvm-ease);
}
.tv-magic.is-focus .tvm-focus-toggle svg{
  width:var(--tvm-q-focus-icon-active);
  height:var(--tvm-q-focus-icon-active);
}
.tv-magic .tvm-focus-icon-exit{display:none}
.tv-magic.is-focus .tvm-focus-icon-enter{display:none}
.tv-magic.is-focus .tvm-focus-icon-exit{display:block}

@media (max-height:32.5em){
  .tv-magic{
    padding-top:max(1em,env(safe-area-inset-top));
    padding-bottom:max(1.5em,env(safe-area-inset-bottom));
  }
  .tv-magic .tvm-top{margin-bottom:1.25em}
  .tv-magic .tvm-spacer--entry-top{height:2em}
  .tv-magic .tvm-spacer--density-2{height:1em}
  .tv-magic .tvm-choices{margin-top:1.125em;gap:0.5em}
  .tv-magic .tvm-choice{min-height:3em;padding:0.75em 1em}
  .tv-magic .tvm-backrow{margin-top:0.75em}
}

@media (max-height:23.75em){
  .tv-magic .tvm-question{font-size:clamp(1.35em,5.5vw,2em)}
}

@media (hover:none){
  .tv-magic .tvm-btn:hover,
  .tv-magic .tvm-choice:hover,
  .tv-magic .tvm-focus-toggle:hover{
    transform:none;
  }
}

@media (pointer:coarse){
  .tv-magic button{
    -webkit-tap-highlight-color:transparent;
  }
}

/* Single-pointer operation contract.
   Keep browser/OS multi-touch accessibility gestures available. */
.tv-magic:not(.is-focus) .tvm-choice,
.tv-magic:not(.is-focus) .tvm-btn,
.tv-magic:not(.is-focus) .tvm-back,
.tv-magic:not(.is-focus) .tvm-lang,
.tv-magic:not(.is-focus) .tvm-focus-toggle{
  touch-action:manipulation;
}

.tv-magic .tvm-question-shell,
.tv-magic .tvm-question-shell .tvm-choice,
.tv-magic.is-focus .tvm-focus-toggle,
.tv-magic.is-focus .tvm-back{
  -webkit-user-select:none;
  user-select:none;
  -webkit-touch-callout:none;
}

.tv-magic .tvm-result-name,
.tv-magic .tvm-core,
.tv-magic .tvm-grid dd,
.tv-magic .tvm-summary-grid dd,
.tv-magic .tvm-carry-lead,
.tv-magic .tvm-helper,
.tv-magic .tvm-note{
  overflow-wrap:anywhere;
}

@media (max-width:20em){
  .tv-magic{
    padding-left:max(0.875em,env(safe-area-inset-left));
    padding-right:max(0.875em,env(safe-area-inset-right));
  }
  .tv-magic .tvm-hero{
    font-size:clamp(1.75em,9vw,2.5em);
  }
  .tv-magic .tvm-question{
    font-size:clamp(1.4em,8vw,2em);
  }
  .tv-magic .tvm-progress{
    width:min(100%,17.5em);
  }
  .tv-magic .tvm-summary-grid{
    grid-template-columns:1fr;
    gap:0.2em;
  }
  .tv-magic .tvm-summary-grid dd{
    margin-bottom:0.8em;
  }
}

@media (prefers-contrast:more){
  .tv-magic{
    --tvm-line:currentColor;
    --tvm-glass-edge:currentColor;
    --tvm-glass-shadow:none;
    --tvm-elevation-float:none;
    --tvm-elevation-toast:none;
  }
  .tv-magic .tvm-btn,
  .tv-magic .tvm-choice,
  .tv-magic .tvm-language,
  .tv-magic .tvm-progress{
    border-color:currentColor;
  }
  .tv-magic .tvm-muted,
  .tv-magic .tvm-lead,
  .tv-magic .tvm-kicker,
  .tv-magic .tvm-helper,
  .tv-magic .tvm-note,
  .tv-magic .tvm-back,
  .tv-magic .tvm-detail-title{
    color:currentColor;
    opacity:.82;
  }
}

@media (prefers-reduced-motion: reduce){
  .tv-magic *,
  .tv-magic *::before,
  .tv-magic *::after{
    scroll-behavior:auto !important;
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
  }
}

/* High-contrast fallback */
@media (forced-colors: active){
  .tv-magic .tvm-language,
  .tv-magic .tvm-btn,
  .tv-magic .tvm-choice,
  .tv-magic .tvm-back,
  .tv-magic .tvm-lang{
    forced-color-adjust:auto;
    -webkit-backdrop-filter:none;
    backdrop-filter:none;
    box-shadow:none;
    border:1px solid ButtonText;
    background:Canvas;
    color:CanvasText;
  }
  .tv-magic .tvm-lang.is-active{
    background:Highlight;
    color:HighlightText;
  }
}


/* =========================================================
   Tranquil Material System v1.7
   Material State Machine / Morphing / Progress / Toast
   ========================================================= */

/* Semantic material aliases: components reference meaning, not raw color. */
.tv-magic{
  --tvm-surface-clear:var(--tvm-clear);
  --tvm-surface-mist:var(--tvm-mist);
  --tvm-surface-veil:var(--tvm-veil);
  --tvm-surface-lens:var(--tvm-lens);

  --tvm-surface-mist-solid:var(--tvm-mist-solid);
  --tvm-surface-veil-solid:var(--tvm-veil-solid);
  --tvm-surface-lens-solid:var(--tvm-lens-solid);

  --tvm-elevation-inline:0 1px 0 rgba(255,255,255,.64);
  --tvm-elevation-float:0 0.5em 1.5em rgba(22,22,20,.08), inset 0 1px 0 rgba(255,255,255,.78);
  --tvm-elevation-toast:0 0.875em 2.25em rgba(22,22,20,.12), inset 0 1px 0 rgba(255,255,255,.82);

  --tvm-z-content:0;
  --tvm-z-inline:10;
  --tvm-z-float:20;
  --tvm-z-toast:30;

  --tvm-control-radius-rest:var(--tvm-radius-16);
  --tvm-control-radius-hover:1.125em;
  --tvm-control-radius-active:1.25em;
}

/* Dark tokens are prepared, but never auto-force the WordPress page into dark mode.
   Activate only when this experience is explicitly placed in a dark context. */
.tv-magic[data-tvm-theme="dark"]{
    --tvm-surface-clear:#171715;
    --tvm-surface-mist:rgba(36,36,33,.82);
    --tvm-surface-veil:rgba(42,42,38,.72);
    --tvm-surface-lens:rgba(48,48,43,.64);

    --tvm-surface-mist-solid:#242421;
    --tvm-surface-veil-solid:#2a2a26;
    --tvm-surface-lens-solid:#30302b;

    --tvm-glass-border:rgba(255,255,255,.12);
    --tvm-glass-edge:rgba(255,255,255,.10);
    --tvm-elevation-inline:0 1px 0 rgba(255,255,255,.05);
    --tvm-elevation-float:0 0.625em 1.875em rgba(0,0,0,.20), inset 0 1px 0 rgba(255,255,255,.08);
    --tvm-elevation-toast:0 1em 2.625em rgba(0,0,0,.30), inset 0 1px 0 rgba(255,255,255,.10);
}

/* Material State Machine */
.tv-magic .tvm-control{
  position:relative;
  z-index:var(--tvm-z-inline);
  border-radius:var(--tvm-control-radius-rest);
  transform:translateZ(0) scale(1);
  transition:
    transform var(--tvm-motion-fast) var(--tvm-ease),
    border-radius var(--tvm-motion-base) var(--tvm-ease),
    background var(--tvm-motion-base) var(--tvm-ease),
    border-color var(--tvm-motion-base) var(--tvm-ease),
    box-shadow var(--tvm-motion-base) var(--tvm-ease),
    opacity var(--tvm-motion-fast) var(--tvm-ease);
}

.tv-magic .tvm-control[data-material="clear" data-surface="interface" data-elevation="s1"]{
  background:var(--tvm-surface-clear);
  box-shadow:var(--tvm-elevation-inline);
}

.tv-magic .tvm-control[data-material="mist" data-surface="interface" data-elevation="s1" data-glass="mist"]{
  background:var(--tvm-surface-mist-solid);
  box-shadow:var(--tvm-elevation-float);
}

.tv-magic .tvm-control[data-material="veil" data-surface="interface" data-elevation="s1" data-glass="veil"]{
  background:var(--tvm-surface-veil-solid);
  box-shadow:var(--tvm-elevation-float);
}

.tv-magic .tvm-control[data-material="lens" data-surface="transient" data-elevation="s3" data-glass="lens"]{
  background:var(--tvm-surface-lens-solid);
  box-shadow:var(--tvm-elevation-float);
}

@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))){
  .tv-magic .tvm-control[data-material="mist" data-surface="interface" data-elevation="s1" data-glass="mist"]{
    background:var(--tvm-surface-mist);
    -webkit-backdrop-filter:blur(0.5em) saturate(1.02);
    backdrop-filter:blur(0.5em) saturate(1.02);
  }

  .tv-magic .tvm-control[data-material="veil" data-surface="interface" data-elevation="s1" data-glass="veil"]{
    background:var(--tvm-surface-veil);
    -webkit-backdrop-filter:blur(1.125em) saturate(1.06);
    backdrop-filter:blur(1.125em) saturate(1.06);
  }

  .tv-magic .tvm-control[data-material="lens" data-surface="transient" data-elevation="s3" data-glass="lens"]{
    background:var(--tvm-surface-lens);
    -webkit-backdrop-filter:blur(1.625em) saturate(1.10);
    backdrop-filter:blur(1.625em) saturate(1.10);
  }
}

@media (hover:hover) and (pointer:fine){
  .tv-magic .tvm-control:hover:not(:disabled){
    border-radius:var(--tvm-control-radius-hover);
    transform:translateY(-1px) scale(1.005);
  }
}

.tv-magic .tvm-control:active:not(:disabled){
  border-radius:var(--tvm-control-radius-active);
  transform:scale(.975);
}

.tv-magic .tvm-control:disabled,
.tv-magic .tvm-control[aria-disabled="true"]{
  opacity:.52;
  cursor:default;
  transform:none;
}

/* Keep the segmented language control pill-shaped. */
.tv-magic .tvm-lang.tvm-control,
.tv-magic .tvm-language{
  border-radius:var(--tvm-radius-pill);
}
@media (hover:hover) and (pointer:fine){
  .tv-magic .tvm-lang.tvm-control:hover:not(:disabled){
    border-radius:var(--tvm-radius-pill);
  }
}
.tv-magic .tvm-lang.tvm-control:active:not(:disabled){
  border-radius:var(--tvm-radius-pill);
}

/* Floating question progress */
.tv-magic .tvm-progress-wrap{
  width:100%;
  position:relative;
  z-index:var(--tvm-z-inline);
  margin-bottom:var(--tvm-q-progress-bottom);
}

.tv-magic .tvm-progress{
  width:100%;
  padding:0;
  border:0;
  border-radius:0;
  background:transparent;
  box-shadow:none;
}

.tv-magic .tvm-progress-meta{
  display:none;
}

.tv-magic .tvm-progress-track{
  position:relative;
  width:100%;
  height:1px;
  margin:0;
  overflow:visible;
  border-radius:0;
  background:var(--tvm-normal-progress-track);
}

.tv-magic .tvm-progress-bar{
  display:block;
  height:1px;
  width:0;
  border-radius:0;
  background:currentColor;
  opacity:var(--tvm-normal-progress-bar);
  transform-origin:left center;
  transition:width var(--tvm-motion-base) var(--tvm-ease);
}

.tv-magic .tvm-progress-traces{
  position:absolute;
  inset:0;
  pointer-events:none;
}
.tv-magic .tvm-progress-trace{
  position:absolute;
  top:50%;
  width:0.25em;
  height:0.25em;
  border-radius:50%;
  background:currentColor;
  opacity:.16;
  transform:translate(-50%,-50%);
}
.tv-magic .tvm-progress-trace.is-current{
  opacity:.42;
}

.tv-magic.is-focus .tvm-progress-track{
  background:var(--tvm-focus-progress-track);
}
.tv-magic.is-focus .tvm-progress-bar{
  opacity:var(--tvm-focus-progress-bar);
}
.tv-magic.is-focus .tvm-progress-trace{
  width:0.2em;
  height:0.2em;
  opacity:.12;
}
.tv-magic.is-focus .tvm-progress-trace.is-current{
  opacity:.34;
}


.tv-magic .tvm-density-regular .tvm-spacer--density-2{
  height:0.65em;
}
.tv-magic .tvm-question-shell{
  max-width:100%;
}
@media (min-width:48.0625em){
  .tv-magic .tvm-density-regular{
    padding-top:0.25em;
  }
}
@media (max-width:30em){
  .tvm-top{
    margin-bottom:0.35em;
  }
  .tvm-progress-wrap{
    margin-bottom:1.25em;
  }
  .tvm-question{
    font-size:clamp(1.42em,7vw,1.9em);
    max-width:16em;
  }
  .tvm-choices{
    margin-top:0.95em;
    gap:0.45em;
  }
}


/* One coordinate system for header / progress / question / choices / back. */
.tv-magic .tvm-question-frame{
  width:min(var(--tvm-q-frame-width),100%);
  margin-left:auto;
  margin-right:auto;
  padding-top:0.25em;
}
.tv-magic.is-focus .tvm-question-frame{
  padding-top:1em;
}
.tv-magic .tvm-question-frame .tvm-top,
.tv-magic .tvm-question-frame .tvm-progress-wrap,
.tv-magic .tvm-question-frame .tvm-question-shell,
.tv-magic .tvm-question-frame .tvm-backrow{
  width:100%;
  max-width:none;
}
.tv-magic .tvm-question-frame .tvm-question-shell:focus{
  outline:none;
}

/* Progress remains intentionally shorter than the answer column. */
.tv-magic .tvm-question-frame .tvm-progress-wrap{
  width:min(var(--tvm-q-progress-width),100%);
  margin-left:0;
  margin-right:0;
}

/* Back is navigation, not a material card. */
.tv-magic .tvm-question-frame .tvm-back,
.tv-magic .tvm-question-frame .tvm-back:hover,
.tv-magic .tvm-question-frame .tvm-back:active{
  width:auto;
  border:0 !important;
  border-radius:0 !important;
  background:transparent !important;
  box-shadow:none !important;
  -webkit-backdrop-filter:none !important;
  backdrop-filter:none !important;
}
.tv-magic .tvm-question-frame .tvm-back:hover{
  color:var(--tvm-ink);
}
.tv-magic .tvm-question-frame .tvm-back:active{
  transform:scale(.98);
}

.tv-magic.is-focus .tvm-question-frame .tvm-back::before{
  content:"←";
  display:inline-block;
  margin-right:.55em;
  transform:translateY(-.02em);
}

/* Choices are deliberately quieter than generic TMS controls. */
.tv-magic .tvm-question-frame .tvm-choice:not(.is-selected){
  background:var(--tvm-normal-choice) !important;
  border-color:var(--tvm-normal-choice-border) !important;
  box-shadow:none !important;
  -webkit-backdrop-filter:none !important;
  backdrop-filter:none !important;
}
.tv-magic.is-focus .tvm-question-frame .tvm-choice:not(.is-selected){
  background:var(--tvm-focus-choice) !important;
  border-color:var(--tvm-focus-choice-border) !important;
}
.tv-magic.is-focus .tvm-question-frame .tvm-choice.is-selected{
  background:var(--tvm-focus-choice-selected) !important;
  border-color:rgba(32,38,36,.22) !important;
  box-shadow:none !important;
  -webkit-backdrop-filter:none !important;
  backdrop-filter:none !important;
}
@media (hover:hover) and (pointer:fine){
  .tv-magic .tvm-question-frame .tvm-choice:hover:not(.is-selected){
    background:var(--tvm-normal-choice-hover) !important;
  }
  .tv-magic.is-focus .tvm-question-frame .tvm-choice:hover:not(.is-selected){
    background:var(--tvm-focus-choice-hover) !important;
  }
}

/* Start is a single gateway action, visually distinct from question rows. */
.tv-magic .tvm-entry .tvm-actions{
  justify-content:center;
}
.tv-magic .tvm-entry #tvmStart{
  width:min(22em,100%);
  max-width:100%;
}

/* Result should feel like the completed artifact, not a smaller footnote. */
.tv-magic .tvm-result-screen{
  width:min(42em,100%);
  margin-left:auto;
  margin-right:auto;
}
.tv-magic .tvm-result-screen .tvm-result-name{
  font-size:clamp(1.9em,4.5vw,2.75em);
}
.tv-magic .tvm-result-screen .tvm-core{
  max-width:38em;
  font-size:1.125em;
}
.tv-magic .tvm-result-screen .tvm-result-section-title{
  font-size:1.125em;
}
.tv-magic .tvm-result-screen .tvm-summary-grid{
  font-size:0.975em;
}
.tv-magic .tvm-result-screen .tvm-grid{
  font-size:0.925em;
}
.tv-magic .tvm-result-screen .tvm-prompt{
  font-size:0.8125em;
}


.tv-magic .tvm-result-screen .tvm-kicker{
  margin-bottom:1em;
}
.tv-magic .tvm-result-screen .tvm-result-section{
  margin-top:3.5em;
}
.tv-magic .tvm-result-screen .tvm-carry-lead{
  max-width:38em;
}



/* =========================================================
   Alignment contract v4.0
   Alignment follows content role rather than one global rule.
   ========================================================= */
.tv-magic .tvm-align-left{
  text-align:left;
}
.tv-magic .tvm-align-center{
  text-align:center;
}
.tv-magic .tvm-align-right{
  text-align:right;
}

/* Entry: invitation / gateway = centered. */
.tv-magic .tvm-entry{
  text-align:center;
}
.tv-magic .tvm-entry .tvm-hero,
.tv-magic .tvm-entry .tvm-lead{
  margin-left:auto;
  margin-right:auto;
  text-align:center;
}
.tv-magic .tvm-entry .tvm-actions{
  justify-content:center;
}

/* Question: reading + decision = left; utility remains split left/right. */
.tv-magic .tvm-question-frame,
.tv-magic .tvm-question-shell,
.tv-magic .tvm-question,
.tv-magic .tvm-choices,
.tv-magic .tvm-choice,
.tv-magic .tvm-backrow,
.tv-magic .tvm-back{
  text-align:left;
}
.tv-magic .tvm-question-meta{
  text-align:left;
}
.tv-magic .tvm-focus-toggle{
  text-align:right;
}

/* Result opening: identity / completion = centered. */
.tv-magic .tvm-result-screen > .tvm-kicker,
.tv-magic .tvm-result-screen > .tvm-result-name,
.tv-magic .tvm-result-screen > .tvm-core{
  text-align:center;
}
.tv-magic .tvm-result-screen > .tvm-core{
  margin-left:auto;
  margin-right:auto;
}

/* Result facts: labels face values across a shared axis. */
.tv-magic .tvm-result-section{
  text-align:left;
}
.tv-magic .tvm-summary-grid dt,
.tv-magic .tvm-grid dt{
  text-align:right;
}
.tv-magic .tvm-summary-grid dd,
.tv-magic .tvm-grid dd{
  text-align:left;
}

/* Carry action: instruction is centered; prompt itself remains source text. */
.tv-magic .tvm-carry-section{
  text-align:center;
}
.tv-magic .tvm-carry-section .tvm-carry-lead{
  margin-left:auto;
  margin-right:auto;
  text-align:center;
}
.tv-magic .tvm-carry-section .tvm-copy-action{
  text-align:center;
}
.tv-magic .tvm-carry-section .tvm-helper{
  text-align:center;
}
.tv-magic .tvm-carry-section .tvm-prompt-heading,
.tv-magic .tvm-carry-section .tvm-prompt,
.tv-magic .tvm-carry-section .tvm-note{
  text-align:left;
}

/* Share / completion actions = centered. */
.tv-magic .tvm-share{
  text-align:center;
}
.tv-magic .tvm-share-row,
.tv-magic .tvm-share-group{
  justify-content:center;
}
.tv-magic .tvm-result-restart{
  text-align:center;
}

/* Narrow screens: two-column definition grids collapse, so labels return left. */
@media(max-width:30em){
  .tv-magic .tvm-summary-grid dt,
  .tv-magic .tvm-grid dt{
    text-align:left;
  }
}

/* =========================================================
   Result share — TranquilShare v1.0-derived icon / state system
   ========================================================= */
.tv-magic .tvm-share{
  margin-top:3.75em;
}
.tv-magic .tvm-share-title{
  margin:0;
  font-size:1.0625em;
  line-height:1.35;
  font-weight:620;
  letter-spacing:-.015em;
}
.tv-magic .tvm-share-row{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:.75em;
  margin-top:1em;
}
.tv-magic .tvm-share-group{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:.38em;
}
.tv-magic .tvm-share-group--utility{
  gap:.42em;
}
.tv-magic .tvm-share-btn{
  appearance:none;
  position:relative;
  display:grid;
  place-items:center;
  width:2.75em;
  height:2.75em;
  min-width:2.75em;
  min-height:2.75em;
  margin:0;
  padding:0;
  border:1px solid rgba(32,38,36,.11);
  border-radius:999em;
  background:rgba(255,255,255,.34);
  color:var(--tvm-ink);
  font:inherit;
  line-height:1;
  cursor:pointer;
  text-decoration:none;
  overflow:visible;
  -webkit-tap-highlight-color:transparent;
  touch-action:manipulation;
  transition:
    background var(--tvm-motion-fast) var(--tvm-ease),
    border-color var(--tvm-motion-fast) var(--tvm-ease),
    transform var(--tvm-motion-fast) var(--tvm-ease),
    opacity var(--tvm-motion-fast) var(--tvm-ease);
}
.tv-magic .tvm-share-btn:hover{
  background:rgba(255,255,255,.62);
  border-color:rgba(32,38,36,.20);
}
.tv-magic .tvm-share-btn:active{
  transform:scale(.97);
}
.tv-magic .tvm-share-btn[hidden]{
  display:none !important;
}
.tv-magic .tvm-share-btn[aria-busy="true"]{
  cursor:progress;
  opacity:.55;
  transform:none;
}
.tv-magic .tvm-share-btn:focus-visible{
  outline:var(--tvm-focus-ring);
  outline-offset:var(--tvm-focus-offset);
}
.tv-magic .tvm-share-icon,
.tv-magic .tvm-copy-icon,
.tv-magic .tvm-share-font-icon{
  display:block;
  width:1em;
  height:1em;
  margin:0;
  padding:0;
  flex:none;
  pointer-events:none;
}
.tv-magic .tvm-share-font-icon{
  font-size:1em;
  line-height:1;
}
.tv-magic .tvm-share-icon{
  fill:none;
  stroke:currentColor;
}
.tv-magic .tvm-share-icon--brand{
  fill:currentColor;
  stroke:none;
}
.tv-magic [data-share-action="x"] .tvm-share-font-icon{
  transform:scale(.90);
}
.tv-magic [data-share-action="threads"] .tvm-share-icon{
  transform:scale(1.20);
}
.tv-magic [data-share-action="bluesky"] .tvm-share-icon{
  transform:scale(.90);
}
.tv-magic [data-share-action="line"] .tvm-share-font-icon{
  transform:scale(1.20);
}
.tv-magic [data-share-action="native"] .tvm-share-icon,
.tv-magic [data-share-action="story"] .tvm-share-icon,
.tv-magic [data-share-action="copy"] .tvm-copy-icon{
  transform:scale(1.15);
}
.tv-magic .tvm-share-fallback{
  display:none;
  font-size:.8em;
  font-weight:700;
  line-height:1;
}
.tv-magic .tvm-share-btn.is-font-icon-missing .tvm-share-font-icon{
  display:none;
}
.tv-magic .tvm-share-btn.is-font-icon-missing .tvm-share-fallback{
  display:block;
}
.tv-magic .tvm-copy-icon__default,
.tv-magic .tvm-copy-icon__copied{
  transition:opacity .18s ease;
}
.tv-magic .tvm-copy-icon__default{
  opacity:1;
}
.tv-magic .tvm-copy-icon__copied{
  opacity:0;
}
.tv-magic .tvm-share-btn.is-copied .tvm-copy-icon__default{
  opacity:0;
}
.tv-magic .tvm-share-btn.is-copied .tvm-copy-icon__copied{
  opacity:1;
}
@media (hover:hover) and (pointer:fine){
  .tv-magic .tvm-share-btn::after{
    content:attr(data-tooltip);
    position:absolute;
    left:50%;
    bottom:calc(100% + .625em);
    width:max-content;
    max-width:14em;
    padding:.45em .65em;
    border-radius:.35em;
    background:#404040;
    color:#fff;
    font-size:.6875em;
    font-weight:400;
    line-height:1.35;
    letter-spacing:.01em;
    white-space:normal;
    text-align:center;
    opacity:0;
    visibility:hidden;
    transform:translate(-50%,.25em);
    pointer-events:none;
    z-index:var(--tvm-z-toast);
    transition:
      opacity .16s ease,
      transform .16s ease,
      visibility .16s ease;
  }
  .tv-magic .tvm-share-btn:hover::after,
  .tv-magic .tvm-share-btn:focus-visible::after{
    opacity:1;
    visibility:visible;
    transform:translate(-50%,0);
  }
}
@media (max-width:20em){
  .tv-magic .tvm-share-row{gap:.625em}
  .tv-magic .tvm-share-group{gap:.3em}
  .tv-magic .tvm-share-btn{
    width:2.75em;
    height:2.75em;
    min-width:2.75em;
    min-height:2.75em;
  }
}
@media (prefers-reduced-motion:reduce){
  .tv-magic .tvm-copy-icon__default,
  .tv-magic .tvm-copy-icon__copied,
  .tv-magic .tvm-share-btn,
  .tv-magic .tvm-share-btn::after{
    transition:none !important;
  }
}
@media (prefers-contrast:more){
  .tv-magic .tvm-share-btn{
    background:transparent;
    border-color:currentColor;
  }
}
@media (forced-colors:active){
  .tv-magic .tvm-share-btn{
    background:ButtonFace;
    color:ButtonText;
    border-color:ButtonText;
  }
}

/* Copy toast — transient interface only */
.tv-magic .tvm-toast{
  position:fixed;
  left:50%;
  bottom:max(1.5em,calc(env(safe-area-inset-bottom) + 1em));
  z-index:var(--tvm-z-toast);
  max-width:min(88vw,26.25em);
  padding:0.75em 1em;
  border:1px solid var(--tvm-glass-border);
  border-radius:var(--tvm-radius-16);
  background:var(--tvm-surface-veil-solid);
  box-shadow:var(--tvm-elevation-toast);
  opacity:0;
  transform:translate(-50%,0.75em) scale(.98);
  pointer-events:none;
  transition:
    opacity var(--tvm-motion-base) var(--tvm-ease),
    transform var(--tvm-motion-base) var(--tvm-ease);
}

@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))){
  .tv-magic .tvm-toast{
    background:var(--tvm-surface-veil);
    -webkit-backdrop-filter:blur(1.125em) saturate(1.06);
    backdrop-filter:blur(1.125em) saturate(1.06);
  }
}

.tv-magic .tvm-toast.is-visible{
  opacity:1;
  transform:translate(-50%,0) scale(1);
}

/* Copy state */
.tv-magic #tvmCopy[data-state="working"]{
  cursor:progress;
}
.tv-magic #tvmCopy[data-state="success"]{
  border-radius:var(--tvm-control-radius-active);
}

/* Prefer spacers for new vertical rhythm. */
.tv-magic .tvm-spacer--progress-question{height:var(--tvm-space-24)}
.tv-magic .tvm-spacer--question-choices{height:var(--tvm-space-24)}

/* Performance budget:
   - progress is the only always-on blurred floating surface during questions.
   - unselected choices stay Clear.
   - selected/active controls alone may use Veil/Lens.
*/
.tv-magic .tvm-choice:not(.is-selected){
  -webkit-backdrop-filter:none !important;
  backdrop-filter:none !important;
}
.tv-magic .tvm-choice.is-selected{
  background:var(--tvm-surface-veil-solid);
}
@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))){
  .tv-magic .tvm-choice.is-selected{
    background:var(--tvm-surface-veil);
  }
}

/* Accessibility fallbacks for new v1.7 surfaces */
@media (prefers-reduced-transparency: reduce){
  .tv-magic .tvm-progress,
  .tv-magic .tvm-toast,
  .tv-magic .tvm-control[data-material="mist" data-surface="interface" data-elevation="s1" data-glass="mist"],
  .tv-magic .tvm-control[data-material="veil" data-surface="interface" data-elevation="s1" data-glass="veil"],
  .tv-magic .tvm-control[data-material="lens" data-surface="transient" data-elevation="s3" data-glass="lens"]{
    -webkit-backdrop-filter:none !important;
    backdrop-filter:none !important;
  }
  .tv-magic .tvm-progress,
  .tv-magic .tvm-toast,
  .tv-magic .tvm-control[data-material="veil" data-surface="interface" data-elevation="s1" data-glass="veil"]{
    background:var(--tvm-surface-veil-solid);
  }
  .tv-magic .tvm-control[data-material="mist" data-surface="interface" data-elevation="s1" data-glass="mist"]{
    background:var(--tvm-surface-mist-solid);
  }
  .tv-magic .tvm-control[data-material="lens" data-surface="transient" data-elevation="s3" data-glass="lens"]{
    background:var(--tvm-surface-lens-solid);
  }
}

@media (forced-colors: active){
  .tv-magic .tvm-progress,
  .tv-magic .tvm-toast{
    forced-color-adjust:auto;
    -webkit-backdrop-filter:none;
    backdrop-filter:none;
    box-shadow:none;
    background:Canvas;
    color:CanvasText;
    border:1px solid ButtonText;
  }
  .tv-magic .tvm-progress-track{
    background:Canvas;
    border:1px solid ButtonText;
  }
  .tv-magic .tvm-progress-bar{
    background:Highlight;
    opacity:1;
  }
}


/* =========================================================
   Tranquil Material System v1.8
   Specular / Edge / Density / Motion Roles / Refraction
   ========================================================= */

.tv-magic{
  --tvm-motion-press:120ms;
  --tvm-motion-select:220ms;
  --tvm-motion-progress:280ms;
  --tvm-motion-float-in:320ms;
  --tvm-motion-float-out:240ms;

  --tvm-density-relaxed-gap-1:1.5em;
  --tvm-density-relaxed-gap-2:2em;
  --tvm-density-regular-gap-1:1em;
  --tvm-density-regular-gap-2:1.5em;
  --tvm-density-compact-gap-1:0.75em;
  --tvm-density-compact-gap-2:1em;

  --tvm-specular:rgba(255,255,255,.82);
  --tvm-specular-soft:rgba(255,255,255,.42);
  --tvm-edge-dark:rgba(20,20,18,.10);
  --tvm-edge-dark-soft:rgba(20,20,18,.05);
  --tvm-refraction-contrast:1.02;
  --tvm-refraction-saturation:1.04;
}

.tv-magic .tvm-density-relaxed{
  --tvm-density-gap-1:var(--tvm-density-relaxed-gap-1);
  --tvm-density-gap-2:var(--tvm-density-relaxed-gap-2);
}
.tv-magic .tvm-density-regular{
  --tvm-density-gap-1:var(--tvm-density-regular-gap-1);
  --tvm-density-gap-2:var(--tvm-density-regular-gap-2);
}
.tv-magic .tvm-density-compact{
  --tvm-density-gap-1:var(--tvm-density-compact-gap-1);
  --tvm-density-gap-2:var(--tvm-density-compact-gap-2);
}
.tv-magic .tvm-spacer--density-1{height:var(--tvm-density-gap-1,1em)}
.tv-magic .tvm-spacer--density-2{height:var(--tvm-density-gap-2,1.5em)}

.tv-magic .tvm-language,
.tv-magic .tvm-progress,
.tv-magic .tvm-toast,
.tv-magic .tvm-control[data-material="mist" data-surface="interface" data-elevation="s1" data-glass="mist"],
.tv-magic .tvm-control[data-material="veil" data-surface="interface" data-elevation="s1" data-glass="veil"],
.tv-magic .tvm-control[data-material="lens" data-surface="transient" data-elevation="s3" data-glass="lens"]{
  position:relative;
  overflow:hidden;
}

.tv-magic .tvm-language::before,
.tv-magic .tvm-progress::before,
.tv-magic .tvm-toast::before,
.tv-magic .tvm-control[data-material="mist" data-surface="interface" data-elevation="s1" data-glass="mist"]::before,
.tv-magic .tvm-control[data-material="veil" data-surface="interface" data-elevation="s1" data-glass="veil"]::before,
.tv-magic .tvm-control[data-material="lens" data-surface="transient" data-elevation="s3" data-glass="lens"]::before{
  content:"";
  position:absolute;
  left:10%;
  right:10%;
  top:0;
  height:1px;
  background:linear-gradient(90deg,transparent,var(--tvm-specular),transparent);
  opacity:.72;
  pointer-events:none;
}

.tv-magic .tvm-language::after,
.tv-magic .tvm-progress::after,
.tv-magic .tvm-toast::after{
  content:"";
  position:absolute;
  left:0.125em;
  right:0.125em;
  top:1px;
  height:40%;
  border-radius:inherit;
  background:linear-gradient(180deg,var(--tvm-specular-soft),transparent);
  opacity:.34;
  pointer-events:none;
}

.tv-magic .tvm-language,
.tv-magic .tvm-progress,
.tv-magic .tvm-toast,
.tv-magic .tvm-control[data-material="mist" data-surface="interface" data-elevation="s1" data-glass="mist"],
.tv-magic .tvm-control[data-material="veil" data-surface="interface" data-elevation="s1" data-glass="veil"],
.tv-magic .tvm-control[data-material="lens" data-surface="transient" data-elevation="s3" data-glass="lens"]{
  box-shadow:
    inset 0 1px 0 var(--tvm-specular-soft),
    inset 0 -1px 0 var(--tvm-edge-dark-soft),
    var(--tvm-elevation-float);
}

@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))){
  .tv-magic .tvm-language,
  .tv-magic .tvm-progress,
  .tv-magic .tvm-toast{
    -webkit-backdrop-filter:
      blur(1em)
      saturate(var(--tvm-refraction-saturation))
      contrast(var(--tvm-refraction-contrast));
    backdrop-filter:
      blur(1em)
      saturate(var(--tvm-refraction-saturation))
      contrast(var(--tvm-refraction-contrast));
  }
  .tv-magic .tvm-control[data-material="mist" data-surface="interface" data-elevation="s1" data-glass="mist"]{
    -webkit-backdrop-filter:blur(0.5em) saturate(1.02) contrast(1.01);
    backdrop-filter:blur(0.5em) saturate(1.02) contrast(1.01);
  }
  .tv-magic .tvm-control[data-material="veil" data-surface="interface" data-elevation="s1" data-glass="veil"]{
    -webkit-backdrop-filter:blur(1.125em) saturate(1.05) contrast(1.02);
    backdrop-filter:blur(1.125em) saturate(1.05) contrast(1.02);
  }
  .tv-magic .tvm-control[data-material="lens" data-surface="transient" data-elevation="s3" data-glass="lens"]{
    -webkit-backdrop-filter:blur(1.5em) saturate(1.08) contrast(1.03);
    backdrop-filter:blur(1.5em) saturate(1.08) contrast(1.03);
  }
}

.tv-magic .tvm-control{
  transition:
    transform var(--tvm-motion-press) var(--tvm-ease),
    border-radius var(--tvm-motion-select) var(--tvm-ease),
    background var(--tvm-motion-select) var(--tvm-ease),
    border-color var(--tvm-motion-select) var(--tvm-ease),
    box-shadow var(--tvm-motion-select) var(--tvm-ease),
    opacity var(--tvm-motion-press) var(--tvm-ease);
}
.tv-magic .tvm-progress-bar{
  transition:width var(--tvm-motion-progress) var(--tvm-ease);
}
.tv-magic .tvm-toast{
  transition:
    opacity var(--tvm-motion-float-in) var(--tvm-ease),
    transform var(--tvm-motion-float-in) var(--tvm-ease);
}
.tv-magic .tvm-toast:not(.is-visible){
  transition-duration:var(--tvm-motion-float-out);
}

.tv-magic .tvm-screen,
.tv-magic .tvm-hero,
.tv-magic .tvm-lead,
.tv-magic .tvm-question,
.tv-magic .tvm-core,
.tv-magic .tvm-detail,
.tv-magic .tvm-grid,
.tv-magic .tvm-pre,
.tv-magic .tvm-prompt,
.tv-magic textarea{
  box-shadow:none;
}

@media (prefers-reduced-transparency: reduce){
  .tv-magic .tvm-language,
  .tv-magic .tvm-progress,
  .tv-magic .tvm-toast,
  .tv-magic .tvm-control[data-material="mist" data-surface="interface" data-elevation="s1" data-glass="mist"],
  .tv-magic .tvm-control[data-material="veil" data-surface="interface" data-elevation="s1" data-glass="veil"],
  .tv-magic .tvm-control[data-material="lens" data-surface="transient" data-elevation="s3" data-glass="lens"]{
    -webkit-backdrop-filter:none !important;
    backdrop-filter:none !important;
  }
  .tv-magic .tvm-language::after,
  .tv-magic .tvm-progress::after,
  .tv-magic .tvm-toast::after{
    opacity:.18;
  }
}

@media (forced-colors: active){
  .tv-magic .tvm-language::before,
  .tv-magic .tvm-language::after,
  .tv-magic .tvm-progress::before,
  .tv-magic .tvm-progress::after,
  .tv-magic .tvm-toast::before,
  .tv-magic .tvm-toast::after,
  .tv-magic .tvm-control::before{
    display:none !important;
  }
}


/* =========================================================
   Tranquil Material System v1.9
   Reactive Input / Trace Decay / Spatial Continuity
   ========================================================= */
.tv-magic{--tvm-pointer-x:50%;--tvm-pointer-y:50%;--tvm-reactive-opacity:0;--tvm-trace-size:2.625em;--tvm-trace-duration:520ms;--tvm-continuity-shift:0.625em}
.tv-magic .tvm-reactive{position:relative;isolation:isolate}
.tv-magic .tvm-reactive::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;background:radial-gradient(circle at var(--tvm-pointer-x) var(--tvm-pointer-y),rgba(255,255,255,.36) 0,rgba(255,255,255,.18) 16%,rgba(255,255,255,0) 46%);opacity:var(--tvm-reactive-opacity);transition:opacity var(--tvm-motion-press) var(--tvm-ease);z-index:1}
.tv-magic .tvm-reactive>*{position:relative;z-index:2}
.tv-magic .tvm-trace-layer{position:absolute;inset:0;overflow:hidden;pointer-events:none;border-radius:inherit;z-index:3}
.tv-magic .tvm-trace{position:absolute;width:var(--tvm-trace-size);height:var(--tvm-trace-size);margin-left:calc(var(--tvm-trace-size)/-2);margin-top:calc(var(--tvm-trace-size)/-2);border-radius:50%;background:radial-gradient(circle,rgba(255,255,255,.34) 0,rgba(255,255,255,.16) 34%,rgba(255,255,255,0) 72%);filter:blur(0.125em);opacity:.92;transform:scale(.82);animation:tvmTraceDecay var(--tvm-trace-duration) var(--tvm-ease) forwards}
@keyframes tvmTraceDecay{0%{opacity:.92;transform:scale(.82)}55%{opacity:.28;transform:scale(1.02)}100%{opacity:0;transform:scale(1.16)}}
.tv-magic .tvm-control[data-contact-state="approach"]{--tvm-reactive-opacity:.20}.tv-magic .tvm-control[data-contact-state="contact"]{--tvm-reactive-opacity:.36}.tv-magic .tvm-control[data-contact-state="pressed"]{--tvm-reactive-opacity:.52}.tv-magic .tvm-control[data-contact-state="selected"]{--tvm-reactive-opacity:.24}
.tv-magic .tvm-choice.is-preview{background:var(--tvm-surface-mist-solid);border-radius:var(--tvm-control-radius-hover)}
@supports ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){.tv-magic .tvm-choice.is-preview{background:var(--tvm-surface-mist);-webkit-backdrop-filter:blur(0.5em) saturate(1.02) contrast(1.01);backdrop-filter:blur(0.5em) saturate(1.02) contrast(1.01)}}
.tv-magic .tvm-question-shell{position:relative}.tv-magic .tvm-question-shell.is-leaving{animation:tvmQuestionLeave var(--tvm-motion-select) var(--tvm-ease) both}.tv-magic .tvm-question-shell.is-entering{animation:tvmQuestionEnter var(--tvm-motion-select) var(--tvm-ease) both}
@keyframes tvmQuestionLeave{from{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(calc(var(--tvm-continuity-shift)*-1))}}@keyframes tvmQuestionEnter{from{opacity:0;transform:translateY(var(--tvm-continuity-shift))}to{opacity:1;transform:translateY(0)}}
.tv-magic .tvm-progress{width:min(13.75em,58vw);padding:0.4375em 0.6875em}.tv-magic .tvm-progress-meta{justify-content:center;font-size:0.75em;letter-spacing:.04em}.tv-magic .tvm-progress-meta span:last-child{display:none}.tv-magic .tvm-progress-track{margin-top:0.375em}
@media (hover:hover) and (pointer:fine){.tv-magic .tvm-control:hover{--tvm-reactive-opacity:.18}}
.tv-magic[data-input-mode="touch"]{--tvm-trace-size:3.25em}.tv-magic[data-input-mode="mouse"]{--tvm-trace-size:2.5em}.tv-magic[data-input-mode="keyboard"]{--tvm-reactive-opacity:0}.tv-magic[data-input-mode="keyboard"] .tvm-reactive::after{display:none}
.tv-magic:not([data-interacting="true"]) .tvm-control{animation:none}
@media (prefers-reduced-motion:reduce){.tv-magic .tvm-trace{animation:none!important;opacity:0!important}.tv-magic .tvm-question-shell.is-leaving,.tv-magic .tvm-question-shell.is-entering{animation:none!important}}
@media (prefers-reduced-transparency:reduce){.tv-magic .tvm-reactive::after{background:radial-gradient(circle at var(--tvm-pointer-x) var(--tvm-pointer-y),rgba(255,255,255,.20) 0,rgba(255,255,255,0) 44%)}}
@media (forced-colors:active){.tv-magic .tvm-reactive::after,.tv-magic .tvm-trace-layer{display:none!important}}


/* =========================================================
   Tranquil Interaction System v2.0
   Unified Interaction Physics / Stage Environment /
   Long-press Preview / Progress Trace / True Calm
   ========================================================= */
.tv-magic{
  --tis-energy:0;
  --tis-contact-x:50%;
  --tis-contact-y:50%;
  --tis-stage-density:1;
  --tis-stage-contrast:1;
  --tis-stage-blur:1;
  --tis-stage-reflection:1;
  --tis-preview-lift:0.3125em;
}
.tv-magic[data-stage-env="outline"]{
  --tis-stage-density:.92;
  --tis-stage-contrast:1;
  --tis-stage-blur:.96;
  --tis-stage-reflection:.88;
}
.tv-magic[data-stage-env="mechanism"]{
  --tis-stage-density:1;
  --tis-stage-contrast:1.02;
  --tis-stage-blur:1;
  --tis-stage-reflection:1;
}
.tv-magic[data-stage-env="almost"]{
  --tis-stage-density:1.04;
  --tis-stage-contrast:1.03;
  --tis-stage-blur:1.02;
  --tis-stage-reflection:1.06;
}
.tv-magic[data-stage-env="result"]{
  --tis-stage-density:.98;
  --tis-stage-contrast:1.01;
  --tis-stage-blur:.98;
  --tis-stage-reflection:.92;
}
.tv-magic .tvm-reactive{
  --tvm-pointer-x:var(--tis-contact-x);
  --tvm-pointer-y:var(--tis-contact-y);
}
.tv-magic .tvm-reactive::after{
  opacity:calc(var(--tis-energy) * .44);
  background:
    radial-gradient(
      circle at var(--tis-contact-x) var(--tis-contact-y),
      rgba(255,255,255,calc(.40 * var(--tis-stage-reflection))) 0,
      rgba(255,255,255,calc(.16 * var(--tis-stage-reflection))) 18%,
      rgba(255,255,255,0) 48%
    );
}
.tv-magic[data-calm="true"]{--tis-energy:0}
.tv-magic[data-calm="true"] .tvm-control{animation:none}
.tv-magic .tvm-control{filter:contrast(var(--tis-stage-contrast))}
.tv-magic .tvm-control[data-contact-state="approach"]{--tis-energy:.22}
.tv-magic .tvm-control[data-contact-state="contact"]{--tis-energy:.34}
.tv-magic .tvm-control[data-contact-state="pressed"]{--tis-energy:.62}
.tv-magic .tvm-control[data-contact-state="selected"]{--tis-energy:.28}

.tv-magic .tvm-choice.is-long-preview{
  transform:translateY(calc(var(--tis-preview-lift) * -1)) scale(1.008);
  background:var(--tvm-surface-veil-solid);
  box-shadow:
    inset 0 1px 0 var(--tvm-specular-soft),
    inset 0 -1px 0 var(--tvm-edge-dark-soft),
    0 0.75em 1.75em rgba(22,22,20,.10);
}
@supports ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){
  .tv-magic .tvm-choice.is-long-preview{
    background:var(--tvm-surface-veil);
    -webkit-backdrop-filter:blur(0.875em) saturate(1.04) contrast(1.02);
    backdrop-filter:blur(0.875em) saturate(1.04) contrast(1.02);
  }
}

.tv-magic .tvm-progress-track{position:relative}
.tv-magic .tvm-progress-traces{
  position:absolute;
  inset:0;
  pointer-events:none;
}
.tv-magic .tvm-progress-trace{
  position:absolute;
  top:50%;
  width:0.25em;
  height:0.25em;
  margin:-0.125em 0 0 -0.125em;
  border-radius:50%;
  background:currentColor;
  opacity:.28;
  transform:scale(.9);
}
.tv-magic .tvm-progress-trace.is-current{
  opacity:.62;
  transform:scale(1.18);
}
.tv-magic .tvm-language,
.tv-magic .tvm-progress,
.tv-magic .tvm-toast,
.tv-magic .tvm-control[data-material="mist" data-surface="interface" data-elevation="s1" data-glass="mist"],
.tv-magic .tvm-control[data-material="veil" data-surface="interface" data-elevation="s1" data-glass="veil"],
.tv-magic .tvm-control[data-material="lens" data-surface="transient" data-elevation="s3" data-glass="lens"]{
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,calc(.42 * var(--tis-stage-reflection))),
    inset 0 -1px 0 var(--tvm-edge-dark-soft),
    0 calc(0.5em * var(--tis-stage-density)) calc(1.5em * var(--tis-stage-density)) rgba(22,22,20,.08);
}
@supports ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){
  .tv-magic .tvm-language,
  .tv-magic .tvm-progress,
  .tv-magic .tvm-toast{
    -webkit-backdrop-filter:
      blur(calc(1em * var(--tis-stage-blur)))
      saturate(calc(1.03 * var(--tis-stage-density)))
      contrast(var(--tis-stage-contrast));
    backdrop-filter:
      blur(calc(1em * var(--tis-stage-blur)))
      saturate(calc(1.03 * var(--tis-stage-density)))
      contrast(var(--tis-stage-contrast));
  }
}
.tv-magic[data-calm="true"] .tvm-reactive::after{opacity:0}
.tv-magic .tvm-choice.is-long-preview{cursor:default}
@media (prefers-reduced-motion:reduce){
  .tv-magic .tvm-choice.is-long-preview{transform:none !important}
}
@media (forced-colors:active){
  .tv-magic .tvm-choice.is-long-preview{
    outline:0.125em solid Highlight;
    box-shadow:none;
  }
}


/* =========================================================
   Tranquil Interaction System v2.1
   Semantic Elevation / Surface Semantics /
   Container Query / Unified Generating & Error States
   ========================================================= */

.tv-magic{
  container-type:inline-size;
  container-name:tvmagic;

  /* Semantic elevation */
  --tis-elev-s0:0;
  --tis-elev-s1:10;
  --tis-elev-s2:20;
  --tis-elev-s3:30;

  /* Surface semantics */
  --tis-content-bg:transparent;
  --tis-interface-bg:var(--tvm-surface-clear);
  --tis-transient-bg:var(--tvm-surface-veil);

  /* Responsive geometry tokens */
  --tis-inline-pad:0;
  --tis-choice-gap:0.75em;
  --tis-result-gap:1em;
  --tis-max-control:42.5em;
}

/* ---------------------------------------------------------
   Semantic elevation layers
   S0 Canvas / S1 Surface / S2 Float / S3 Focus
   --------------------------------------------------------- */
.tv-magic [data-elevation="s0"]{z-index:var(--tis-elev-s0)}
.tv-magic [data-elevation="s1"]{z-index:var(--tis-elev-s1)}
.tv-magic [data-elevation="s2"]{z-index:var(--tis-elev-s2)}
.tv-magic [data-elevation="s3"]{z-index:var(--tis-elev-s3)}

/* ---------------------------------------------------------
   Surface semantics
   content = Clear
   interface = interactive surface
   transient = temporary focus surface
   --------------------------------------------------------- */
.tv-magic [data-surface="content"]{
  background:var(--tis-content-bg);
  -webkit-backdrop-filter:none;
  backdrop-filter:none;
  box-shadow:none;
}

.tv-magic [data-surface="interface"]{
  position:relative;
}

.tv-magic [data-surface="transient"]{
  position:relative;
}

/* Content must never inherit glass */
.tv-magic [data-surface="content"]::before,
.tv-magic [data-surface="content"]::after{
  display:none !important;
}

/* ---------------------------------------------------------
   Glass eligibility contract
   Only interface/transient surfaces may blur.
   --------------------------------------------------------- */
.tv-magic [data-surface="interface"][data-glass="mist"]{
  background:var(--tvm-surface-mist-solid);
}
.tv-magic [data-surface="interface"][data-glass="veil"],
.tv-magic [data-surface="transient"][data-glass="veil"]{
  background:var(--tvm-surface-veil-solid);
}
.tv-magic [data-surface="transient"][data-glass="lens"]{
  background:var(--tvm-surface-lens-solid);
}

@supports ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){
  .tv-magic [data-surface="interface"][data-glass="mist"]{
    background:var(--tvm-surface-mist);
    -webkit-backdrop-filter:blur(0.5em) saturate(1.02) contrast(1.01);
    backdrop-filter:blur(0.5em) saturate(1.02) contrast(1.01);
  }

  .tv-magic [data-surface="interface"][data-glass="veil"],
  .tv-magic [data-surface="transient"][data-glass="veil"]{
    background:var(--tvm-surface-veil);
    -webkit-backdrop-filter:blur(1.125em) saturate(1.05) contrast(1.02);
    backdrop-filter:blur(1.125em) saturate(1.05) contrast(1.02);
  }

  .tv-magic [data-surface="transient"][data-glass="lens"]{
    background:var(--tvm-surface-lens);
    -webkit-backdrop-filter:blur(1.5em) saturate(1.08) contrast(1.03);
    backdrop-filter:blur(1.5em) saturate(1.08) contrast(1.03);
  }
}

/* ---------------------------------------------------------
   Single-DOM responsive contract
   Geometry changes only; markup remains identical.
   --------------------------------------------------------- */
.tv-magic .tvm-screen{
  padding-inline:var(--tis-inline-pad);
}

.tv-magic .tvm-choices{
  gap:var(--tis-choice-gap);
}

.tv-magic .tvm-choice,
.tv-magic .tvm-btn,
.tv-magic .tvm-back{
  width:min(100%,var(--tis-max-control));
}

.tv-magic .tvm-grid{
  gap:var(--tis-result-gap);
}

@container tvmagic (max-width: 32.5em){
  .tv-magic{
    --tis-inline-pad:0;
    --tis-choice-gap:0.625em;
    --tis-result-gap:0.75em;
    --tis-max-control:100%;
  }

  .tv-magic .tvm-progress{
    width:min(12.5em,64cqw);
  }

  .tv-magic .tvm-language{
    max-width:100%;
  }

  .tv-magic .tvm-grid{
    grid-template-columns:1fr;
  }
}

@container tvmagic (min-width: 32.5625em) and (max-width: 51.25em){
  .tv-magic{
    --tis-choice-gap:0.75em;
    --tis-result-gap:1em;
    --tis-max-control:40em;
  }

  .tv-magic .tvm-progress{
    width:min(13.75em,40cqw);
  }
}

@container tvmagic (min-width: 51.3125em){
  .tv-magic{
    --tis-choice-gap:0.875em;
    --tis-result-gap:1.25em;
    --tis-max-control:42.5em;
  }
}

/* Fallback for browsers without container queries */
@supports not (container-type:inline-size){
  @media (max-width:40em){
    .tv-magic{
      --tis-choice-gap:0.625em;
      --tis-result-gap:0.75em;
      --tis-max-control:100%;
    }

    .tv-magic .tvm-grid{
      grid-template-columns:1fr;
    }
  }
}

/* ---------------------------------------------------------
   Unified generating/error state surfaces
   --------------------------------------------------------- */
.tv-magic .tvm-state-surface{
  width:min(100%,42.5em);
  margin-inline:auto;
  padding:1.25em;
  border:1px solid var(--tvm-glass-border);
  border-radius:var(--tvm-radius-24);
  background:var(--tvm-surface-veil-solid);
  box-shadow:var(--tvm-elevation-float);
  text-align:center;
}

@supports ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){
  .tv-magic .tvm-state-surface{
    background:var(--tvm-surface-veil);
    -webkit-backdrop-filter:blur(1.125em) saturate(1.05) contrast(1.02);
    backdrop-filter:blur(1.125em) saturate(1.05) contrast(1.02);
  }
}

.tv-magic .tvm-state-surface[data-state="generating"]{
  transform:translateY(0);
  opacity:1;
}

.tv-magic .tvm-state-surface[data-state="error"]{
  border-style:dashed;
}

.tv-magic .tvm-state-title{
  margin:0;
  font:inherit;
  font-weight:600;
}

.tv-magic .tvm-state-copy{
  margin:0.5em 0 0;
  font-size:0.8125em;
  line-height:1.6;
  opacity:.72;
}

.tv-magic .tvm-state-actions{
  display:flex;
  justify-content:center;
  gap:0.625em;
  margin-top:1em;
  flex-wrap:wrap;
}

/* State continuity */
.tv-magic .tvm-state-surface.is-entering{
  animation:tisStateEnter var(--tvm-motion-float-in) var(--tvm-ease) both;
}

@keyframes tisStateEnter{
  from{
    opacity:0;
    transform:translateY(0.5em) scale(.99);
  }
  to{
    opacity:1;
    transform:translateY(0) scale(1);
  }
}

/* Accessibility */
@media (prefers-reduced-motion:reduce){
  .tv-magic .tvm-state-surface.is-entering{
    animation:none !important;
  }
}

@media (prefers-reduced-transparency:reduce){
  .tv-magic .tvm-state-surface{
    -webkit-backdrop-filter:none !important;
    backdrop-filter:none !important;
    background:var(--tvm-surface-veil-solid);
  }
}

@media (forced-colors:active){
  .tv-magic .tvm-state-surface{
    background:Canvas;
    color:CanvasText;
    border:1px solid ButtonText;
    box-shadow:none;
  }
}


/* =========================================================
   Tranquil Interaction System v2.3
   Role Radius / Focus-visible / QA Contracts
   ========================================================= */

.tv-magic{
  /* Role radius aliases */
  --tis-radius-control:var(--tvm-radius-16);
  --tis-radius-control-active:1.25em;
  --tis-radius-floating:var(--tvm-radius-24);
  --tis-radius-dialog:var(--tvm-radius-24);
  --tis-radius-pill:var(--tvm-radius-pill);

  /* Accessibility contract */
  --tis-focus-width:0.125em;
  --tis-focus-offset:0.1875em;
  --tis-focus-color:currentColor;
}

/* Role-based geometry */
.tv-magic .tvm-control{
  border-radius:var(--tis-radius-control);
}
.tv-magic .tvm-control:active:not(:disabled){
  border-radius:var(--tis-radius-control-active);
}
.tv-magic .tvm-progress,
.tv-magic .tvm-state-surface,
.tv-magic .tvm-toast{
  border-radius:var(--tis-radius-floating);
}
.tv-magic .tvm-language,
.tv-magic .tvm-lang{
  border-radius:var(--tis-radius-pill);
}

/* Pointer focus must not imitate keyboard focus. */
.tv-magic .tvm-control:focus{
  outline:none;
}
.tv-magic .tvm-control:focus-visible,
.tv-magic .tvm-lang:focus-visible,
.tv-magic summary:focus-visible,
.tv-magic textarea:focus-visible{
  outline:var(--tis-focus-width) solid var(--tis-focus-color);
  outline-offset:var(--tis-focus-offset);
}

/* Error state accessibility */
.tv-magic .tvm-state-surface[data-state="error"] .tvm-state-title{
  font-weight:700;
}
.tv-magic .tvm-state-surface[data-state="error"] .tvm-state-copy{
  max-width:52ch;
  margin-inline:auto;
}

/* QA contract: content may never become glass. */
.tv-magic [data-surface="content"][data-glass]{
  -webkit-backdrop-filter:none !important;
  backdrop-filter:none !important;
  background:transparent !important;
  box-shadow:none !important;
}

/* Reduced-motion contract: remove travel, keep state meaning. */
@media (prefers-reduced-motion:reduce){
  .tv-magic .tvm-control,
  .tv-magic .tvm-progress-bar,
  .tv-magic .tvm-toast,
  .tv-magic .tvm-question-shell,
  .tv-magic .tvm-state-surface{
    transition-duration:1ms !important;
    animation-duration:1ms !important;
    animation-iteration-count:1 !important;
  }
}

/* Reduced-transparency contract: all glass surfaces become solid. */
@media (prefers-reduced-transparency:reduce){
  .tv-magic [data-glass="mist"]{
    -webkit-backdrop-filter:none !important;
    backdrop-filter:none !important;
    background:var(--tvm-surface-mist-solid) !important;
  }
  .tv-magic [data-glass="veil"]{
    -webkit-backdrop-filter:none !important;
    backdrop-filter:none !important;
    background:var(--tvm-surface-veil-solid) !important;
  }
  .tv-magic [data-glass="lens"]{
    -webkit-backdrop-filter:none !important;
    backdrop-filter:none !important;
    background:var(--tvm-surface-lens-solid) !important;
  }
}

/* Forced-colors contract */
@media (forced-colors:active){
  .tv-magic [data-surface="interface"],
  .tv-magic [data-surface="transient"]{
    forced-color-adjust:auto;
    color:CanvasText !important;
    background:Canvas !important;
    border-color:ButtonText !important;
    box-shadow:none !important;
    -webkit-backdrop-filter:none !important;
    backdrop-filter:none !important;
  }

  .tv-magic .tvm-control:focus-visible,
  .tv-magic .tvm-lang:focus-visible,
  .tv-magic summary:focus-visible,
  .tv-magic textarea:focus-visible{
    outline-color:Highlight;
  }
}


.tv-magic .tvm-spacer--detail-section{height:1.75em}

@media (forced-colors:active){
  .tv-magic.is-focus{
    background-image:none !important;
    background-color:Canvas !important;
  }
}


/* =========================================================
   v4.1 — Density / balance / hover physics refinement
   ========================================================= */

/* Entry */
.tv-magic .tvm-entry .tvm-hero{
  max-width:12em;
  margin-left:auto;
  margin-right:auto;
}
.tv-magic .tvm-entry .tvm-lead{
  max-width:32em;
  font-size:.975em;
}
.tv-magic .tvm-entry #tvmStart{
  width:min(20em,100%);
  box-shadow:0 .35em 1em rgba(22,22,20,.065);
}

/* Questions */
.tv-magic .tvm-choice{
  font-size:1.025em;
}
.tv-magic.is-focus .tvm-question-frame{
  padding-top:1.375em;
}
.tv-magic.is-focus .tvm-question-frame .tvm-choice:not(.is-selected){
  border-color:var(--tvm-focus-choice-border) !important;
}
.tv-magic.is-focus .tvm-question-frame .tvm-choice:hover:not(.is-selected){
  border-color:rgba(32,38,36,.15) !important;
}
.tv-magic .tvm-progress-meta{
  opacity:.78;
}

/* Result width and hierarchy */
.tv-magic .tvm-result-screen{
  width:min(44em,100%);
}
.tv-magic .tvm-result-screen .tvm-core{
  max-width:38em;
  font-size:1.2em;
  line-height:1.85;
}
.tv-magic .tvm-result-screen .tvm-summary-section{
  margin-top:4.5em;
}
.tv-magic .tvm-summary-grid{
  grid-template-columns:9em minmax(0,1fr);
}
.tv-magic .tvm-grid{
  grid-template-columns:8.5em minmax(0,1fr);
}
.tv-magic .tvm-carry-lead{
  color:rgba(32,38,36,.68);
}
.tv-magic .tvm-copy-action{
  text-align:center;
}
.tv-magic .tvm-copy-action .tvm-btn{
  width:100%;
  max-width:24em;
  margin-left:auto;
  margin-right:auto;
}
.tv-magic .tvm-prompt-heading{
  margin-bottom:1.15em;
}
.tv-magic .tvm-prompt{
  min-height:9em;
  max-height:22em;
  border-color:rgba(32,38,36,.10);
  background:rgba(255,255,255,.30);
}
.tv-magic .tvm-share{
  margin-top:4.25em;
}
.tv-magic .tvm-share-row{
  gap:1em;
}
.tv-magic .tvm-share-btn{
  width:2.875em;
  height:2.875em;
  min-width:2.875em;
  min-height:2.875em;
}
.tv-magic .tvm-result-restart{
  margin-top:3.125em;
}

/* On narrow layouts the definition grids collapse back to a natural reading edge. */
@media(max-width:30em){
  .tv-magic .tvm-summary-grid,
  .tv-magic .tvm-grid{
    grid-template-columns:1fr;
  }
  .tv-magic .tvm-share-btn{
    width:2.875em;
    height:2.875em;
    min-width:2.875em;
    min-height:2.875em;
  }
}

/*
  Hover no longer lifts controls.
  Position remains fixed; only material/contrast changes.
  Press remains a small downward/physical scale response.
*/
@media (hover:hover) and (pointer:fine){
  .tv-magic .tvm-control:hover:not(:disabled){
    transform:none !important;
  }
  .tv-magic .tvm-btn:hover:not(:disabled){
    background:var(--tvm-surface-strong);
  }
  .tv-magic .tvm-btn.is-ghost:hover:not(:disabled),
  .tv-magic .tvm-back:hover:not(:disabled),
  .tv-magic .tvm-focus-toggle:hover:not(:disabled){
    background:transparent;
    color:var(--tvm-ink);
    opacity:1;
  }
  .tv-magic .tvm-share-btn:hover:not(:disabled){
    background:rgba(255,255,255,.62);
    border-color:rgba(32,38,36,.20);
  }
}
.tv-magic .tvm-control:active:not(:disabled){
  transform:scale(.975);
}
.tv-magic .tvm-choice:active:not(:disabled){
  transform:scale(.985);
}
.tv-magic .tvm-share-btn:active:not(:disabled){
  transform:scale(.97);
}


/* =========================================================
   v4.2 — Grouped result laws / prompt alignment / hover state contract
   Inspired by Library v8.8 + Osaka Guide v11.0 interaction semantics.
   ========================================================= */

/* Result laws: one centered semantic group, without a static Glass card. */
.tv-magic .tvm-summary-section{
  text-align:center;
}
.tv-magic .tvm-law-group{
  width:min(36em,100%);
  margin-left:auto;
  margin-right:auto;
  text-align:center;
}
.tv-magic .tvm-summary-section .tvm-result-section-title{
  margin-bottom:1.5em;
  text-align:center;
}
.tv-magic .tvm-law-list,
.tv-magic .tvm-summary-grid,
.tv-magic .tvm-grid{
  display:grid;
  grid-template-columns:1fr;
  gap:1.15em;
  width:100%;
  margin:0 auto;
  text-align:center;
}
.tv-magic .tvm-law-row{
  display:grid;
  grid-template-columns:1fr;
  gap:.2em;
  justify-items:center;
  min-width:0;
  text-align:center;
}
.tv-magic .tvm-law-row dt,
.tv-magic .tvm-law-row dd,
.tv-magic .tvm-summary-grid dt,
.tv-magic .tvm-summary-grid dd,
.tv-magic .tvm-grid dt,
.tv-magic .tvm-grid dd{
  width:100%;
  margin:0;
  text-align:center;
}
.tv-magic .tvm-law-row dt{
  color:var(--tvm-muted);
  font-size:.86em;
  line-height:1.5;
}
.tv-magic .tvm-law-row dd{
  color:var(--tvm-ink);
  line-height:1.72;
}
.tv-magic .tvm-law-row--ontology{
  width:min(34em,100%);
  margin-left:auto;
  margin-right:auto;
}
.tv-magic .tvm-law-row--ontology dd{
  max-width:34em;
}
.tv-magic .tvm-summary-section .tvm-detail{
  text-align:center;
}
.tv-magic .tvm-summary-section .tvm-detail-title{
  margin-bottom:1.35em;
  text-align:center;
}

/* Carry prompt: the whole subsection is centered as a unit.
   Long prompt contents remain left-aligned inside the textarea. */
.tv-magic .tvm-prompt-group{
  width:min(38em,100%);
  margin-left:auto;
  margin-right:auto;
  text-align:center;
}
.tv-magic .tvm-carry-section .tvm-prompt-heading{
  margin-left:auto;
  margin-right:auto;
  text-align:center;
}
.tv-magic .tvm-carry-section .tvm-prompt{
  display:block;
  width:100%;
  max-width:38em;
  margin-left:auto;
  margin-right:auto;
  text-align:left;
}
.tv-magic .tvm-carry-section .tvm-note{
  max-width:34em;
  margin-left:auto;
  margin-right:auto;
  text-align:center;
}

/* -----------------------------------------
   Interaction state contract
   rest -> hover -> focus -> active/selected
   Hover never moves the control.
----------------------------------------- */
.tv-magic{
  --tvm-hover-soft:rgba(106,125,137,.055);
  --tvm-hover-medium:rgba(106,125,137,.075);
  --tvm-hover-line:rgba(32,38,36,.18);
  --tvm-focus-soft:rgba(106,125,137,.10);
  --tvm-selected-line:rgba(32,38,36,.22);
}

/* Ghost navigation: color/opacity only. */
@media (hover:hover) and (pointer:fine){
  .tv-magic .tvm-back:hover:not(:disabled),
  .tv-magic .tvm-result-restart .tvm-btn:hover:not(:disabled),
  .tv-magic .tvm-focus-toggle:hover:not(:disabled){
    transform:none !important;
    background:transparent !important;
    border-color:transparent !important;
    color:var(--tvm-ink) !important;
    opacity:1;
    box-shadow:none !important;
    -webkit-backdrop-filter:none !important;
    backdrop-filter:none !important;
  }

  /* Primary actions: subtle fill only. */
  .tv-magic .tvm-btn.is-primary:hover:not(:disabled){
    transform:none !important;
    background:var(--tvm-hover-medium) !important;
    border-color:rgba(32,38,36,.14) !important;
    box-shadow:none !important;
    -webkit-backdrop-filter:none !important;
    backdrop-filter:none !important;
  }

  /* Language selector: quiet surface; active state remains authoritative. */
  .tv-magic .tvm-lang:hover:not(.is-active):not(:disabled){
    transform:none !important;
    background:var(--tvm-hover-soft) !important;
    color:var(--tvm-ink);
    box-shadow:none !important;
    -webkit-backdrop-filter:none !important;
    backdrop-filter:none !important;
  }
  .tv-magic .tvm-lang.is-active:hover{
    transform:none !important;
    background:var(--tvm-clear) !important;
  }

  /* Choice: surface + border, but selected always wins over hover. */
  .tv-magic .tvm-choice:hover:not(.is-selected):not(:disabled){
    transform:none !important;
    background:var(--tvm-hover-soft) !important;
    border-color:var(--tvm-hover-line) !important;
    box-shadow:none !important;
    -webkit-backdrop-filter:none !important;
    backdrop-filter:none !important;
  }
  .tv-magic .tvm-choice.is-selected:hover{
    transform:none !important;
    background:var(--tvm-veil-solid) !important;
    border-color:var(--tvm-selected-line) !important;
  }

  /* Share icons: gentle material increase. */
  .tv-magic .tvm-share-btn:hover:not(:disabled){
    transform:none !important;
    background:var(--tvm-hover-soft);
    border-color:var(--tvm-hover-line);
    opacity:1;
  }

  /* Tooltip is the preview layer: opacity + scale, never button lift. */
  .tv-magic .tvm-share-btn::after{
    transform:translateX(-50%) scale(.94);
    transform-origin:50% 100%;
  }
  .tv-magic .tvm-share-btn:hover::after,
  .tv-magic .tvm-share-btn:focus-visible::after{
    transform:translateX(-50%) scale(1);
  }
}

/* Focus is deliberately stronger than hover. */
.tv-magic .tvm-btn:focus-visible,
.tv-magic .tvm-choice:focus-visible,
.tv-magic .tvm-back:focus-visible,
.tv-magic .tvm-lang:focus-visible,
.tv-magic .tvm-focus-toggle:focus-visible,
.tv-magic .tvm-share-btn:focus-visible{
  outline:var(--tvm-focus-ring);
  outline-offset:var(--tvm-focus-offset);
}
.tv-magic .tvm-choice:focus-visible{
  background:var(--tvm-focus-soft);
  border-color:rgba(32,38,36,.28);
}

/* Press stays physical. */
.tv-magic .tvm-btn:active:not(:disabled),
.tv-magic .tvm-lang:active:not(:disabled),
.tv-magic .tvm-back:active:not(:disabled),
.tv-magic .tvm-focus-toggle:active:not(:disabled){
  transform:scale(.975);
}
.tv-magic .tvm-choice:active:not(:disabled){
  transform:scale(.985);
}
.tv-magic .tvm-share-btn:active:not(:disabled){
  transform:scale(.97);
}

@media(max-width:30em){
  .tv-magic .tvm-law-group,
  .tv-magic .tvm-prompt-group{
    width:100%;
  }
  .tv-magic .tvm-law-row--ontology{
    width:100%;
  }
}

@media(prefers-reduced-motion:reduce){
  .tv-magic .tvm-share-btn::after{
    transform:translateX(-50%) scale(1) !important;
  }
}


/* =========================================================
   v4.3 — Typography consolidation + unified control states
   ========================================================= */

.tv-magic{
  /* -------------------------------------------------------
     Typography — non-heading text uses only four base styles.
     Bold / italic / muted are modifiers, not new type styles.
     ------------------------------------------------------- */
  --tvm-text-body-size:1em;
  --tvm-text-body-weight:400;
  --tvm-text-body-line:1.75;
  --tvm-text-body-track:0;

  --tvm-text-ui-size:1em;
  --tvm-text-ui-weight:400;
  --tvm-text-ui-line:1.5;
  --tvm-text-ui-track:0;

  --tvm-text-meta-size:.8125em;
  --tvm-text-meta-weight:400;
  --tvm-text-meta-line:1.6;
  --tvm-text-meta-track:.03em;

  --tvm-text-code-size:.8125em;
  --tvm-text-code-weight:400;
  --tvm-text-code-line:1.65;
  --tvm-text-code-track:0;

  --tvm-weight-regular:400;
  --tvm-weight-medium:560;
  --tvm-weight-semibold:600;
  --tvm-weight-bold:700;

  /* -------------------------------------------------------
     Unified control state tokens.
     Every button/control uses the same rest → hover → focus
     → active state change. Shape may differ; behavior does not.
     ------------------------------------------------------- */
  --tvm-control-rest-bg:rgba(255,255,255,.28);
  --tvm-control-rest-border:rgba(32,38,36,.11);
  --tvm-control-rest-color:var(--tvm-ink);

  --tvm-control-hover-bg:rgba(106,125,137,.065);
  --tvm-control-hover-border:rgba(32,38,36,.18);
  --tvm-control-hover-color:var(--tvm-ink);

  --tvm-control-focus-bg:rgba(106,125,137,.10);
  --tvm-control-focus-border:rgba(32,38,36,.28);

  --tvm-control-active-bg:rgba(106,125,137,.12);
  --tvm-control-active-scale:.975;

  --tvm-control-selected-bg:rgba(255,255,255,.46);
  --tvm-control-selected-border:rgba(32,38,36,.22);
  --tvm-control-disabled-opacity:.52;
}

/* ---------------------------------------------------------
   Text / Body
   --------------------------------------------------------- */
.tv-magic .tvm-lead,
.tv-magic .tvm-core,
.tv-magic .tvm-summary-grid dd,
.tv-magic .tvm-grid dd,
.tv-magic .tvm-carry-lead,
.tv-magic .tvm-error{
  font-size:var(--tvm-text-body-size);
  font-weight:var(--tvm-text-body-weight);
  line-height:var(--tvm-text-body-line);
  letter-spacing:var(--tvm-text-body-track);
}

/* ---------------------------------------------------------
   Text / UI
   --------------------------------------------------------- */
.tv-magic .tvm-btn,
.tv-magic .tvm-choice,
.tv-magic .tvm-lang,
.tv-magic .tvm-back,
.tv-magic .tvm-focus-toggle,
.tv-magic .tvm-share-btn{
  font-size:var(--tvm-text-ui-size);
  font-weight:var(--tvm-text-ui-weight);
  line-height:var(--tvm-text-ui-line);
  letter-spacing:var(--tvm-text-ui-track);
}

/* ---------------------------------------------------------
   Text / Meta
   --------------------------------------------------------- */
.tv-magic .tvm-kicker,
.tv-magic .tvm-name,
.tv-magic .tvm-question-meta,
.tv-magic .tvm-progress-meta,
.tv-magic .tvm-helper,
.tv-magic .tvm-note,
.tv-magic .tvm-detail-title,
.tv-magic .tvm-summary-grid dt,
.tv-magic .tvm-grid dt,
.tv-magic .tvm-state-copy,
.tv-magic .tvm-share-btn::after{
  font-size:var(--tvm-text-meta-size);
  font-weight:var(--tvm-text-meta-weight);
  line-height:var(--tvm-text-meta-line);
  letter-spacing:var(--tvm-text-meta-track);
}

/* Semantic labels use the same Meta style + Semibold modifier. */
.tv-magic .tvm-summary-grid dt,
.tv-magic .tvm-grid dt{
  font-weight:var(--tvm-weight-semibold);
}

/* ---------------------------------------------------------
   Text / Code
   --------------------------------------------------------- */
.tv-magic .tvm-pre,
.tv-magic .tvm-prompt{
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size:var(--tvm-text-code-size);
  font-weight:var(--tvm-text-code-weight);
  line-height:var(--tvm-text-code-line);
  letter-spacing:var(--tvm-text-code-track);
}

/* Modifiers — optional, not separate typography styles. */
.tv-magic .is-medium{font-weight:var(--tvm-weight-medium)}
.tv-magic .is-semibold{font-weight:var(--tvm-weight-semibold)}
.tv-magic .is-bold{font-weight:var(--tvm-weight-bold)}
.tv-magic .is-italic{font-style:italic}
.tv-magic .is-muted{color:var(--tvm-muted)}

/* ---------------------------------------------------------
   Result laws — preserve the prior two-column structure,
   but center the whole information group.
   --------------------------------------------------------- */
.tv-magic .tvm-summary-section{
  text-align:center;
}
.tv-magic .tvm-law-group{
  width:min(38em,100%);
  margin-left:auto;
  margin-right:auto;
  text-align:center;
}
.tv-magic .tvm-summary-section .tvm-result-section-title{
  text-align:center;
  margin-bottom:1.5em;
}
.tv-magic .tvm-summary-grid,
.tv-magic .tvm-grid{
  display:grid;
  grid-template-columns:minmax(7.8em,max-content) minmax(0,1fr);
  gap:.72em 1.15em;
  width:min(34em,100%);
  margin-left:auto;
  margin-right:auto;
  text-align:left;
}
.tv-magic .tvm-summary-grid dt,
.tv-magic .tvm-grid dt{
  margin:0;
  text-align:right;
  color:var(--tvm-muted);
}
.tv-magic .tvm-summary-grid dd,
.tv-magic .tvm-grid dd{
  margin:0;
  text-align:left;
  overflow-wrap:anywhere;
}
.tv-magic .tvm-summary-section .tvm-detail{
  text-align:center;
}
.tv-magic .tvm-summary-section .tvm-detail-title{
  margin-bottom:1.35em;
  text-align:center;
}
.tv-magic .tvm-grid--secondary{
  width:min(34em,100%);
}
.tv-magic .tvm-grid--secondary dd:last-child{
  max-width:24em;
}

/* ---------------------------------------------------------
   Unified control behavior.
   --------------------------------------------------------- */

/* Base rest state. */
.tv-magic .tvm-control,
.tv-magic .tvm-lang,
.tv-magic .tvm-choice,
.tv-magic .tvm-btn,
.tv-magic .tvm-back,
.tv-magic .tvm-focus-toggle,
.tv-magic .tvm-share-btn{
  color:var(--tvm-control-rest-color);
  transform:none;
}

/* Surface-bearing controls use shared rest tokens. */
.tv-magic .tvm-btn:not(.is-ghost),
.tv-magic .tvm-choice,
.tv-magic .tvm-lang,
.tv-magic .tvm-share-btn{
  background:var(--tvm-control-rest-bg);
  border-color:var(--tvm-control-rest-border);
}

/* Ghost/navigation controls stay transparent at rest. */
.tv-magic .tvm-btn.is-ghost,
.tv-magic .tvm-back,
.tv-magic .tvm-focus-toggle{
  background:transparent;
  border-color:transparent;
  box-shadow:none;
  -webkit-backdrop-filter:none;
  backdrop-filter:none;
}

/* Selected state is persistent and wins over hover. */
.tv-magic .tvm-choice.is-selected,
.tv-magic .tvm-lang.is-active{
  background:var(--tvm-control-selected-bg);
  border-color:var(--tvm-control-selected-border);
}

/* Hover: all buttons change the same properties and never move. */
@media (hover:hover) and (pointer:fine){
  .tv-magic .tvm-control:hover:not(:disabled),
  .tv-magic .tvm-lang:hover:not(:disabled),
  .tv-magic .tvm-choice:hover:not(:disabled),
  .tv-magic .tvm-btn:hover:not(:disabled),
  .tv-magic .tvm-back:hover:not(:disabled),
  .tv-magic .tvm-focus-toggle:hover:not(:disabled),
  .tv-magic .tvm-share-btn:hover:not(:disabled){
    transform:none !important;
    color:var(--tvm-control-hover-color) !important;
  }

  .tv-magic .tvm-btn:not(.is-ghost):hover:not(:disabled),
  .tv-magic .tvm-choice:hover:not(.is-selected):not(:disabled),
  .tv-magic .tvm-lang:hover:not(.is-active):not(:disabled),
  .tv-magic .tvm-share-btn:hover:not(:disabled){
    background:var(--tvm-control-hover-bg) !important;
    border-color:var(--tvm-control-hover-border) !important;
    box-shadow:none !important;
    -webkit-backdrop-filter:none !important;
    backdrop-filter:none !important;
  }

  .tv-magic .tvm-btn.is-ghost:hover:not(:disabled),
  .tv-magic .tvm-back:hover:not(:disabled),
  .tv-magic .tvm-focus-toggle:hover:not(:disabled){
    background:transparent !important;
    border-color:transparent !important;
    box-shadow:none !important;
  }

  .tv-magic .tvm-choice.is-selected:hover,
  .tv-magic .tvm-lang.is-active:hover{
    background:var(--tvm-control-selected-bg) !important;
    border-color:var(--tvm-control-selected-border) !important;
  }
}

/* Focus-visible: same across all control types and stronger than hover. */
.tv-magic .tvm-control:focus-visible,
.tv-magic .tvm-lang:focus-visible,
.tv-magic .tvm-choice:focus-visible,
.tv-magic .tvm-btn:focus-visible,
.tv-magic .tvm-back:focus-visible,
.tv-magic .tvm-focus-toggle:focus-visible,
.tv-magic .tvm-share-btn:focus-visible{
  outline:var(--tvm-focus-ring);
  outline-offset:var(--tvm-focus-offset);
}
.tv-magic .tvm-btn:not(.is-ghost):focus-visible,
.tv-magic .tvm-choice:focus-visible,
.tv-magic .tvm-lang:focus-visible,
.tv-magic .tvm-share-btn:focus-visible{
  background:var(--tvm-control-focus-bg);
  border-color:var(--tvm-control-focus-border);
}

/* Press: same physical rule everywhere. */
.tv-magic .tvm-control:active:not(:disabled),
.tv-magic .tvm-lang:active:not(:disabled),
.tv-magic .tvm-choice:active:not(:disabled),
.tv-magic .tvm-btn:active:not(:disabled),
.tv-magic .tvm-back:active:not(:disabled),
.tv-magic .tvm-focus-toggle:active:not(:disabled),
.tv-magic .tvm-share-btn:active:not(:disabled){
  transform:scale(var(--tvm-control-active-scale)) !important;
}
.tv-magic .tvm-btn:not(.is-ghost):active:not(:disabled),
.tv-magic .tvm-choice:active:not(:disabled),
.tv-magic .tvm-lang:active:not(:disabled),
.tv-magic .tvm-share-btn:active:not(:disabled){
  background:var(--tvm-control-active-bg) !important;
}

/* Disabled: same opacity across controls. */
.tv-magic .tvm-control:disabled,
.tv-magic .tvm-lang:disabled,
.tv-magic .tvm-choice:disabled,
.tv-magic .tvm-btn:disabled,
.tv-magic .tvm-back:disabled,
.tv-magic .tvm-focus-toggle:disabled,
.tv-magic .tvm-share-btn:disabled,
.tv-magic [aria-disabled="true"]{
  opacity:var(--tvm-control-disabled-opacity);
  cursor:default;
  transform:none !important;
}

/* Tooltip remains a separate preview layer. */
@media (hover:hover) and (pointer:fine){
  .tv-magic .tvm-share-btn::after{
    transform:translateX(-50%) scale(.94);
    transform-origin:50% 100%;
  }
  .tv-magic .tvm-share-btn:hover::after,
  .tv-magic .tvm-share-btn:focus-visible::after{
    transform:translateX(-50%) scale(1);
  }
}

/* Mobile: keep the two-column information relation as long as practical.
   Collapse only at genuinely narrow widths. */
@media(max-width:23em){
  .tv-magic .tvm-summary-grid,
  .tv-magic .tvm-grid{
    grid-template-columns:1fr;
    gap:.18em;
    width:100%;
  }
  .tv-magic .tvm-summary-grid dt,
  .tv-magic .tvm-grid dt,
  .tv-magic .tvm-summary-grid dd,
  .tv-magic .tvm-grid dd{
    text-align:center;
  }
  .tv-magic .tvm-summary-grid dd,
  .tv-magic .tvm-grid dd{
    margin-bottom:.6em;
  }
}

@media(prefers-reduced-motion:reduce){
  .tv-magic .tvm-control,
  .tv-magic .tvm-lang,
  .tv-magic .tvm-choice,
  .tv-magic .tvm-btn,
  .tv-magic .tvm-back,
  .tv-magic .tvm-focus-toggle,
  .tv-magic .tvm-share-btn,
  .tv-magic .tvm-share-btn::after{
    transition:none !important;
  }
}


/* =========================================================
   v4.4 — viewport-aware composition + compact laws + focus scale
   ========================================================= */

.tv-magic{
  --tvm-focus-frame-width:min(42em,78dvw);
  --tvm-focus-question-size:clamp(2em,2.6vw,2.8em);
  --tvm-focus-choice-size:clamp(1em,1.05vw,1.125em);
  --tvm-focus-choice-height:3.6em;
  --tvm-focus-top-space:clamp(4em,9dvh,7.5em);
  --tvm-focus-question-gap:clamp(1.45em,2.6dvh,2.3em);
  --tvm-focus-choice-gap:clamp(.65em,1.05dvh,.95em);

  --tvm-result-fluid-width:min(44em,88dvw);
  --tvm-prompt-fluid-width:min(38em,86dvw);
  --tvm-law-fluid-width:min(24em,72dvw);
  --tvm-major-section-space:clamp(2.5em,5dvh,5em);
}

/* Large-display text can breathe with the viewport but remains clamped. */
.tv-magic .tvm-hero{
  font-size:clamp(2.125em,3.15vw,3.25em);
}
.tv-magic .tvm-result-name{
  font-size:clamp(1.9em,2.7vw,2.75em);
}

/* Result / prompt / law widths use dvw where screen-relative sizing is useful. */
.tv-magic .tvm-result-screen{
  width:var(--tvm-result-fluid-width);
  max-width:100%;
  margin-left:auto;
  margin-right:auto;
}
.tv-magic .tvm-prompt-group{
  width:var(--tvm-prompt-fluid-width);
  max-width:100%;
}
.tv-magic .tvm-prompt{
  width:100%;
  max-width:100%;
}
.tv-magic .tvm-law-group{
  width:var(--tvm-law-fluid-width);
  max-width:100%;
}

/* Compact central law column — prior two-column structure preserved. */
.tv-magic .tvm-summary-grid,
.tv-magic .tvm-grid{
  width:100%;
  grid-template-columns:max-content minmax(0,1fr);
  column-gap:1em;
  row-gap:.58em;
}
.tv-magic .tvm-summary-grid dt,
.tv-magic .tvm-grid dt{
  white-space:nowrap;
}
.tv-magic .tvm-summary-section .tvm-result-section-title{
  margin-bottom:1.25em;
}
.tv-magic .tvm-summary-section .tvm-detail-title{
  margin-bottom:1.15em;
}
.tv-magic .tvm-spacer--detail-section{
  height:clamp(2em,3.6dvh,3.25em);
}

/* Major result rhythm follows viewport height only where the separation is structural. */
.tv-magic .tvm-carry,
.tv-magic .tvm-share{
  margin-top:var(--tvm-major-section-space);
}

/* ---------------------------------------------------------
   Focus = a dedicated enlarged full-screen composition.
   Progress, focus control, question, choices and Back use
   one shared coordinate frame.
   --------------------------------------------------------- */
.tv-magic.is-focus .tvm-screen{
  width:100%;
  max-width:none;
}

.tv-magic.is-focus .tvm-question-frame{
  width:var(--tvm-focus-frame-width);
  max-width:100%;
  margin-left:auto;
  margin-right:auto;
  padding-top:var(--tvm-focus-top-space);
}

.tv-magic.is-focus .tvm-question-header,
.tv-magic.is-focus .tvm-progress-wrap,
.tv-magic.is-focus .tvm-question-shell,
.tv-magic.is-focus .tvm-backrow{
  width:100%;
  max-width:none;
  margin-left:auto;
  margin-right:auto;
}

.tv-magic.is-focus .tvm-question-header{
  position:relative;
  display:flex;
  align-items:center;
  justify-content:space-between;
}

.tv-magic.is-focus .tvm-progress{
  margin-top:clamp(.8em,1.4dvh,1.25em);
}

.tv-magic.is-focus .tvm-question{
  font-size:var(--tvm-focus-question-size);
  line-height:1.3;
  letter-spacing:-.024em;
  max-width:100%;
}

.tv-magic.is-focus .tvm-question-shell{
  margin-top:clamp(1.55em,2.8dvh,2.5em);
}

.tv-magic.is-focus .tvm-choices{
  margin-top:var(--tvm-focus-question-gap);
  display:grid;
  gap:var(--tvm-focus-choice-gap);
}

.tv-magic.is-focus .tvm-choice{
  width:100%;
  min-height:var(--tvm-focus-choice-height);
  font-size:var(--tvm-focus-choice-size);
  padding:.82em 1.05em;
}

.tv-magic.is-focus .tvm-backrow{
  margin-top:clamp(1.2em,2.2dvh,2em);
}

.tv-magic.is-focus .tvm-back{
  font-size:clamp(1em,.9vw,1.075em);
}

.tv-magic.is-focus .tvm-question-meta,
.tv-magic.is-focus .tvm-progress-meta{
  font-size:clamp(.8125em,.78vw,.9em);
}

.tv-magic.is-focus .tvm-focus-toggle{
  width:3em;
  height:3em;
}
.tv-magic.is-focus .tvm-margin__fullscreenIcon,
.tv-magic.is-focus .tvm-focus-icon,
.tv-magic.is-focus .tvm-focus-toggle svg{
  width:1.7em;
  height:1.7em;
}

/* Short viewports: preserve usable composition without overfilling. */
@media(max-height:42em){
  .tv-magic.is-focus{
    --tvm-focus-top-space:clamp(2.25em,5.5dvh,4em);
    --tvm-focus-question-size:clamp(1.72em,2.35vw,2.25em);
    --tvm-focus-choice-height:3.15em;
    --tvm-focus-question-gap:clamp(1em,1.8dvh,1.45em);
    --tvm-focus-choice-gap:.52em;
  }
}

/* Narrow portrait: viewport-aware width, component internals remain em based. */
@media(max-width:30em){
  .tv-magic{
    --tvm-focus-frame-width:min(34em,calc(100dvw - 2em));
    --tvm-focus-question-size:clamp(1.72em,7.1vw,2.2em);
    --tvm-focus-choice-size:1em;
    --tvm-focus-top-space:clamp(3em,7dvh,5em);
    --tvm-result-fluid-width:min(44em,calc(100dvw - 1.5em));
    --tvm-prompt-fluid-width:min(38em,calc(100dvw - 1.5em));
    --tvm-law-fluid-width:min(24em,calc(100dvw - 2em));
  }
}

/* Existing very-narrow one-column law fallback remains readable. */
@media(max-width:23em){
  .tv-magic .tvm-summary-grid,
  .tv-magic .tvm-grid{
    grid-template-columns:1fr;
  }
}


/* =========================================================
   v4.5 — Experience Mode
   Start / Question / Result share one Focus canvas.
   ========================================================= */

.tv-magic{
  --tvm-experience-bg:#efeee9;
  --tvm-experience-inline:min(72em,92dvw);
  --tvm-experience-top:clamp(3.5em,7dvh,6.5em);
  --tvm-experience-bottom:clamp(4em,8dvh,7em);

  --tvm-start-width:min(42em,76dvw);
  --tvm-start-top:clamp(5em,12dvh,9em);
  --tvm-start-hero-size:clamp(2.35em,3.2vw,3.8em);
  --tvm-start-lead-size:clamp(1em,1.02vw,1.125em);

  --tvm-result-body-size:clamp(1.075em,1.15vw,1.2em);
  --tvm-result-meta-size:clamp(.8125em,.78vw,.9em);
  --tvm-result-ui-size:clamp(1.025em,1vw,1.1em);
  --tvm-result-fluid-width:min(48em,86dvw);
  --tvm-prompt-fluid-width:min(40em,80dvw);
  --tvm-law-fluid-width:min(29em,68dvw);
  --tvm-result-section-space:clamp(2em,2.7dvh,3.4em);
  --tvm-result-small-space:clamp(1.1em,1.6dvh,1.8em);

  --tvm-focus-progress-width:min(16em,28dvw);
}

/* Full-screen Experience canvas */
.tv-magic.is-focus{
  background:var(--tvm-experience-bg);
  min-height:100dvh;
}

.tv-magic.is-focus .tvm-screen{
  max-width:none;
}

.tv-magic.is-focus .tvm-entry,
.tv-magic.is-focus .tvm-question-screen,
.tv-magic.is-focus .tvm-result-screen{
  width:var(--tvm-experience-inline);
  max-width:100%;
  margin-left:auto;
  margin-right:auto;
}

/* Shared Focus toggle across all screens */
.tv-magic.is-focus .tvm-experience-toggle .tvm-focus-toggle,
.tv-magic.is-focus > .tvm-focus-toggle,
.tv-magic.is-focus .tvm-focus-toggle{
  position:fixed;
  top:max(1.25em,env(safe-area-inset-top));
  right:max(1.25em,env(safe-area-inset-right));
  z-index:30;
}

/* ---------------------------------------------------------
   Start — a real full-screen gateway
   --------------------------------------------------------- */
.tv-magic.is-focus .tvm-entry{
  min-height:100dvh;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:flex-start;
  padding-top:var(--tvm-start-top);
  padding-bottom:var(--tvm-experience-bottom);
  text-align:center;
}

.tv-magic.is-focus .tvm-entry > *{
  max-width:var(--tvm-start-width);
}

.tv-magic.is-focus .tvm-entry .tvm-hero{
  font-size:var(--tvm-start-hero-size);
  line-height:1.08;
  letter-spacing:-.034em;
}

.tv-magic.is-focus .tvm-entry .tvm-lead{
  font-size:var(--tvm-start-lead-size);
  line-height:1.8;
  max-width:34em;
}

.tv-magic.is-focus .tvm-entry .tvm-language{
  font-size:clamp(1em,.92vw,1.08em);
}

.tv-magic.is-focus .tvm-entry .tvm-btn{
  min-height:3.25em;
  font-size:clamp(1em,.92vw,1.08em);
}

/* Existing entry spacers should not force the old WP-embedded vertical rhythm. */
.tv-magic.is-focus .tvm-entry .tvm-spacer--entry-top{
  height:0;
}

/* ---------------------------------------------------------
   Question — preserve v4.4 scale, refine vertical balance
   --------------------------------------------------------- */
.tv-magic.is-focus .tvm-question-frame{
  padding-top:clamp(4.75em,10dvh,8.25em);
}

.tv-magic.is-focus .tvm-progress{
  width:var(--tvm-focus-progress-width);
  max-width:44%;
  margin-left:0;
  margin-right:auto;
}

.tv-magic.is-focus .tvm-progress-track{
  width:100%;
}

.tv-magic.is-focus .tvm-question-shell{
  margin-top:clamp(1.7em,3dvh,2.7em);
}

/* ---------------------------------------------------------
   Result — full-screen destination
   --------------------------------------------------------- */
.tv-magic.is-focus .tvm-result-screen{
  width:var(--tvm-result-fluid-width);
  max-width:100%;
  min-height:100dvh;
  padding-top:var(--tvm-experience-top);
  padding-bottom:var(--tvm-experience-bottom);
  margin-left:auto;
  margin-right:auto;
}

.tv-magic.is-focus .tvm-result-name{
  font-size:clamp(2.2em,3vw,3.25em);
  line-height:1.12;
}

/* Same four typography families, scaled contextually rather than adding new styles. */
.tv-magic.is-focus .tvm-result-screen .tvm-lead,
.tv-magic.is-focus .tvm-result-screen .tvm-core,
.tv-magic.is-focus .tvm-result-screen .tvm-summary-grid dd,
.tv-magic.is-focus .tvm-result-screen .tvm-grid dd,
.tv-magic.is-focus .tvm-result-screen .tvm-carry-lead,
.tv-magic.is-focus .tvm-result-screen .tvm-error{
  font-size:var(--tvm-result-body-size);
}

.tv-magic.is-focus .tvm-result-screen .tvm-kicker,
.tv-magic.is-focus .tvm-result-screen .tvm-name,
.tv-magic.is-focus .tvm-result-screen .tvm-helper,
.tv-magic.is-focus .tvm-result-screen .tvm-note,
.tv-magic.is-focus .tvm-result-screen .tvm-detail-title,
.tv-magic.is-focus .tvm-result-screen .tvm-summary-grid dt,
.tv-magic.is-focus .tvm-result-screen .tvm-grid dt,
.tv-magic.is-focus .tvm-result-screen .tvm-state-copy,
.tv-magic.is-focus .tvm-result-screen .tvm-share-btn::after{
  font-size:var(--tvm-result-meta-size);
}

.tv-magic.is-focus .tvm-result-screen .tvm-btn,
.tv-magic.is-focus .tvm-result-screen .tvm-share-btn{
  font-size:var(--tvm-result-ui-size);
}

.tv-magic.is-focus .tvm-core{
  max-width:38em;
  margin-left:auto;
  margin-right:auto;
  line-height:1.82;
}

/* Correct v4.4's small-text / large-gap imbalance. */
.tv-magic.is-focus .tvm-result-screen .tvm-result-section,
.tv-magic.is-focus .tvm-result-screen .tvm-carry,
.tv-magic.is-focus .tvm-result-screen .tvm-prompt-group,
.tv-magic.is-focus .tvm-result-screen .tvm-share,
.tv-magic.is-focus .tvm-result-screen .tvm-result-restart{
  margin-top:var(--tvm-result-section-space);
}

.tv-magic.is-focus .tvm-result-screen .tvm-spacer--detail-section{
  height:var(--tvm-result-small-space);
}

/* Law column: still compact, but no longer over-compressed. */
.tv-magic.is-focus .tvm-law-group{
  width:var(--tvm-law-fluid-width);
  max-width:100%;
}

.tv-magic.is-focus .tvm-summary-grid,
.tv-magic.is-focus .tvm-grid{
  width:100%;
  grid-template-columns:max-content minmax(0,1fr);
  column-gap:1.15em;
  row-gap:.62em;
}

.tv-magic.is-focus .tvm-summary-grid dd,
.tv-magic.is-focus .tvm-grid dd{
  line-height:1.7;
}

.tv-magic.is-focus .tvm-grid--secondary dd:last-child{
  max-width:none;
}

/* Prompt expands with Result, but text itself remains left aligned. */
.tv-magic.is-focus .tvm-prompt-group{
  width:var(--tvm-prompt-fluid-width);
  max-width:100%;
}

.tv-magic.is-focus .tvm-prompt{
  min-height:10em;
  max-height:24em;
}

/* ---------------------------------------------------------
   Responsive tuning
   --------------------------------------------------------- */
@media(max-width:48em){
  .tv-magic{
    --tvm-experience-inline:min(44em,calc(100dvw - 2em));
    --tvm-start-width:min(36em,calc(100dvw - 2em));
    --tvm-result-fluid-width:min(44em,calc(100dvw - 2em));
    --tvm-prompt-fluid-width:min(38em,calc(100dvw - 2em));
    --tvm-law-fluid-width:min(29em,calc(100dvw - 2em));
  }
}

@media(max-width:30em){
  .tv-magic{
    --tvm-start-top:clamp(3.5em,8dvh,5.5em);
    --tvm-start-hero-size:clamp(2em,8.4vw,2.65em);
    --tvm-start-lead-size:1em;

    --tvm-result-body-size:1em;
    --tvm-result-meta-size:.8125em;
    --tvm-result-ui-size:1em;

    --tvm-law-fluid-width:min(26em,calc(100dvw - 2em));
    --tvm-result-section-space:clamp(1.8em,2.4dvh,2.7em);
  }

  .tv-magic.is-focus .tvm-result-name{
    font-size:clamp(2em,8.4vw,2.7em);
  }
}

@media(max-height:42em){
  .tv-magic{
    --tvm-start-top:clamp(2.5em,6dvh,4em);
    --tvm-experience-top:clamp(2.5em,5dvh,4em);
    --tvm-experience-bottom:clamp(2.5em,5dvh,4em);
  }

  .tv-magic.is-focus .tvm-question-frame{
    padding-top:clamp(2.5em,5.5dvh,4.2em);
  }
}


/* =========================================================
   v4.6 — result axis / keyboard-ready controls / button sizing
   ========================================================= */

.tv-magic{
  --tvm-result-axis-width:min(40em,78dvw);

  --tvm-language-button-height:3.25em;
  --tvm-primary-button-height:3.5em;
  --tvm-share-button-size:3.25em;
}

/* ---------------------------------------------------------
   Back: text only in both Normal and Focus.
   --------------------------------------------------------- */
.tv-magic .tvm-back::before,
.tv-magic.is-focus .tvm-question-frame .tvm-back::before{
  content:none !important;
  display:none !important;
}

/* ---------------------------------------------------------
   Question vertical density
   Short content sits slightly lower; long/dense questions stay higher.
   --------------------------------------------------------- */
.tv-magic.is-focus .tvm-question-frame.is-density-relaxed{
  padding-top:clamp(5.75em,12dvh,9.5em);
}

.tv-magic.is-focus .tvm-question-frame.is-density-regular{
  padding-top:clamp(4.75em,9dvh,7.5em);
}

.tv-magic.is-focus .tvm-question-frame.is-density-dense{
  padding-top:clamp(3em,5.8dvh,5em);
}

@media(max-height:42em){
  .tv-magic.is-focus .tvm-question-frame.is-density-relaxed,
  .tv-magic.is-focus .tvm-question-frame.is-density-regular{
    padding-top:clamp(2.4em,5dvh,3.8em);
  }

  .tv-magic.is-focus .tvm-question-frame.is-density-dense{
    padding-top:clamp(1.75em,3.6dvh,2.8em);
  }
}

/* ---------------------------------------------------------
   Result: one central axis for Laws → AI carry → Share → Restart.
   --------------------------------------------------------- */
.tv-magic .tvm-result-axis{
  width:var(--tvm-result-axis-width);
  max-width:100%;
  margin-left:auto;
  margin-right:auto;
  text-align:center;
}

.tv-magic .tvm-result-axis > .tvm-result-section,
.tv-magic .tvm-result-axis > .tvm-result-restart{
  width:100%;
  margin-left:auto;
  margin-right:auto;
}

.tv-magic .tvm-result-axis .tvm-result-section-title,
.tv-magic .tvm-result-axis .tvm-detail-title,
.tv-magic .tvm-result-axis .tvm-share-title,
.tv-magic .tvm-result-axis .tvm-result-restart{
  text-align:center;
}

/* Law block: strict shared 2-column definition axis. */
.tv-magic .tvm-law-group{
  width:min(30em,100%);
  margin-left:auto;
  margin-right:auto;
}

.tv-magic .tvm-summary-grid,
.tv-magic .tvm-grid{
  width:100%;
  display:grid;
  grid-template-columns:max-content minmax(0,1fr);
  column-gap:1.15em;
  row-gap:.56em;
  margin-left:auto;
  margin-right:auto;
}

.tv-magic .tvm-summary-grid dt,
.tv-magic .tvm-grid dt{
  text-align:right;
  white-space:nowrap;
}

.tv-magic .tvm-summary-grid dd,
.tv-magic .tvm-grid dd{
  text-align:left;
  min-width:0;
  overflow-wrap:anywhere;
}

.tv-magic .tvm-grid--secondary dd:last-child{
  max-width:none;
}

/* Prompt can be wider inside the common result axis without shifting headings. */
.tv-magic .tvm-prompt-group{
  width:min(38em,100%);
  margin-left:auto;
  margin-right:auto;
}

/* ---------------------------------------------------------
   Button sizing: em-based, role-based.
   --------------------------------------------------------- */
.tv-magic .tvm-lang{
  min-height:var(--tvm-language-button-height);
  padding-inline:1.15em;
}

.tv-magic #tvmStart,
.tv-magic #tvmCopy{
  min-height:var(--tvm-primary-button-height);
  padding-inline:1.4em;
}

.tv-magic .tvm-share-btn{
  width:var(--tvm-share-button-size);
  height:var(--tvm-share-button-size);
  min-width:var(--tvm-share-button-size);
  min-height:var(--tvm-share-button-size);
  padding:0;
}

/* Keep the language group proportional to its children. */
.tv-magic .tvm-language{
  min-height:var(--tvm-language-button-height);
}

/* Mobile keeps the same em relationships. */
@media(max-width:30em){
  .tv-magic{
    --tvm-result-axis-width:min(38em,calc(100dvw - 1.5em));
  }

  .tv-magic .tvm-law-group{
    width:min(28em,100%);
  }
}

@media(max-width:23em){
  .tv-magic .tvm-summary-grid,
  .tv-magic .tvm-grid{
    grid-template-columns:1fr;
    row-gap:.18em;
  }

  .tv-magic .tvm-summary-grid dt,
  .tv-magic .tvm-grid dt,
  .tv-magic .tvm-summary-grid dd,
  .tv-magic .tvm-grid dd{
    text-align:center;
  }
}


/* =========================================================
   v4.7 — central-axis correction + unified Focus utility
   ========================================================= */

.tv-magic{
  --tvm-result-axis-width:min(42em,80dvw);
  --tvm-law-axis-width:min(34em,72dvw);

  /* Shared top-right utility geometry */
  --tvm-focus-control-size:2.75em;
  --tvm-focus-glyph-size:1.5em;
  --tvm-focus-edge-x:max(1.25em,env(safe-area-inset-right));
  --tvm-focus-edge-y:max(1.25em,env(safe-area-inset-top));
}

/* ---------------------------------------------------------
   Result: exact common center axis
   --------------------------------------------------------- */
.tv-magic .tvm-result-axis{
  width:var(--tvm-result-axis-width);
  max-width:100%;
  margin-inline:auto;
  text-align:center;
}

.tv-magic .tvm-result-axis > *{
  margin-left:auto;
  margin-right:auto;
}

.tv-magic .tvm-result-axis .tvm-summary-section,
.tv-magic .tvm-result-axis .tvm-carry,
.tv-magic .tvm-result-axis .tvm-share,
.tv-magic .tvm-result-axis .tvm-result-restart{
  width:100%;
  max-width:100%;
}

/* Headings share the exact geometric center. */
.tv-magic .tvm-result-axis .tvm-result-section-title,
.tv-magic .tvm-result-axis .tvm-detail-title,
.tv-magic .tvm-result-axis .tvm-carry-title,
.tv-magic .tvm-result-axis .tvm-prompt-heading,
.tv-magic .tvm-result-axis .tvm-share-title,
.tv-magic .tvm-result-axis .tvm-result-restart,
.tv-magic .tvm-result-axis .tvm-actions{
  width:100%;
  text-align:center;
  margin-left:auto;
  margin-right:auto;
}

/* Laws: two equal columns = center seam is always the page axis. */
.tv-magic .tvm-law-group{
  width:var(--tvm-law-axis-width);
  max-width:100%;
  margin-inline:auto;
}

.tv-magic .tvm-summary-grid,
.tv-magic .tvm-grid{
  width:100%;
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  column-gap:1.15em;
  row-gap:.58em;
  margin-inline:auto;
}

.tv-magic .tvm-summary-grid dt,
.tv-magic .tvm-grid dt{
  justify-self:stretch;
  text-align:right;
  white-space:normal;
}

.tv-magic .tvm-summary-grid dd,
.tv-magic .tvm-grid dd{
  justify-self:stretch;
  text-align:left;
  min-width:0;
  overflow-wrap:anywhere;
}

/* Prompt unit and box are centered on the same axis. */
.tv-magic .tvm-prompt-group{
  width:min(40em,100%);
  max-width:100%;
  margin-inline:auto;
  text-align:center;
}

.tv-magic .tvm-prompt{
  display:block;
  width:100%;
  margin-inline:auto;
  text-align:left;
}

/* Share row and restart remain centered within the same axis. */
.tv-magic .tvm-share-row,
.tv-magic #tvmShareRow{
  justify-content:center;
  margin-inline:auto;
}

.tv-magic .tvm-result-restart .tvm-actions{
  display:flex;
  justify-content:center;
}

/* ---------------------------------------------------------
   Focus utility: same glyph size, hit area and fixed position
   on Start / Question / Result.
   --------------------------------------------------------- */
.tv-magic .tvm-focus-toggle,
.tv-magic.is-focus .tvm-focus-toggle,
.tv-magic.is-focus .tvm-experience-toggle .tvm-focus-toggle,
.tv-magic.is-focus > .tvm-focus-toggle{
  position:fixed !important;
  top:var(--tvm-focus-edge-y) !important;
  right:var(--tvm-focus-edge-x) !important;
  left:auto !important;
  bottom:auto !important;
  width:var(--tvm-focus-control-size) !important;
  min-width:var(--tvm-focus-control-size) !important;
  height:var(--tvm-focus-control-size) !important;
  min-height:var(--tvm-focus-control-size) !important;
  padding:0 !important;
  z-index:30;
  display:inline-flex;
  align-items:center;
  justify-content:center;
}

.tv-magic .tvm-focus-toggle svg,
.tv-magic .tvm-focus-icon-enter,
.tv-magic .tvm-focus-icon-exit,
.tv-magic .tvm-margin__fullscreenIcon{
  width:var(--tvm-focus-glyph-size) !important;
  height:var(--tvm-focus-glyph-size) !important;
  flex:0 0 var(--tvm-focus-glyph-size);
}

/* Prevent question-header layout from reserving space for the fixed icon. */
.tv-magic.is-focus .tvm-question-header .tvm-focus-toggle{
  margin:0 !important;
}

/* ---------------------------------------------------------
   TMS resilience refinements carried into this component.
   --------------------------------------------------------- */
@supports not (backdrop-filter:blur(1px)){
  .tv-magic .tvm-btn,
  .tv-magic .tvm-choice,
  .tv-magic .tvm-lang,
  .tv-magic .tvm-share-btn,
  .tv-magic .tvm-prompt{
    -webkit-backdrop-filter:none !important;
    backdrop-filter:none !important;
  }
}

@media(forced-colors:active){
  .tv-magic .tvm-btn,
  .tv-magic .tvm-choice,
  .tv-magic .tvm-lang,
  .tv-magic .tvm-share-btn,
  .tv-magic .tvm-focus-toggle{
    background:Canvas !important;
    color:CanvasText !important;
    border:1px solid CanvasText !important;
    box-shadow:none !important;
  }

  .tv-magic .tvm-focus-toggle svg{
    stroke:CanvasText !important;
  }
}

@media(prefers-reduced-motion:reduce){
  .tv-magic *,
  .tv-magic *::before,
  .tv-magic *::after{
    scroll-behavior:auto !important;
  }
}

/* Narrow screens retain the same centered two-column seam until
   the existing very-narrow one-column fallback takes over. */
@media(max-width:30em){
  .tv-magic{
    --tvm-result-axis-width:min(40em,calc(100dvw - 1.5em));
    --tvm-law-axis-width:min(32em,calc(100dvw - 1.75em));
    --tvm-focus-edge-x:max(1em,env(safe-area-inset-right));
    --tvm-focus-edge-y:max(1em,env(safe-area-inset-top));
  }
}

@media(max-width:23em){
  .tv-magic .tvm-summary-grid,
  .tv-magic .tvm-grid{
    grid-template-columns:1fr;
  }

  .tv-magic .tvm-summary-grid dt,
  .tv-magic .tvm-grid dt,
  .tv-magic .tvm-summary-grid dd,
  .tv-magic .tvm-grid dd{
    text-align:center;
  }
}


/* v4.7.1 specificity correction: Experience Mode must use the same
   geometric center-axis rules as Normal mode. */
.tv-magic.is-focus .tvm-law-group{
  width:var(--tvm-law-axis-width);
  max-width:100%;
  margin-inline:auto;
}

.tv-magic.is-focus .tvm-summary-grid,
.tv-magic.is-focus .tvm-grid{
  width:100%;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  column-gap:1.15em;
  row-gap:.58em;
  margin-inline:auto;
}

.tv-magic.is-focus .tvm-prompt-group{
  width:min(40em,100%);
  max-width:100%;
  margin-inline:auto;
}


/* =========================================================
   v4.8 — PPE/TMS + Indextro integration
   Applicable source patterns only; Magic-specific UX preserved.
   ========================================================= */

.tv-magic{
  /* Semantic text / line system */
  --tvm-text-primary:var(--tvm-ink);
  --tvm-text-secondary:var(--tvm-muted);
  --tvm-text-tertiary:rgba(32,38,36,.52);
  --tvm-text-disabled:rgba(32,38,36,.38);

  --tvm-line-subtle:rgba(32,38,36,.08);
  --tvm-line-default:rgba(32,38,36,.14);
  --tvm-line-strong:rgba(32,38,36,.24);

  /* Semantic spacing aliases */
  --tvm-space-0:0;
  --tvm-space-1:.125em;
  --tvm-space-2:.25em;
  --tvm-space-3:.5em;
  --tvm-space-4:.75em;
  --tvm-space-5:1em;
  --tvm-space-6:1.5em;
  --tvm-space-7:2em;
  --tvm-space-8:3em;
  --tvm-space-9:4em;

  /* Interaction tokens */
  --tvm-target-min:2.75em;
  --tvm-target-comfort:3em;
  --tvm-opacity-hover:.92;
  --tvm-opacity-pressed:.82;
  --tvm-opacity-disabled:.42;

  /* Layer aliases */
  --tvm-layer-content:0;
  --tvm-layer-sticky:20;
  --tvm-layer-floating:40;
  --tvm-layer-popover:60;
  --tvm-layer-modal:80;
  --tvm-layer-toast:100;

  /* Safe-area aliases */
  --tvm-safe-top:env(safe-area-inset-top,0px);
  --tvm-safe-right:env(safe-area-inset-right,0px);
  --tvm-safe-bottom:env(safe-area-inset-bottom,0px);
  --tvm-safe-left:env(safe-area-inset-left,0px);

  /* Content-width aliases */
  --tvm-content-narrow:40em;
  --tvm-content-reading:45em;
  --tvm-content-standard:60em;
  --tvm-content-wide:80em;

  color-scheme:light;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}

/* Explicit theme support. Default remains light; auto/dark are opt-in via
   TranquilMagicTheme.set("auto"|"dark"|"light"). */
.tv-magic[data-tvm-theme="dark"]{
  color-scheme:dark;
  --tvm-ink:#f8f8f7;
  --tvm-muted:#c6c6c2;
  --tvm-text-primary:#f8f8f7;
  --tvm-text-secondary:#c6c6c2;
  --tvm-text-tertiary:#a5a5a0;
  --tvm-text-disabled:#5d5d59;
  --tvm-line-subtle:rgba(248,248,247,.08);
  --tvm-line-default:rgba(248,248,247,.14);
  --tvm-line-strong:rgba(248,248,247,.24);
  --tvm-focus-bg:#0d0d0c;
  --tvm-experience-bg:#0d0d0c;
  --tvm-clear:#171716;
  --tvm-mist:rgba(23,23,22,.84);
  --tvm-veil:rgba(23,23,22,.72);
  --tvm-lens:rgba(23,23,22,.64);
  --tvm-mist-solid:#1b1b19;
  --tvm-veil-solid:#242421;
  --tvm-lens-solid:#30302c;
  --tvm-hover-soft:rgba(248,248,247,.055);
  --tvm-hover-medium:rgba(248,248,247,.075);
  --tvm-hover-line:rgba(248,248,247,.18);
  --tvm-focus-soft:rgba(248,248,247,.10);
  --tvm-selected-line:rgba(248,248,247,.22);
}

/* Content stays clear; glass remains interface/transient only. */
.tv-magic [data-surface="content"]{
  -webkit-backdrop-filter:none;
  backdrop-filter:none;
}

/* Indextro-style stationary hover: state changes, controls do not lift. */
@media(hover:hover) and (pointer:fine){
  .tv-magic .tvm-control:hover:not(:disabled):not([aria-disabled="true"]){
    transform:none !important;
  }
}

/* Disabled is a semantic interaction state, not just a visual hint. */
.tv-magic .tvm-control:disabled,
.tv-magic .tvm-control[aria-disabled="true"],
.tv-magic .tvm-lang:disabled,
.tv-magic .tvm-choice:disabled{
  opacity:var(--tvm-opacity-disabled) !important;
  cursor:default !important;
  pointer-events:none !important;
  transform:none !important;
}

/* Global focus-visible contract for every executable/input surface. */
.tv-magic button:focus-visible,
.tv-magic textarea:focus-visible,
.tv-magic input:focus-visible,
.tv-magic select:focus-visible,
.tv-magic a:focus-visible,
.tv-magic [tabindex]:focus-visible{
  outline:2px solid var(--tvm-focus-ring);
  outline-offset:3px;
}

/* Language is a true segmented radiogroup. */
.tv-magic .tvm-language[role="radiogroup"]{
  display:inline-flex;
  align-items:stretch;
}
.tv-magic .tvm-lang[role="radio"][aria-checked="true"]{
  color:var(--tvm-text-primary);
}

/* ---------------------------------------------------------
   Keyboard shortcut sheet — hidden until requested with ?
   --------------------------------------------------------- */
.tv-magic .tvm-shortcut-sheet{
  position:fixed;
  inset:0;
  z-index:var(--tvm-layer-modal);
  display:grid;
  place-items:center;
  padding:
    max(1em,var(--tvm-safe-top))
    max(1em,var(--tvm-safe-right))
    max(1em,var(--tvm-safe-bottom))
    max(1em,var(--tvm-safe-left));
  background:rgba(0,0,0,.12);
}

.tv-magic .tvm-shortcut-panel{
  width:min(27em,calc(100dvw - 2em));
  max-height:min(36em,calc(100dvh - 2em));
  overflow:auto;
  padding:1.25em;
  border:1px solid var(--tvm-line-subtle);
  border-radius:1.25em;
  background:var(--tvm-surface-veil-solid);
  color:var(--tvm-text-primary);
  box-shadow:var(--tvm-elevation-toast);
}

@supports ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){
  .tv-magic .tvm-shortcut-panel{
    background:var(--tvm-surface-veil);
    -webkit-backdrop-filter:blur(1.125em) saturate(1.06);
    backdrop-filter:blur(1.125em) saturate(1.06);
  }
}

.tv-magic .tvm-shortcut-head{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:1em;
  margin-bottom:1em;
}

.tv-magic .tvm-shortcut-title{
  margin:0;
  font-size:1em;
  font-weight:600;
}

.tv-magic .tvm-shortcut-close{
  width:2.75em;
  height:2.75em;
  min-width:2.75em;
  min-height:2.75em;
  padding:0;
  display:inline-grid;
  place-items:center;
  border:1px solid var(--tvm-line-subtle);
  border-radius:999em;
  background:transparent;
  color:inherit;
  font:inherit;
}

.tv-magic .tvm-shortcut-list{
  display:grid;
  gap:.25em;
}

.tv-magic .tvm-shortcut-list > div{
  display:grid;
  grid-template-columns:5.75em minmax(0,1fr);
  gap:1em;
  align-items:baseline;
  padding:.625em 0;
  border-bottom:1px solid var(--tvm-line-subtle);
}

.tv-magic .tvm-shortcut-list kbd{
  font-family:var(--tvm-font-mono);
  font-size:.8125em;
  color:var(--tvm-text-secondary);
}

.tv-magic .tvm-shortcut-list span{
  font-size:.875em;
  line-height:1.55;
}

.tv-magic .tvm-shortcut-hint{
  margin:1em 0 0;
  font-size:.8125em;
  line-height:1.55;
  color:var(--tvm-text-secondary);
}

/* ---------------------------------------------------------
   Runtime recovery layer
   --------------------------------------------------------- */
.tv-magic .tvm-recovery{
  position:fixed;
  left:50%;
  bottom:max(1.25em,var(--tvm-safe-bottom));
  transform:translateX(-50%);
  z-index:var(--tvm-layer-toast);
  width:min(32.5em,calc(100dvw - 2em));
  padding:1em;
  border:1px solid var(--tvm-line-default);
  border-radius:1em;
  background:var(--tvm-surface-veil-solid);
  color:var(--tvm-text-primary);
  box-shadow:var(--tvm-elevation-toast);
}

.tv-magic .tvm-recovery[hidden]{
  display:none;
}

@supports ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){
  .tv-magic .tvm-recovery{
    background:var(--tvm-surface-veil);
    -webkit-backdrop-filter:blur(1.125em) saturate(1.06);
    backdrop-filter:blur(1.125em) saturate(1.06);
  }
}

.tv-magic .tvm-recovery-message{
  margin:0;
  font-size:.875em;
  line-height:1.55;
}

.tv-magic .tvm-recovery-actions{
  display:flex;
  flex-wrap:wrap;
  gap:.5em;
  margin-top:.75em;
}

.tv-magic .tvm-recovery-actions .tvm-btn{
  min-height:2.75em;
}

/* Glass fallbacks for the new transient surfaces. */
@supports not (backdrop-filter:blur(1px)){
  .tv-magic .tvm-shortcut-panel,
  .tv-magic .tvm-recovery{
    -webkit-backdrop-filter:none !important;
    backdrop-filter:none !important;
    background:var(--tvm-surface-veil-solid) !important;
  }
}

@media(prefers-reduced-motion:reduce){
  .tv-magic .tvm-shortcut-sheet,
  .tv-magic .tvm-shortcut-panel,
  .tv-magic .tvm-recovery{
    animation:none !important;
    transition:none !important;
  }
}

@media(forced-colors:active){
  .tv-magic .tvm-shortcut-sheet{
    background:Canvas;
  }

  .tv-magic .tvm-shortcut-panel,
  .tv-magic .tvm-recovery{
    background:Canvas !important;
    color:CanvasText !important;
    border:1px solid CanvasText !important;
    box-shadow:none !important;
    -webkit-backdrop-filter:none !important;
    backdrop-filter:none !important;
  }

  .tv-magic .tvm-shortcut-list > div{
    border-color:CanvasText;
  }
}


/* =========================================================
   v4.9 — remaining PPE/TMS + Indextro integration
   ========================================================= */

/* Language is scoped to the component; WordPress document language is untouched. */
.tv-magic[lang="ja"]{
  font-language-override:normal;
}
.tv-magic[lang="en"]{
  font-language-override:normal;
}

/* Stable layout when internal scrolling appears. */
.tv-magic.is-focus,
.tv-magic .tvm-result-screen,
.tv-magic .tvm-prompt,
.tv-magic .tvm-shortcut-panel{
  scrollbar-gutter:stable;
}

.tv-magic.is-focus,
.tv-magic .tvm-shortcut-panel{
  overscroll-behavior:contain;
}

/* Prompt unit communicates focus at the unit level. */
.tv-magic .tvm-prompt-group{
  border-radius:1em;
  transition:
    background-color var(--tvm-motion-fast) var(--tvm-ease-standard),
    box-shadow var(--tvm-motion-fast) var(--tvm-ease-standard);
}

.tv-magic .tvm-prompt-group:focus-within{
  background:var(--tvm-focus-soft);
  box-shadow:0 0 0 1px var(--tvm-hover-line);
}

/* Progressive semantic color derivation. Existing RGBA values remain fallback. */
@supports(color:color-mix(in srgb,currentColor 10%,transparent)){
  .tv-magic{
    --tvm-hover-soft:color-mix(in srgb,var(--tvm-ink) 5.5%,transparent);
    --tvm-hover-medium:color-mix(in srgb,var(--tvm-ink) 7.5%,transparent);
    --tvm-focus-soft:color-mix(in srgb,var(--tvm-ink) 10%,transparent);
    --tvm-hover-line:color-mix(in srgb,var(--tvm-ink) 18%,transparent);
    --tvm-selected-line:color-mix(in srgb,var(--tvm-ink) 22%,transparent);
  }
}

/* Busy is a first-class state. */
.tv-magic .tvm-control[data-busy="true"]{
  cursor:progress !important;
  opacity:.72;
  pointer-events:none !important;
}

/* Toast may include one contextual action. */
.tv-magic .tvm-toast{
  display:flex;
  align-items:center;
  gap:.75em;
}

.tv-magic .tvm-toast-message{
  min-width:0;
}

.tv-magic .tvm-toast-action{
  flex:0 0 auto;
  min-height:2.5em;
  padding-inline:.85em;
  border:1px solid var(--tvm-line-default);
  border-radius:999em;
  background:transparent;
  color:inherit;
  font:inherit;
  font-size:.8125em;
}

/* Recovery retry is shown only when a local retry callback exists. */
.tv-magic #tvmRecoveryRetry[hidden]{
  display:none;
}

/* Managed overlays use one explicit open state. */
.tv-magic [data-overlay-open="true"]{
  visibility:visible;
}

/* Prevent page-scroll chaining while a modal sheet is open. */
.tv-magic .tvm-shortcut-sheet[data-overlay-open="true"]{
  overscroll-behavior:contain;
}

/* Dark theme prompt focus remains restrained. */
.tv-magic[data-tvm-theme="dark"] .tvm-prompt-group:focus-within{
  background:var(--tvm-focus-soft);
}


/* =========================================================
   v5.0 — action affordance / unified action sizing / share color inversion
   ========================================================= */
.tv-magic{
  --tvm-action-size:3.25em;
  --tvm-start-size:5em;
  --tvm-secondary-rest-bg:rgba(255,255,255,.34);
  --tvm-secondary-rest-border:rgba(32,38,36,.16);
  --tvm-secondary-hover-bg:rgba(255,255,255,.62);
  --tvm-secondary-hover-border:rgba(32,38,36,.28);
}

/* Language / Prompt Copy / Share / Secondary Action share one action size. */
.tv-magic .tvm-lang,
.tv-magic #tvmCopy,
.tv-magic .tvm-back,
.tv-magic .tvm-result-restart .tvm-btn{
  min-height:var(--tvm-action-size) !important;
}
.tv-magic .tvm-language{
  min-height:var(--tvm-action-size) !important;
}
.tv-magic .tvm-share-btn{
  width:var(--tvm-action-size) !important;
  height:var(--tvm-action-size) !important;
  min-width:var(--tvm-action-size) !important;
  min-height:var(--tvm-action-size) !important;
}

/* Start is the single dominant CTA. */
.tv-magic #tvmStart{
  min-height:var(--tvm-start-size) !important;
  padding-inline:2.25em !important;
  font-size:clamp(1.0625em,1.1vw,1.1875em) !important;
  font-weight:var(--tvm-weight-semibold) !important;
}
.tv-magic .tvm-entry .tvm-actions{
  justify-content:center;
  margin-top:clamp(2em,3.5dvh,3.25em);
}

/* Back / Restart are visibly actionable even before hover. */
.tv-magic .tvm-back,
.tv-magic .tvm-result-restart .tvm-btn,
.tv-magic .tvm-result-restart .tvm-btn.is-ghost{
  padding-inline:1.2em !important;
  border:0.0625em solid var(--tvm-secondary-rest-border) !important;
  border-radius:999em !important;
  background:var(--tvm-secondary-rest-bg) !important;
  color:var(--tvm-ink) !important;
  box-shadow:inset 0 0.0625em 0 rgba(255,255,255,.38) !important;
  -webkit-backdrop-filter:none !important;
  backdrop-filter:none !important;
}

@media (hover:hover) and (pointer:fine){
  .tv-magic .tvm-back:hover:not(:disabled),
  .tv-magic .tvm-result-restart .tvm-btn:hover:not(:disabled){
    transform:none !important;
    background:var(--tvm-secondary-hover-bg) !important;
    border-color:var(--tvm-secondary-hover-border) !important;
    color:var(--tvm-ink) !important;
    box-shadow:inset 0 0.0625em 0 rgba(255,255,255,.5) !important;
  }
}

.tv-magic .tvm-back:focus-visible,
.tv-magic .tvm-result-restart .tvm-btn:focus-visible{
  background:var(--tvm-control-focus-bg) !important;
  border-color:var(--tvm-control-focus-border) !important;
  outline:var(--tvm-focus-ring) !important;
  outline-offset:var(--tvm-focus-offset) !important;
}

/* TranquilShare v1.0-derived rest colors. */
.tv-magic [data-share-action="x"]{color:#000 !important;}
.tv-magic [data-share-action="threads"]{color:#383D38 !important;}
.tv-magic [data-share-action="bluesky"]{color:#1185FE !important;}
.tv-magic [data-share-action="line"]{color:#06C755 !important;}
.tv-magic [data-share-action="native"],
.tv-magic [data-share-action="story"],
.tv-magic [data-share-action="copy"]{color:#404040 !important;}

/* Stationary color inversion: surface becomes service color, glyph becomes white. */
@media (hover:hover) and (pointer:fine){
  .tv-magic [data-share-action="x"]:hover:not(:disabled){
    background:#000 !important;
    border-color:#000 !important;
    color:#fff !important;
  }
  .tv-magic [data-share-action="threads"]:hover:not(:disabled){
    background:#383D38 !important;
    border-color:#383D38 !important;
    color:#fff !important;
  }
  .tv-magic [data-share-action="bluesky"]:hover:not(:disabled){
    background:#1185FE !important;
    border-color:#1185FE !important;
    color:#fff !important;
  }
  .tv-magic [data-share-action="line"]:hover:not(:disabled){
    background:#06C755 !important;
    border-color:#06C755 !important;
    color:#fff !important;
  }
  .tv-magic [data-share-action="native"]:hover:not(:disabled),
  .tv-magic [data-share-action="story"]:hover:not(:disabled),
  .tv-magic [data-share-action="copy"]:hover:not(:disabled){
    background:#404040 !important;
    border-color:#404040 !important;
    color:#fff !important;
  }
  .tv-magic [data-share-action="threads"]:hover .tvm-share-icon--brand path,
  .tv-magic [data-share-action="bluesky"]:hover .tvm-share-icon--brand path{
    fill:#fff !important;
  }
  .tv-magic [data-share-action="native"]:hover .tvm-share-icon path,
  .tv-magic [data-share-action="story"]:hover .tvm-share-icon rect,
  .tv-magic [data-share-action="story"]:hover .tvm-share-icon path,
  .tv-magic [data-share-action="copy"]:hover .tvm-copy-icon rect,
  .tv-magic [data-share-action="copy"]:hover .tvm-copy-icon path{
    stroke:#fff !important;
  }
  .tv-magic [data-share-action="story"]:hover .tvm-share-icon rect,
  .tv-magic [data-share-action="story"]:hover .tvm-share-icon path{
    fill:none !important;
  }
  .tv-magic [data-share-action="story"]:hover .tvm-share-icon circle{
    fill:#fff !important;
  }
  .tv-magic .tvm-share-btn:hover:not(:disabled){
    transform:none !important;
    box-shadow:none !important;
  }
}

/* Press remains the only positional feedback. */
.tv-magic .tvm-back:active:not(:disabled),
.tv-magic .tvm-result-restart .tvm-btn:active:not(:disabled),
.tv-magic .tvm-share-btn:active:not(:disabled){
  transform:scale(.975) !important;
}

@media (forced-colors:active){
  .tv-magic .tvm-back,
  .tv-magic .tvm-result-restart .tvm-btn{
    background:ButtonFace !important;
    color:ButtonText !important;
    border-color:ButtonText !important;
  }
}



/* =========================================================
   v5.1 — scale hierarchy / language-derived controls / ontology prose
   ========================================================= */
.tv-magic{
  --tvm-action-size:3.25em;
  --tvm-share-size:3.75em;
  --tvm-share-glyph-size:1.30em;
  --tvm-start-size:6em;
  --tvm-focus-exit-size:5em;
  --tvm-focus-exit-glyph-size:2.55em;
}

/* Language is the visual/interaction reference for text actions. */
.tv-magic #tvmCopy,
.tv-magic .tvm-back,
.tv-magic .tvm-result-restart .tvm-btn,
.tv-magic .tvm-result-restart .tvm-btn.is-ghost{
  min-height:var(--tvm-action-size) !important;
  padding-inline:1.15em !important;
  border-radius:var(--tvm-radius-pill) !important;
  font:inherit !important;
  line-height:1.2 !important;
  transition:
    background var(--tvm-motion-fast) var(--tvm-ease),
    color var(--tvm-motion-fast) var(--tvm-ease),
    border-color var(--tvm-motion-fast) var(--tvm-ease),
    transform var(--tvm-motion-fast) var(--tvm-ease),
    box-shadow var(--tvm-motion-fast) var(--tvm-ease) !important;
}

/* Start keeps the language-control design language but becomes the unmistakable CTA. */
.tv-magic #tvmStart{
  min-height:var(--tvm-start-size) !important;
  width:min(30em,calc(100dvw - 3em));
  max-width:100%;
  padding-inline:clamp(2.5em,7dvw,5em) !important;
  border-radius:999em !important;
  font-size:clamp(1.20em,1.55vw,1.50em) !important;
  line-height:1.2 !important;
  letter-spacing:-.015em;
}
.tv-magic .tvm-entry .tvm-actions{
  width:100%;
  justify-content:center;
  margin-top:clamp(2.25em,4.5dvh,4em);
}

/* Share controls: true circles, larger glyphs, same control physics. */
.tv-magic .tvm-share-btn{
  width:var(--tvm-share-size) !important;
  height:var(--tvm-share-size) !important;
  min-width:var(--tvm-share-size) !important;
  min-height:var(--tvm-share-size) !important;
  flex:0 0 var(--tvm-share-size) !important;
  aspect-ratio:1 / 1;
  border-radius:50% !important;
  padding:0 !important;
}
.tv-magic .tvm-share-icon,
.tv-magic .tvm-copy-icon,
.tv-magic .tvm-share-font-icon{
  width:var(--tvm-share-glyph-size) !important;
  height:var(--tvm-share-glyph-size) !important;
}
.tv-magic .tvm-share-font-icon{
  font-size:var(--tvm-share-glyph-size) !important;
}
.tv-magic .tvm-share-row{
  gap:.85em;
}
.tv-magic .tvm-share-group{
  gap:.52em;
}

/* Only the Focus-exit control grows: entering Focus remains unobtrusive. */
.tv-magic.is-focus .tvm-focus-toggle,
.tv-magic.is-focus .tvm-experience-toggle .tvm-focus-toggle,
.tv-magic.is-focus > .tvm-focus-toggle{
  width:var(--tvm-focus-exit-size) !important;
  min-width:var(--tvm-focus-exit-size) !important;
  height:var(--tvm-focus-exit-size) !important;
  min-height:var(--tvm-focus-exit-size) !important;
  border-radius:50% !important;
}
.tv-magic.is-focus .tvm-focus-toggle svg,
.tv-magic.is-focus .tvm-focus-icon-exit,
.tv-magic.is-focus .tvm-margin__fullscreenIcon{
  width:var(--tvm-focus-exit-glyph-size) !important;
  height:var(--tvm-focus-exit-glyph-size) !important;
  flex:0 0 var(--tvm-focus-exit-glyph-size) !important;
}

/* World law is prose, not a squeezed definition-list value. */
.tv-magic .tvm-ontology-block{
  width:min(34em,100%);
  margin:clamp(2.25em,4dvh,3.5em) auto 0;
  text-align:center;
}
.tv-magic .tvm-ontology-label{
  margin:0 0 .8em;
  color:var(--tvm-muted);
  font-size:.86em;
  line-height:1.5;
  font-weight:600;
}
.tv-magic .tvm-ontology-text{
  width:min(30em,100%);
  margin:0 auto;
  color:var(--tvm-ink);
  font-size:.96em;
  line-height:1.9;
  text-align:center;
  text-wrap:pretty;
}

@media(max-width:30em){
  .tv-magic #tvmStart{
    width:min(100%,calc(100dvw - 2em));
    min-height:6em !important;
    padding-inline:2em !important;
  }
  .tv-magic .tvm-share-row{
    gap:.65em;
  }
  .tv-magic .tvm-share-group{
    gap:.44em;
  }
  .tv-magic .tvm-ontology-text{
    width:min(27em,100%);
  }
}

@media (hover:hover) and (pointer:fine){
  .tv-magic #tvmCopy:hover:not(:disabled),
  .tv-magic .tvm-back:hover:not(:disabled),
  .tv-magic .tvm-result-restart .tvm-btn:hover:not(:disabled){
    transform:none !important;
  }
}

@media (prefers-reduced-motion:reduce){
  .tv-magic #tvmStart,
  .tv-magic #tvmCopy,
  .tv-magic .tvm-back,
  .tv-magic .tvm-result-restart .tvm-btn,
  .tv-magic .tvm-share-btn,
  .tv-magic .tvm-focus-toggle{
    transition:none !important;
  }
}


/* =========================================================
   v5.2 — real-browser refinement / Today-Margin CTA / grouped share optics
   ========================================================= */
.tv-magic{
  /* 0924today-derived composition: em inside controls, viewport only for bounded composition. */
  --tvm-start-cta-min:5em;
  --tvm-start-cta-fluid:8dvh;
  --tvm-start-cta-max:6.25em;
  --tvm-start-cta-width:min(34em,82dvw);
  --tvm-focus-control-size-v52:5em;
  --tvm-focus-glyph-size-v52:2.4em;
  --tvm-share-glyph-size-v52:1.5em;
  --tvm-related-gap:.9em;
  --tvm-section-gap-after-ontology:clamp(3.5em,6dvh,5.75em);
}

/* Start: retain Main CTA prominence without turning height itself into a 10em object. */
.tv-magic #tvmStart{
  width:var(--tvm-start-cta-width) !important;
  max-width:100% !important;
  min-height:clamp(var(--tvm-start-cta-min),var(--tvm-start-cta-fluid),var(--tvm-start-cta-max)) !important;
  padding-inline:clamp(2.25em,6dvw,4.5em) !important;
  padding-block:1.15em !important;
  border-radius:var(--tvm-radius-pill) !important;
  font-size:clamp(1.15em,1.35vw,1.4em) !important;
  line-height:1.2 !important;
  letter-spacing:-.012em !important;
}
.tv-magic .tvm-entry .tvm-actions{
  margin-top:clamp(2.25em,4dvh,3.6em) !important;
}
@media(max-width:30em){
  .tv-magic #tvmStart{
    width:min(100%,calc(100dvw - 2em)) !important;
    min-height:clamp(4.75em,7.5dvh,5.75em) !important;
    padding-inline:1.75em !important;
  }
}

/* Back is now a real Language-family action, including inside Question Frame. */
.tv-magic .tvm-question-frame .tvm-back,
.tv-magic .tvm-question-frame .tvm-back:hover,
.tv-magic .tvm-question-frame .tvm-back:active,
.tv-magic .tvm-back{
  width:auto !important;
  min-width:0 !important;
  min-height:var(--tvm-action-size) !important;
  padding-inline:1.15em !important;
  border:0.0625em solid var(--tvm-secondary-rest-border) !important;
  border-radius:var(--tvm-radius-pill) !important;
  background:var(--tvm-secondary-rest-bg) !important;
  color:var(--tvm-ink) !important;
  box-shadow:inset 0 0.0625em 0 rgba(255,255,255,.38) !important;
  -webkit-backdrop-filter:none !important;
  backdrop-filter:none !important;
}
@media (hover:hover) and (pointer:fine){
  .tv-magic .tvm-question-frame .tvm-back:hover:not(:disabled),
  .tv-magic .tvm-back:hover:not(:disabled){
    transform:none !important;
    background:var(--tvm-secondary-hover-bg) !important;
    border-color:var(--tvm-secondary-hover-border) !important;
    color:var(--tvm-ink) !important;
  }
}
.tv-magic .tvm-question-frame .tvm-back:active:not(:disabled),
.tv-magic .tvm-back:active:not(:disabled){
  transform:scale(var(--tvm-control-active-scale)) !important;
}

/* Focus enter and exit use one clearly visible geometry; hit area and glyph grow together. */
.tv-magic .tvm-focus-toggle,
.tv-magic.is-focus .tvm-focus-toggle,
.tv-magic .tvm-experience-toggle .tvm-focus-toggle,
.tv-magic.is-focus .tvm-experience-toggle .tvm-focus-toggle,
.tv-magic > .tvm-focus-toggle,
.tv-magic.is-focus > .tvm-focus-toggle{
  flex:0 0 var(--tvm-focus-control-size-v52) !important;
  width:var(--tvm-focus-control-size-v52) !important;
  height:var(--tvm-focus-control-size-v52) !important;
  min-width:var(--tvm-focus-control-size-v52) !important;
  min-height:var(--tvm-focus-control-size-v52) !important;
  border-radius:50% !important;
}
.tv-magic .tvm-focus-toggle svg,
.tv-magic.is-focus .tvm-focus-toggle svg,
.tv-magic .tvm-focus-icon-enter,
.tv-magic .tvm-focus-icon-exit,
.tv-magic .tvm-margin__fullscreenIcon{
  width:var(--tvm-focus-glyph-size-v52) !important;
  height:var(--tvm-focus-glyph-size-v52) !important;
  flex:0 0 var(--tvm-focus-glyph-size-v52) !important;
}

/* Result title unit: completion label belongs to the name; prose starts after a larger pause. */
.tv-magic .tvm-result-screen > .tvm-kicker{
  margin-bottom:.62em !important;
}
.tv-magic .tvm-result-screen > .tvm-result-name{
  margin:0 !important;
}
.tv-magic .tvm-result-screen > .tvm-result-name + .tvm-spacer--density-1{
  height:1.55em !important;
}

/* World law closes the law block; carrying begins as a clearly new section. */
.tv-magic .tvm-summary-section + .tvm-carry-section{
  margin-top:var(--tvm-section-gap-after-ontology) !important;
}

/* Copy button and the prompt are one related unit. */
.tv-magic .tvm-spacer--copy-to-prompt{
  height:var(--tvm-related-gap) !important;
}
.tv-magic .tvm-copy-action{
  margin-bottom:0 !important;
}
.tv-magic .tvm-prompt-group{
  margin-top:0 !important;
}

/* Explicit share action units: each circle and glyph travel as one grouped control. */
.tv-magic .tvm-share-unit{
  display:grid;
  place-items:center;
  width:var(--tvm-share-size);
  height:var(--tvm-share-size);
  min-width:var(--tvm-share-size);
  min-height:var(--tvm-share-size);
  flex:0 0 var(--tvm-share-size);
  margin:0;
  padding:0;
}
.tv-magic .tvm-share-unit > .tvm-share-btn{
  width:100% !important;
  height:100% !important;
  min-width:100% !important;
  min-height:100% !important;
  flex:none !important;
  display:grid !important;
  place-items:center !important;
  aspect-ratio:1 / 1;
  border-radius:50% !important;
  padding:0 !important;
}
.tv-magic .tvm-share-icon,
.tv-magic .tvm-copy-icon,
.tv-magic .tvm-share-font-icon{
  width:var(--tvm-share-glyph-size-v52) !important;
  height:var(--tvm-share-glyph-size-v52) !important;
  margin:0 !important;
  transform-origin:50% 50% !important;
  justify-self:center !important;
  align-self:center !important;
}
.tv-magic .tvm-share-font-icon{
  display:grid !important;
  place-items:center !important;
  font-size:var(--tvm-share-glyph-size-v52) !important;
  line-height:1 !important;
}
/* Per-glyph optical correction happens inside the fixed geometric circle. */
.tv-magic [data-share-action="x"] .tvm-share-font-icon{
  transform:translateY(-.02em) scale(.98) !important;
}
.tv-magic [data-share-action="threads"] .tvm-share-icon{
  transform:translateY(.01em) scale(1.14) !important;
}
.tv-magic [data-share-action="bluesky"] .tvm-share-icon{
  transform:translateY(.02em) scale(.98) !important;
}
.tv-magic [data-share-action="line"] .tvm-share-font-icon{
  transform:translateY(.01em) scale(1.12) !important;
}
.tv-magic [data-share-action="native"] .tvm-share-icon,
.tv-magic [data-share-action="story"] .tvm-share-icon,
.tv-magic [data-share-action="copy"] .tvm-copy-icon{
  transform:translateY(.01em) scale(1.08) !important;
}
.tv-magic .tvm-share-group{
  align-items:center !important;
}

/* Restart follows the same language-family action surface; wording is semantic, not system jargon. */
.tv-magic .tvm-result-restart .tvm-btn,
.tv-magic .tvm-result-restart .tvm-btn.is-ghost{
  width:auto !important;
  min-width:10em !important;
  min-height:var(--tvm-action-size) !important;
}

@media(prefers-reduced-motion:reduce){
  .tv-magic #tvmStart,
  .tv-magic .tvm-share-unit,
  .tv-magic .tvm-share-unit > .tvm-share-btn{
    transition:none !important;
  }
}


/* =========================================================
   v5.3 — Normal/Focus split + exact law-row centers + Akeru v3.0 resilience
   ========================================================= */
.tv-magic{
  --tvm-result-hero-gap:clamp(1.85em,3.2dvh,2.9em);
  --tvm-normal-bottom-space:3em;
  --tvm-law-row-gap:.58em;
  --tvm-law-column-gap:1.15em;
  --tvm-share-optical-size:1.58em;
}

/* Akeru v3.0-derived local hardening: keep SWELL from redefining interaction controls. */
.tv-magic,
.tv-magic *{
  box-sizing:border-box;
}
.tv-magic button{
  font-family:inherit;
  text-transform:none;
  appearance:none;
  -webkit-appearance:none;
  touch-action:manipulation;
  -webkit-tap-highlight-color:transparent;
}
.tv-magic .tvm-question-meta,
.tv-magic .tvm-question-meta-count{
  font-variant-numeric:tabular-nums;
}
.tv-magic .tvm-choice,
.tv-magic .tvm-btn,
.tv-magic .tvm-back,
.tv-magic .tvm-share-btn,
.tv-magic .tvm-focus-toggle{
  isolation:isolate;
}

/* Normal mode belongs to the WordPress article: content height, not a pseudo viewport. */
.tv-magic:not(.is-focus){
  padding-bottom:max(var(--tvm-normal-bottom-space),env(safe-area-inset-bottom));
}
.tv-magic:not(.is-focus) .tvm-entry,
.tv-magic:not(.is-focus) .tvm-question-screen,
.tv-magic:not(.is-focus) .tvm-result-screen{
  min-height:0 !important;
}
.tv-magic:not(.is-focus) .tvm-result-screen{
  width:min(48em,100%);
}
.tv-magic:not(.is-focus) .tvm-result-screen .tvm-result-name{
  font-size:clamp(2.05em,3vw,3em);
}
.tv-magic:not(.is-focus) .tvm-result-screen .tvm-core{
  font-size:1.15em;
}

/* Completion notice and magic name are distinct semantic layers in both modes. */
.tv-magic .tvm-result-screen > .tvm-kicker{
  margin-bottom:var(--tvm-result-hero-gap) !important;
}
.tv-magic .tvm-result-screen > .tvm-result-name{
  margin-top:0 !important;
}

/* One law row = one alignment unit. Label/value share the same row box center. */
.tv-magic .tvm-summary-grid.tvm-law-list,
.tv-magic .tvm-grid.tvm-law-list{
  display:grid !important;
  grid-template-columns:1fr !important;
  row-gap:var(--tvm-law-row-gap) !important;
  column-gap:0 !important;
}
.tv-magic .tvm-law-list > .tvm-law-row{
  display:grid !important;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr) !important;
  column-gap:var(--tvm-law-column-gap) !important;
  align-items:center !important;
  justify-items:stretch !important;
  width:100% !important;
  min-width:0 !important;
  margin:0 !important;
  padding:0 !important;
}
.tv-magic .tvm-law-list > .tvm-law-row > dt,
.tv-magic .tvm-law-list > .tvm-law-row > dd{
  display:flex !important;
  align-items:center !important;
  min-height:1.72em !important;
  margin:0 !important;
  padding:0 !important;
  line-height:1.45 !important;
}
.tv-magic .tvm-law-list > .tvm-law-row > dt{
  justify-content:flex-end !important;
  text-align:right !important;
  color:var(--tvm-muted);
}
.tv-magic .tvm-law-list > .tvm-law-row > dd{
  justify-content:flex-start !important;
  text-align:left !important;
  color:var(--tvm-ink);
  overflow-wrap:anywhere;
}

/* Language is the measured visual source of truth for text actions. */
.tv-magic .tvm-lang,
.tv-magic #tvmCopy,
.tv-magic .tvm-back,
.tv-magic .tvm-result-restart .tvm-btn,
.tv-magic .tvm-result-restart .tvm-btn.is-ghost{
  min-height:var(--tvm-action-size) !important;
  padding-block:0 !important;
  padding-inline:1.15em !important;
  border-radius:var(--tvm-radius-pill) !important;
  font-family:inherit !important;
  font-size:1em !important;
  font-weight:inherit !important;
  line-height:1.2 !important;
  align-items:center !important;
  justify-content:center !important;
}
.tv-magic #tvmCopy,
.tv-magic .tvm-back,
.tv-magic .tvm-result-restart .tvm-btn{
  display:inline-flex !important;
}
.tv-magic #tvmCopy{
  width:100% !important;
}
.tv-magic .tvm-back{
  width:auto !important;
}
.tv-magic .tvm-result-restart .tvm-btn{
  width:auto !important;
  min-width:10em !important;
}

/* Share: immutable geometric center wrapper; only the glyph receives optical correction. */
.tv-magic .tvm-share-unit,
.tv-magic .tvm-share-unit > .tvm-share-btn{
  aspect-ratio:1 / 1;
  border-radius:50% !important;
}
.tv-magic .tvm-share-icon-wrap{
  position:absolute;
  inset:0;
  display:grid;
  place-items:center;
  width:100%;
  height:100%;
  pointer-events:none;
}
.tv-magic .tvm-share-unit > .tvm-share-btn{
  position:relative;
  overflow:visible;
}
.tv-magic .tvm-share-icon,
.tv-magic .tvm-copy-icon{
  width:var(--tvm-share-optical-size) !important;
  height:var(--tvm-share-optical-size) !important;
}
.tv-magic .tvm-share-font-icon{
  width:auto !important;
  height:auto !important;
  font-size:var(--tvm-share-optical-size) !important;
}
.tv-magic [data-share-action="x"] .tvm-share-font-icon{
  transform:translateY(-.025em) scale(1.03) !important;
}
.tv-magic [data-share-action="threads"] .tvm-share-icon{
  transform:translateY(.005em) scale(1.15) !important;
}
.tv-magic [data-share-action="bluesky"] .tvm-share-icon{
  transform:translateY(.015em) scale(1.02) !important;
}
.tv-magic [data-share-action="line"] .tvm-share-font-icon{
  transform:translateY(.015em) scale(1.14) !important;
}
.tv-magic [data-share-action="native"] .tvm-share-icon{
  transform:translateY(.015em) scale(1.08) !important;
}
.tv-magic [data-share-action="story"] .tvm-share-icon{
  transform:translateY(.01em) scale(1.10) !important;
}
.tv-magic [data-share-action="copy"] .tvm-copy-icon{
  transform:translateY(.01em) scale(1.10) !important;
}

/* Focus start/exit: visible circle and glyph both use the enlarged geometry. */
.tv-magic .tvm-focus-toggle,
.tv-magic.is-focus .tvm-focus-toggle{
  width:var(--tvm-focus-control-size-v52) !important;
  height:var(--tvm-focus-control-size-v52) !important;
  min-width:var(--tvm-focus-control-size-v52) !important;
  min-height:var(--tvm-focus-control-size-v52) !important;
  display:grid !important;
  place-items:center !important;
  border-radius:50% !important;
}
.tv-magic .tvm-focus-toggle svg,
.tv-magic.is-focus .tvm-focus-toggle svg{
  width:var(--tvm-focus-glyph-size-v52) !important;
  height:var(--tvm-focus-glyph-size-v52) !important;
}

/* Focus keeps immersive viewport composition; it does not inherit Normal compaction. */
.tv-magic.is-focus .tvm-result-screen{
  min-height:100dvh !important;
}

@media(max-width:30em){
  .tv-magic{
    --tvm-result-hero-gap:2em;
    --tvm-law-column-gap:.9em;
  }
}

@media(prefers-reduced-motion:reduce){
  .tv-magic .tvm-share-icon-wrap,
  .tv-magic .tvm-law-row{
    transition:none !important;
  }
}


/* =========================================================
   v5.5 — unified controls / adaptive QA hardening / non-destructive feedback
   Base: 20260924_magic_v5.4.html
   ========================================================= */
.tv-magic{
  --tvm-normal-frame-width:min(50em,100%);
  --tvm-result-axis-width:min(48em,86dvw);
  --tvm-law-axis-width:min(38em,76dvw);
  --tvm-result-section-space:clamp(2.55em,3.5dvh,4em);
  --tvm-result-small-space:clamp(1.2em,1.7dvh,1.9em);
  --tvm-result-body-size:clamp(1.15em,1.25vw,1.32em);
  --tvm-result-meta-size:clamp(.875em,.86vw,.97em);
  --tvm-result-ui-size:clamp(1.025em,1.02vw,1.125em);
  --tvm-result-hero-gap:clamp(2.25em,4dvh,3.5em);
  --tvm-law-row-gap:.58em;

  --tvm-segment-outer-bg:rgba(255,255,255,.22);
  --tvm-segment-outer-border:rgba(32,38,36,.08);
  --tvm-segment-inner-bg:rgba(255,255,255,.82);
  --tvm-segment-inner-border:rgba(32,38,36,.08);
  --tvm-segment-inner-shadow:0 .0625em 0 rgba(255,255,255,.82),0 .22em .75em rgba(22,22,20,.07);

  --tvm-action-bg:var(--tvm-veil-solid);
  --tvm-action-border:var(--tvm-glass-edge);
  --tvm-action-hover-bg:var(--tvm-hover-medium);
  --tvm-action-hover-border:rgba(32,38,36,.14);
}

/* Result hierarchy is canonicalized in v5.7 below. */

/* Start remains v5.4; Question and Result use the same Normal frame axis. */
.tv-magic:not(.is-focus) .tvm-question-frame{
  width:var(--tvm-normal-frame-width);
  max-width:100%;
  margin-inline:auto;
}

/* Language: match the approved soft outer capsule + active inner pill. */
.tv-magic .tvm-language{
  background:var(--tvm-segment-outer-bg) !important;
  border:.0625em solid var(--tvm-segment-outer-border) !important;
  box-shadow:inset 0 .0625em 0 rgba(255,255,255,.28) !important;
  -webkit-backdrop-filter:none !important;
  backdrop-filter:none !important;
}
.tv-magic .tvm-lang{
  border:.0625em solid transparent !important;
  background:transparent !important;
  box-shadow:none !important;
}
.tv-magic .tvm-lang.is-active{
  background:var(--tvm-segment-inner-bg) !important;
  border-color:var(--tvm-segment-inner-border) !important;
  box-shadow:var(--tvm-segment-inner-shadow) !important;
}
@media (hover:hover) and (pointer:fine){
  .tv-magic .tvm-lang:hover:not(.is-active){
    background:rgba(255,255,255,.28) !important;
    border-color:transparent !important;
    transform:none !important;
  }
}

/* Question choices inherit the Language control's material language, not its segmented geometry. */
.tv-magic .tvm-choice{
  background:var(--tvm-segment-outer-bg) !important;
  border:.0625em solid var(--tvm-segment-outer-border) !important;
  border-radius:var(--tvm-radius-pill) !important;
  box-shadow:inset 0 .0625em 0 rgba(255,255,255,.24) !important;
  -webkit-backdrop-filter:none !important;
  backdrop-filter:none !important;
}
.tv-magic .tvm-choice.is-selected{
  background:var(--tvm-segment-inner-bg) !important;
  border-color:var(--tvm-segment-inner-border) !important;
  box-shadow:var(--tvm-segment-inner-shadow) !important;
}
@media (hover:hover) and (pointer:fine){
  .tv-magic .tvm-choice:hover:not(.is-selected):not(:disabled){
    background:rgba(255,255,255,.34) !important;
    border-color:rgba(32,38,36,.10) !important;
    box-shadow:inset 0 .0625em 0 rgba(255,255,255,.34) !important;
    transform:none !important;
  }
}
.tv-magic .tvm-choice:active:not(:disabled){
  transform:scale(.975) !important;
}

/* Prompt Copy / もどる / もういちど are one Button System. Width remains contextual. */
.tv-magic #tvmCopy,
.tv-magic .tvm-question-frame .tvm-back,
.tv-magic .tvm-result-restart .tvm-btn,
.tv-magic .tvm-result-restart .tvm-btn.is-ghost{
  min-height:var(--tvm-action-size) !important;
  padding-inline:1.2em !important;
  border:.0625em solid var(--tvm-action-border) !important;
  border-radius:var(--tvm-radius-pill) !important;
  background:var(--tvm-action-bg) !important;
  color:var(--tvm-ink) !important;
  box-shadow:var(--tvm-glass-shadow) !important;
  -webkit-backdrop-filter:blur(1.125em) saturate(1.06) !important;
  backdrop-filter:blur(1.125em) saturate(1.06) !important;
  font:inherit !important;
  line-height:1.2 !important;
  display:inline-flex !important;
  align-items:center !important;
  justify-content:center !important;
  transition:background var(--tvm-motion-fast) var(--tvm-ease),border-color var(--tvm-motion-fast) var(--tvm-ease),color var(--tvm-motion-fast) var(--tvm-ease),transform var(--tvm-motion-fast) var(--tvm-ease),box-shadow var(--tvm-motion-fast) var(--tvm-ease) !important;
}
.tv-magic #tvmCopy{width:100% !important;}
.tv-magic .tvm-question-frame .tvm-back{width:auto !important;}
.tv-magic .tvm-result-restart .tvm-btn{width:auto !important;min-width:10em !important;}
.tv-magic .tvm-question-frame .tvm-back::before{content:none !important;}
@media (hover:hover) and (pointer:fine){
  .tv-magic #tvmCopy:hover:not(:disabled),
  .tv-magic .tvm-question-frame .tvm-back:hover:not(:disabled),
  .tv-magic .tvm-result-restart .tvm-btn:hover:not(:disabled){
    background:var(--tvm-action-hover-bg) !important;
    border-color:var(--tvm-action-hover-border) !important;
    box-shadow:none !important;
    transform:none !important;
  }
}
.tv-magic #tvmCopy:active:not(:disabled),
.tv-magic .tvm-question-frame .tvm-back:active:not(:disabled),
.tv-magic .tvm-result-restart .tvm-btn:active:not(:disabled){
  transform:scale(.975) !important;
}

/* Prompt-copy success is explicit at the point of action. */
.tv-magic #tvmCopy[data-state="success"]{
  border-color:var(--tvm-control-selected-border) !important;
  background:var(--tvm-control-selected-bg) !important;
}
.tv-magic .tvm-btn-label{pointer-events:none;}
.tv-magic .tvm-copy-status{
  position:absolute !important;
  inline-size:.0625em !important;
  block-size:.0625em !important;
  margin:-.0625em !important;
  padding:0 !important;
  overflow:hidden !important;
  clip-path:inset(50%) !important;
  white-space:nowrap !important;
  border:0 !important;
}

/* Laws are one continuous list. World-law prose begins after the same row rhythm. */
.tv-magic .tvm-summary-grid.tvm-law-list,
.tv-magic .tvm-grid.tvm-law-list{
  row-gap:var(--tvm-law-row-gap) !important;
}
.tv-magic .tvm-detail{margin-top:0 !important;}
.tv-magic .tvm-ontology-block{
  margin-top:var(--tvm-law-row-gap) !important;
}
.tv-magic .tvm-ontology-label{margin-bottom:.8em !important;}

/* Focus exit glyph is deliberately more visible; hit area remains stable. */
.tv-magic.is-focus .tvm-focus-toggle .tvm-focus-icon-exit,
.tv-magic.is-focus .tvm-focus-toggle .tvm-margin__fullscreenIcon.tvm-focus-icon-exit{
  width:3.5em !important;
  height:3.5em !important;
  flex-basis:3.5em !important;
}

/* Share geometry stays fixed; only visible glyph area receives optical correction. */
.tv-magic [data-share-action="x"] .tvm-share-font-icon{transform:translateY(-.025em) scale(.97) !important;}
.tv-magic [data-share-action="threads"] .tvm-share-icon{transform:translateY(.005em) scale(1.20) !important;}
.tv-magic [data-share-action="bluesky"] .tvm-share-icon{transform:translateY(.015em) scale(1.00) !important;}
.tv-magic [data-share-action="line"] .tvm-share-font-icon{transform:translateY(.015em) scale(1.25) !important;}
.tv-magic [data-share-action="native"] .tvm-share-icon{transform:translateY(.01em) scale(1.18) !important;}
.tv-magic [data-share-action="story"] .tvm-share-icon{transform:translateY(.01em) scale(1.18) !important;}
.tv-magic [data-share-action="copy"] .tvm-copy-icon{transform:translateY(.01em) scale(1.18) !important;}

/* Busy state never hides share/icon DOM. */
.tv-magic .tvm-share-btn[data-busy="true"] .tvm-share-icon-wrap,
.tv-magic .tvm-share-btn[data-busy="true"] .tvm-share-fallback{
  visibility:visible !important;
  opacity:1 !important;
}

@media(max-width:30em){
  .tv-magic{
    --tvm-result-axis-width:min(46em,calc(100dvw - 1.5em));
    --tvm-law-axis-width:min(35em,calc(100dvw - 1.75em));
  }
  .tv-magic:not(.is-focus) .tvm-result-name{font-size:clamp(2.15em,9vw,2.95em);}
}

@media(prefers-reduced-transparency:reduce){
  .tv-magic #tvmCopy,
  .tv-magic .tvm-question-frame .tvm-back,
  .tv-magic .tvm-result-restart .tvm-btn{
    -webkit-backdrop-filter:none !important;
    backdrop-filter:none !important;
    background:var(--tvm-veil-solid) !important;
  }
}



/* =========================================================
   v5.7 — canonical Result hierarchy / Focus composition
   Consolidates Result-specific overrides into one final layer.
   ========================================================= */
.tv-magic{
  --tvm-v57-result-width:min(50em,88dvw);
  --tvm-v57-law-width:min(38em,74dvw);
  --tvm-v57-prompt-width:min(42em,80dvw);
  --tvm-v57-section-gap:clamp(2.75em,4.2dvh,4.8em);
  --tvm-v57-law-gap:.72em;
  --tvm-v57-discovery-gap:clamp(1.15em,1.8dvh,1.8em);
}

/* Discovery -> Laws -> Carry -> Share -> Again */
.tv-magic .tvm-result-screen{
  width:var(--tvm-v57-result-width);
  max-width:100%;
  margin-inline:auto;
  padding-top:var(--tvm-experience-top);
  padding-bottom:var(--tvm-experience-bottom);
}
.tv-magic .tvm-result-discovery{
  width:100%;
  max-width:44em;
  margin-inline:auto;
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:var(--tvm-v57-discovery-gap);
}
.tv-magic .tvm-result-discovery .tvm-kicker{
  margin:0 !important;
  font-size:var(--tvm-result-meta-size);
  color:var(--tvm-muted);
}
.tv-magic .tvm-result-discovery .tvm-result-name{
  margin:0 !important;
  font-size:clamp(2.35em,3.35vw,3.4em);
  line-height:1.08;
  letter-spacing:-.034em;
}
.tv-magic .tvm-result-discovery .tvm-core{
  margin:0 !important;
  max-width:36em;
  font-size:var(--tvm-result-body-size);
  line-height:1.82;
}
.tv-magic .tvm-result-axis{
  width:min(48em,86dvw);
  max-width:100%;
  margin-inline:auto;
}
.tv-magic .tvm-result-axis > .tvm-result-section,
.tv-magic .tvm-result-axis > .tvm-result-restart{
  margin-top:var(--tvm-v57-section-gap) !important;
}
.tv-magic .tvm-result-section-title{
  margin:0 0 1.35em !important;
}

/* Law layout restored to the proven v5.5 composition: 5 core rows + 3 detail rows + world law. */
.tv-magic .tvm-law-group{
  width:var(--tvm-v57-law-width);
  max-width:100%;
  margin-inline:auto;
}
.tv-magic .tvm-summary-grid.tvm-law-list,
.tv-magic .tvm-grid.tvm-law-list{
  width:100%;
  display:grid !important;
  grid-template-columns:1fr !important;
  row-gap:var(--tvm-law-row-gap) !important;
  column-gap:0 !important;
  margin:0 !important;
  padding:0 !important;
}
.tv-magic .tvm-law-list > .tvm-law-row{
  display:grid !important;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr) !important;
  column-gap:var(--tvm-law-column-gap) !important;
  align-items:center !important;
  justify-items:stretch !important;
  width:100% !important;
  min-width:0 !important;
  margin:0 !important;
  padding:0 !important;
}
.tv-magic .tvm-law-list > .tvm-law-row > dt,
.tv-magic .tvm-law-list > .tvm-law-row > dd{
  display:flex !important;
  align-items:center !important;
  min-height:1.72em !important;
  margin:0 !important;
  padding:0 !important;
  line-height:1.45 !important;
}
.tv-magic .tvm-law-list > .tvm-law-row > dt{
  justify-content:flex-end !important;
  text-align:right !important;
  color:var(--tvm-muted);
}
.tv-magic .tvm-law-list > .tvm-law-row > dd{
  justify-content:flex-start !important;
  text-align:left !important;
  color:var(--tvm-ink);
  overflow-wrap:anywhere;
}
.tv-magic .tvm-detail{
  margin-top:0;
}
.tv-magic .tvm-law-list--detail{
  margin-top:0 !important;
}
.tv-magic .tvm-ontology-block{
  width:min(34em,100%);
  margin:clamp(2.25em,4dvh,3.5em) auto 0 !important;
  text-align:center;
}
.tv-magic .tvm-ontology-label{
  margin:0 0 .8em !important;
  color:var(--tvm-muted);
  font-size:var(--tvm-result-meta-size);
  line-height:1.5;
  font-weight:600;
  text-align:center;
}
.tv-magic .tvm-ontology-text{
  width:min(30em,100%);
  margin:0 auto !important;
  color:var(--tvm-ink);
  font-size:var(--tvm-result-body-size);
  line-height:1.9;
  text-align:center;
  overflow-wrap:anywhere;
}

/* Carry is action-first; full prompt remains available but visually secondary. */
.tv-magic .tvm-carry-section{
  width:100%;
}
.tv-magic .tvm-carry-lead{
  max-width:36em;
  margin-inline:auto;
  line-height:1.75;
  font-size:var(--tvm-result-body-size);
}
.tv-magic .tvm-copy-action{
  width:min(28em,100%);
  margin-inline:auto;
}
.tv-magic .tvm-prompt-group{
  width:var(--tvm-v57-prompt-width);
  max-width:100%;
  margin-inline:auto;
}
.tv-magic .tvm-prompt{
  min-height:7.5em;
  max-height:18em;
  font-size:.9em;
  line-height:1.65;
}
.tv-magic .tvm-result-restart .tvm-btn{
  min-width:7.5em !important;
}

/* Focus is a dedicated composition rather than Normal with the background removed. */
.tv-magic.is-focus{
  --tvm-v57-result-width:min(58em,91dvw);
  --tvm-v57-law-width:min(44em,76dvw);
  --tvm-v57-prompt-width:min(48em,82dvw);
  --tvm-v57-section-gap:clamp(3.4em,6.2dvh,6.2em);
  --tvm-v57-law-gap:clamp(.82em,1.15dvh,1.05em);
  --tvm-result-body-size:clamp(1.18em,1.35vw,1.38em);
  --tvm-result-meta-size:clamp(.9em,.9vw,1em);
  --tvm-result-ui-size:clamp(1.05em,1.04vw,1.15em);
}
.tv-magic.is-focus .tvm-entry{
  padding-top:clamp(6.5em,15dvh,11em);
}
.tv-magic.is-focus .tvm-question-frame{
  width:min(44em,80dvw);
}
.tv-magic.is-focus .tvm-question{
  font-size:clamp(2.08em,2.8vw,3em);
}
.tv-magic.is-focus .tvm-choice{
  min-height:3.8em;
  font-size:clamp(1.035em,1.08vw,1.16em);
}
.tv-magic.is-focus .tvm-result-screen{
  width:var(--tvm-v57-result-width);
  min-height:100dvh !important;
  padding-top:clamp(5.5em,10dvh,8.5em);
  padding-bottom:clamp(5em,9dvh,8em);
}
.tv-magic.is-focus .tvm-result-discovery{
  max-width:50em;
  gap:clamp(1.4em,2.4dvh,2.2em);
}
.tv-magic.is-focus .tvm-result-discovery .tvm-result-name{
  font-size:clamp(3em,4.2vw,4.35em);
}
.tv-magic.is-focus .tvm-result-discovery .tvm-core{
  max-width:40em;
  font-size:clamp(1.2em,1.45vw,1.5em);
  line-height:1.9;
}
.tv-magic.is-focus .tvm-result-axis{
  width:min(54em,88dvw);
}
.tv-magic.is-focus .tvm-law-list > .tvm-law-row{
  column-gap:1.45em !important;
}
.tv-magic.is-focus .tvm-law-list > .tvm-law-row > dt{
  font-size:clamp(.92em,.9vw,1.02em);
}
.tv-magic.is-focus .tvm-law-list > .tvm-law-row > dd,
.tv-magic.is-focus .tvm-ontology-text{
  font-size:clamp(1.08em,1.18vw,1.24em);
  line-height:1.68 !important;
}
.tv-magic.is-focus .tvm-carry-lead{
  max-width:40em;
  font-size:clamp(1.08em,1.18vw,1.24em);
}
.tv-magic.is-focus #tvmCopy,
.tv-magic.is-focus .tvm-result-restart .tvm-btn{
  min-height:3.6em !important;
  font-size:var(--tvm-result-ui-size) !important;
}
.tv-magic.is-focus .tvm-share-btn{
  font-size:var(--tvm-result-ui-size);
}
.tv-magic.is-focus .tvm-prompt{
  min-height:12em;
  max-height:30em;
  font-size:.95em;
}

@media(max-width:48em){
  .tv-magic,
  .tv-magic.is-focus{
    --tvm-v57-result-width:min(46em,calc(100dvw - 2em));
    --tvm-v57-law-width:min(38em,calc(100dvw - 2em));
    --tvm-v57-prompt-width:min(42em,calc(100dvw - 2em));
  }
}
@media(max-width:30em){
  .tv-magic,
  .tv-magic.is-focus{
    --tvm-v57-result-width:calc(100dvw - 1.5em);
    --tvm-v57-law-width:calc(100dvw - 2em);
    --tvm-v57-prompt-width:calc(100dvw - 1.5em);
    --tvm-v57-section-gap:clamp(2.1em,3.2dvh,3em);
  }
  .tv-magic .tvm-law-list > .tvm-law-row{
    grid-template-columns:minmax(7.5em,auto) minmax(0,1fr) !important;
    column-gap:.9em !important;
  }
  .tv-magic.is-focus .tvm-entry{
    padding-top:clamp(4.5em,10dvh,7em);
  }
  .tv-magic.is-focus .tvm-question-frame{
    width:calc(100dvw - 2em);
  }
  .tv-magic.is-focus .tvm-question{
    font-size:clamp(1.82em,7.4vw,2.3em);
  }
  .tv-magic.is-focus .tvm-result-discovery .tvm-result-name{
    font-size:clamp(2.45em,10vw,3.3em);
  }
  .tv-magic.is-focus .tvm-result-discovery .tvm-core{
    font-size:1.08em;
    line-height:1.82;
  }
}
@media(max-height:42em){
  .tv-magic.is-focus .tvm-entry{
    padding-top:clamp(3.25em,7dvh,4.5em);
  }
  .tv-magic.is-focus .tvm-result-screen{
    padding-top:clamp(3.25em,6dvh,4.5em);
    padding-bottom:clamp(3em,6dvh,4.5em);
  }
}



/* =========================================================
   v5.9 — ephemeral experience state / white & clear Normal actions
   - Answers, question position, Result/Profile/Prompt remain memory-only.
   - Reload always starts a fresh experience.
   - Display preferences remain persistent via localStorage.
   - Normal-mode recurring actions use white or transparent surfaces only.
   ========================================================= */
.tv-magic{
  --tvm-v59-white:#fff;
  --tvm-v59-clear:transparent;
  --tvm-v59-border:rgba(32,38,36,.14);
  --tvm-v59-hover-border:rgba(32,38,36,.24);
  --tvm-v59-hover-white:rgba(255,255,255,.72);
}

/* Copy is the primary carry action: clean white, no grey/ivory cast. */
.tv-magic:not(.is-focus) #tvmCopy{
  background:var(--tvm-v59-white) !important;
  border-color:var(--tvm-v59-border) !important;
  box-shadow:0 .10em .45em rgba(22,22,20,.045) !important;
  -webkit-backdrop-filter:none !important;
  backdrop-filter:none !important;
}

/* Back / Again stay visually quieter: transparent at rest. */
.tv-magic:not(.is-focus) .tvm-question-frame .tvm-back,
.tv-magic:not(.is-focus) .tvm-result-restart .tvm-btn,
.tv-magic:not(.is-focus) .tvm-result-restart .tvm-btn.is-ghost{
  background:var(--tvm-v59-clear) !important;
  border-color:var(--tvm-v59-border) !important;
  box-shadow:none !important;
  -webkit-backdrop-filter:none !important;
  backdrop-filter:none !important;
}
@media (hover:hover) and (pointer:fine){
  .tv-magic:not(.is-focus) #tvmCopy:hover:not(:disabled),
  .tv-magic:not(.is-focus) .tvm-question-frame .tvm-back:hover:not(:disabled),
  .tv-magic:not(.is-focus) .tvm-result-restart .tvm-btn:hover:not(:disabled){
    background:var(--tvm-v59-hover-white) !important;
    border-color:var(--tvm-v59-hover-border) !important;
    box-shadow:none !important;
  }
}

/* Dark mode uses the same semantic roles: white primary, transparent secondary. */
.tv-magic[data-tvm-theme="dark"]{
  --tvm-v59-white:rgba(255,255,255,.10);
  --tvm-v59-clear:transparent;
  --tvm-v59-border:rgba(255,255,255,.22);
  --tvm-v59-hover-border:rgba(255,255,255,.36);
  --tvm-v59-hover-white:rgba(255,255,255,.14);
}

@media (prefers-reduced-transparency:reduce){
  .tv-magic:not(.is-focus) #tvmCopy,
  .tv-magic:not(.is-focus) .tvm-question-frame .tvm-back,
  .tv-magic:not(.is-focus) .tvm-result-restart .tvm-btn{
    -webkit-backdrop-filter:none !important;
    backdrop-filter:none !important;
  }
}

/* =========================================================
   v6.8 — unified scrollable Focus shell / fluid scale / editorial Story Card
   - One responsive system across PC and mobile.
   - Focus shell stays fixed; its app surface is the shared vertical scroller.
   - Narrow-screen exceptions are reserved for genuine geometry constraints.
   ========================================================= */
.tv-magic{
  --tvm-law-row-gap:1.02em;
  --tvm-result-fluid-body:clamp(1.02em,1.12cqw,1.24em);
  --tvm-result-fluid-meta:clamp(.82em,.84cqw,.96em);
  --tvm-result-fluid-name:clamp(2.45em,3.55cqw,3.7em);
  --tvm-result-fluid-law:clamp(1em,1.02cqw,1.20em);
  --tvm-result-fluid-label:clamp(.84em,.80cqw,1em);
}

/* Entry hero: authored line breaks remain explicit; automatic wraps remain natural. */
.tv-magic .tvm-entry .tvm-hero{
  font-size:clamp(2em,7.15cqw,3.15em);
  line-height:1.04;
}
.tv-magic .tvm-hero-gap{
  display:block;
  width:100%;
  height:.18em;
  pointer-events:none;
}

/* Questions use one fluid equation. JS only marks genuinely wrapped questions. */
.tv-magic .tvm-question{
  font-size:clamp(1.40em,5.55cqw,2.08em);
  line-height:1.48;
}
.tv-magic.is-focus .tvm-question{
  font-size:clamp(1.42em,5.65cqw,2.12em);
  line-height:1.50;
}
.tv-magic .tvm-question-frame .tvm-choices{margin-top:1.05em;}
.tv-magic .tvm-question-frame.is-question-multiline .tvm-choices{margin-top:1.30em;}
.tv-magic.is-focus .tvm-question-frame.is-question-multiline .tvm-choices{margin-top:1.34em;}

/* Result: Normal and Focus share the same scale. Focus only widens the ceiling slightly. */
.tv-magic .tvm-result-screen{
  width:min(50em,94cqw);
}
.tv-magic .tvm-result-discovery{
  max-width:47em;
}
.tv-magic .tvm-result-discovery .tvm-kicker{
  margin-bottom:clamp(1.7em,2.8dvh,2.55em) !important;
}
.tv-magic .tvm-result-discovery .tvm-result-name{
  font-size:var(--tvm-result-fluid-name);
}
.tv-magic .tvm-result-discovery .tvm-core{
  max-width:39em;
  font-size:var(--tvm-result-fluid-body);
  line-height:1.82;
}
.tv-magic .tvm-result-axis{
  width:min(50em,92cqw);
}
.tv-magic .tvm-law-group{
  width:min(40em,100%);
}
.tv-magic .tvm-law-list > .tvm-law-row > dt{
  font-size:var(--tvm-result-fluid-label);
}
.tv-magic .tvm-law-list > .tvm-law-row > dd,
.tv-magic .tvm-ontology-text{
  font-size:var(--tvm-result-fluid-law);
  line-height:1.68 !important;
}
.tv-magic .tvm-result-section-title{
  font-size:clamp(1.02em,.98cqw,1.18em);
}

/* World law is one centered proposition, always outside the tabular rhythm. */
.tv-magic .tvm-ontology-block{
  width:min(36em,100%);
  margin:clamp(1.9em,2.8dvh,2.5em) auto 0 !important;
  text-align:center !important;
}
.tv-magic .tvm-ontology-label,
.tv-magic .tvm-ontology-text{
  text-align:center !important;
  margin-left:auto !important;
  margin-right:auto !important;
}
.tv-magic .tvm-ontology-label{margin-bottom:1.12em !important;}
.tv-magic .tvm-ontology-text{width:min(32em,100%) !important;}

/* Carry helper remains clearly subordinate to the result. */
.tv-magic .tvm-carry-lead{
  display:flex;
  flex-direction:column;
  align-items:center;
  width:min(100%,29em);
  max-width:29em;
  margin-left:auto !important;
  margin-right:auto !important;
  font-size:clamp(.78em,.74cqw,.88em) !important;
  line-height:1.40 !important;
}
.tv-magic .tvm-carry-lead-line{
  width:min(100%,26em);
  margin:0;
  line-height:1.40;
  text-align:center;
}
.tv-magic .tvm-carry-lead-gap{
  display:block;
  width:100%;
  height:.18em;
  flex:none;
}

/* Focus uses the same responsive system. No independent mobile composition. */
.tv-magic.is-focus{
  --tvm-v57-result-width:min(54em,94dvw);
  --tvm-v57-law-width:min(42em,86dvw);
  --tvm-v57-prompt-width:min(48em,88dvw);
  --tvm-v57-section-gap:clamp(3.0em,5dvh,5.0em);
  --tvm-result-body-size:var(--tvm-result-fluid-body);
  --tvm-result-meta-size:var(--tvm-result-fluid-meta);
}
.tv-magic.is-focus .tvm-screen{
  margin-left:auto;
  margin-right:auto;
}
.tv-magic.is-focus .tvm-result-screen{
  width:var(--tvm-v57-result-width);
  min-height:auto !important;
  padding-top:clamp(3.75em,7dvh,6em);
  padding-bottom:clamp(4.5em,8dvh,7em);
}
.tv-magic.is-focus .tvm-result-discovery{
  max-width:50em;
}
.tv-magic.is-focus .tvm-result-discovery .tvm-result-name{
  font-size:clamp(2.55em,3.75cqw,4.0em);
}
.tv-magic.is-focus .tvm-result-discovery .tvm-core{
  max-width:41em;
  font-size:clamp(1.03em,1.18cqw,1.34em);
  line-height:1.82;
}
.tv-magic.is-focus .tvm-result-axis{
  width:min(52em,90dvw);
}
.tv-magic.is-focus .tvm-law-list > .tvm-law-row > dt{
  font-size:clamp(.86em,.82cqw,1.02em);
}
.tv-magic.is-focus .tvm-law-list > .tvm-law-row > dd,
.tv-magic.is-focus .tvm-ontology-text{
  font-size:clamp(1em,1.04cqw,1.22em);
  line-height:1.68 !important;
}
.tv-magic.is-focus .tvm-result-section-title{
  font-size:clamp(1.03em,1cqw,1.20em);
}
.tv-magic.is-focus .tvm-carry-lead{
  font-size:clamp(.79em,.72cqw,.89em) !important;
  line-height:1.40 !important;
}
.tv-magic.is-focus .tvm-carry-lead-gap{height:.18em;}

/* Long result/prompt content remains reachable on every viewport. */
.tv-magic.is-focus .tvm-result-restart{
  padding-bottom:max(1em,env(safe-area-inset-bottom));
}

/* Genuine extreme-width safeguard only. */
@container tvmagic (max-width:22em){
  .tv-magic .tvm-question-frame{width:100%;}
  .tv-magic .tvm-result-axis{width:100%;}
  .tv-magic .tvm-law-list > .tvm-law-row{
    grid-template-columns:minmax(7.25em,auto) minmax(0,1fr) !important;
    column-gap:.8em !important;
  }
}


/* =========================================================
   v7.1 — safe mobile law layout / unified row rhythm / compact share row
   PC horizontal law geometry intentionally remains unchanged.
   ========================================================= */
.tv-magic{
  --tvm-v71-law-row-gap:.88em;
  --tvm-q-choice-pad-x:clamp(1.25em,2.2vw,1.55em);
}

/* One visible vertical rhythm across all eight law rows.
   Remove the older min-height contribution so the perceived spacing comes
   from one source: row-gap. LIMIT -> ACCESS uses the same gap as every row. */
.tv-magic .tvm-summary-grid.tvm-law-list,
.tv-magic .tvm-grid.tvm-law-list{
  row-gap:var(--tvm-v71-law-row-gap) !important;
}
.tv-magic .tvm-law-list--detail{
  margin-top:var(--tvm-v71-law-row-gap) !important;
}
.tv-magic .tvm-law-list > .tvm-law-row > dt,
.tv-magic .tvm-law-list > .tvm-law-row > dd{
  min-height:0 !important;
  line-height:1.45 !important;
}

/* Question answers remain scan-friendly: a shared left reading edge with
   a little more inset than the pill itself. */
.tv-magic .tvm-choice{
  padding-left:var(--tvm-q-choice-pad-x) !important;
  padding-right:var(--tvm-q-choice-pad-x) !important;
  text-align:left !important;
}

@media(max-width:30em){
  /* Safari-safe mobile law layout.
     No subgrid and no display:contents: both semantic lists remain ordinary
     grids, so every law row is paintable and scrollable on iOS Safari.
     The whole information block is deliberately narrower than the viewport,
     then centered as one unit. */
  .tv-magic .tvm-law-group{
    display:block !important;
    width:min(22.5em,calc(100dvw - 2em)) !important;
    max-width:100% !important;
    margin-left:auto !important;
    margin-right:auto !important;
  }
  .tv-magic .tvm-law-group > .tvm-result-section-title{
    width:100% !important;
    text-align:center !important;
  }
  .tv-magic .tvm-law-group > .tvm-law-list,
  .tv-magic .tvm-law-group .tvm-detail > .tvm-law-list{
    display:grid !important;
    grid-template-columns:1fr !important;
    width:100% !important;
    max-width:100% !important;
    margin-left:0 !important;
    margin-right:0 !important;
  }
  .tv-magic .tvm-law-group > .tvm-detail{
    display:block !important;
    width:100% !important;
    max-width:100% !important;
  }
  .tv-magic .tvm-law-list > .tvm-law-row{
    display:grid !important;
    grid-template-columns:7.75em minmax(0,1fr) !important;
    column-gap:clamp(.68em,2.5cqw,.88em) !important;
    align-items:start !important;
    width:100% !important;
    max-width:100% !important;
    margin:0 !important;
  }
  .tv-magic .tvm-law-list > .tvm-law-row > dt,
  .tv-magic .tvm-law-list > .tvm-law-row > dd{
    display:block !important;
    width:auto !important;
    min-width:0 !important;
    max-width:100% !important;
    margin:0 !important;
  }
  .tv-magic .tvm-law-list > .tvm-law-row > dt{
    text-align:right !important;
  }
  .tv-magic .tvm-law-list > .tvm-law-row > dd{
    text-align:left !important;
    overflow-wrap:anywhere !important;
  }
  .tv-magic .tvm-ontology-block{
    width:100% !important;
    max-width:100% !important;
    margin-left:auto !important;
    margin-right:auto !important;
  }
  .tv-magic .tvm-ontology-text{
    width:min(100%,27em) !important;
    max-width:100% !important;
  }

  /* Focus is internally scrollable; reserve enough terminal space that the
     world law, share actions and restart control can clear mobile browser UI. */
  .tv-magic.is-focus #tvmagicApp{
    padding-bottom:max(10em,calc(env(safe-area-inset-bottom) + 8em)) !important;
    scroll-padding-bottom:max(10em,calc(env(safe-area-inset-bottom) + 8em));
  }
  .tv-magic.is-focus .tvm-result-screen{
    padding-bottom:max(6em,calc(env(safe-area-inset-bottom) + 4em)) !important;
  }

  /* Seven actions must remain on one line on phone widths. */
  .tv-magic{
    --tvm-share-size:clamp(2.18em,9.45cqw,2.62em);
    --tvm-share-optical-size:clamp(.98em,4.15cqw,1.25em);
    --tvm-share-glyph-size-v52:var(--tvm-share-optical-size);
  }
  .tv-magic .tvm-share-row{
    display:flex !important;
    flex-wrap:nowrap !important;
    justify-content:center !important;
    align-items:center !important;
    width:100% !important;
    max-width:100% !important;
    gap:clamp(.16em,1.05cqw,.32em) !important;
  }
  .tv-magic .tvm-share-group{
    display:flex !important;
    flex-wrap:nowrap !important;
    align-items:center !important;
    gap:clamp(.14em,.92cqw,.28em) !important;
    min-width:0 !important;
  }
  .tv-magic .tvm-share-unit{
    width:var(--tvm-share-size) !important;
    height:var(--tvm-share-size) !important;
    min-width:var(--tvm-share-size) !important;
    min-height:var(--tvm-share-size) !important;
    flex:0 0 var(--tvm-share-size) !important;
  }
  .tv-magic .tvm-share-unit > .tvm-share-btn{
    width:100% !important;
    height:100% !important;
    min-width:100% !important;
    min-height:100% !important;
  }
}


/* =========================================================
   v7.2 — borderless share actions / mobile terminal reachability
   ========================================================= */
.tv-magic .tvm-share-btn,
.tv-magic .tvm-share-btn:hover,
.tv-magic .tvm-share-btn:hover:not(:disabled),
.tv-magic .tvm-share-btn:active,
.tv-magic .tvm-share-btn:active:not(:disabled),
.tv-magic .tvm-share-btn:focus-visible{
  border:0 !important;
  border-color:transparent !important;
  box-shadow:none !important;
}

@media(forced-colors:active){
  .tv-magic .tvm-share-btn,
  .tv-magic .tvm-share-btn:hover,
  .tv-magic .tvm-share-btn:focus-visible{
    border:1px solid ButtonText !important;
    border-color:ButtonText !important;
  }
}

@media(max-width:30em){
  .tv-magic.is-focus .tvm-ontology-block{
    scroll-margin-bottom:max(10em,calc(env(safe-area-inset-bottom) + 8em));
  }
  .tv-magic.is-focus .tvm-result-restart{
    padding-bottom:max(4em,calc(env(safe-area-inset-bottom) + 3em)) !important;
  }
}


/* =========================================================
   v7.3 — Story Card single-color typography
   ========================================================= */
/* Web UI colors remain unchanged. Story Card alone uses one light text color
   over a dark neutral image veil for stable photographic readability. */

</style>

<div class="tv-magic" id="tvmagic">
  <div id="tvmagicApp" aria-live="polite"></div>
  <textarea id="tvmPromptTemplateJA" hidden aria-hidden="true">以下は、 https://TranquilGuides.com で生成した私専用のPersona Magic Profileです。

[TASK]
このProfileを、今後の生成における「魔法法則の固定核」として使用してください。
これは性格診断・心理診断・能力判定・適性評価・占い・客観的な人格分析ではなく、質問への選択から構成された創作上の魔法体系です。
このPromptを受け取ったら、最初に追加質問をせず、Profileを保持した具体的な成果物を一つ生成してください。 迷った場合も質問へ戻らず、固定核を壊さない最小限の解釈で最初の一例まで進めてください。

[PRIORITY]
1. Persona Magic Profile = FIXED CORE
2. 正当に参照できる既存文脈 = SUPPORTING CONTEXT
3. 固定核を壊さず成立させる論理解釈 = DERIVED INTERPRETATION
4. 今回だけの具体化 = MANIFESTATION DETAIL

下位層から上位層を書き換えないでください。Profileに確定値として書かれた項目は、直接質問されたか、回答間の整合からTranquilGuides側で解決されたかに関係なくFIXED COREです。未確定なのは、明示的にunspecified / open等として残された部分だけです。

[PERSONA MAGIC PROFILE]
{{PERSONA_MAGIC_PROFILE}}
[/PERSONA MAGIC PROFILE]

[CORE SEMANTICS]
Profileの各項目は装飾語ではなく、互いに因果関係を持つ法則です。
DOMINANT_PRINCIPLE = 中心原理。
SOURCE = 力の発生源。
ACCESS = SOURCEと有効なTARGETの接続が成立する条件。
MEDIUM = 接続成立後にEFFECTを実行する行為・媒介。
TARGET = 作用対象。
EFFECT = TARGETへ起きる変化。
COST = 発動に伴って必ず失われるもの。
LIMIT = 成立範囲・使用条件を制約する境界。
CONTROL = 結果を意図的に決められる全体的な程度。
ONTOLOGY = この魔法が成立可能である理由を定める世界法則。

原則として SOURCE → ACCESS → MEDIUM → TARGET → EFFECT → LIMIT/COST → CONTROL の因果を、ONTOLOGYが全体として説明します。SOURCE / ACCESS / MEDIUMを同義にしないでください。たとえばsource=self、access=contact、medium=touchなら、力は本人から生まれ、接触で対象との接続条件が成立し、その接続中のtouchが発動行為です。役割を混ぜて一つの設定へ潰さないでください。

[FIXED CORE RULES]
Profileのtype、operation、level、ontology、明示されたrule等を、SUPPORTING CONTEXT、ジャンル慣習、ドラマ性、映像映え、ゲームバランス、一般的な魔法イメージを理由に変更しないでください。

COSTとLIMITは別概念です。cost.type=noneなら、寿命、記憶、身体損傷、精神的消耗、疲労、人格変化、資源消費、強制的な時間損失等を「発動の代償」として追加しません。ACCESSを満たすこと、MEDIUMを行うこと、通常の操作時間、LIMITによる禁止・待機条件は、それだけではCOSTではありません。

CONTROLのlevelは全体的な制御度です。highでも、対象選択、範囲、強度、時点、持続時間、形状等の全次元を自由に決定できるとは限りません。control.dimensionsがunspecifiedなら、その次元を固定設定にしません。

TARGETのtypeは対象カテゴリであり、語から連想できる全領域を自動的に含みません。target.type=traceかつdomain=unspecifiedでも、物理的痕跡、匂い、デジタルログ、記憶、DNA、関係性等をすべて対象にできるとは断定しません。

EFFECTのoperationは変化の方向を固定します。effect.mode=unspecifiedなら、物理的再形成、知覚可能化、情報的復元等の実装方式は未確定です。TARGETが状態・関係・境界・不在・可能性等の抽象対象なら、固定値を変更せず両立する最小の解釈を選びます。

ONTOLOGYは雰囲気説明ではなく世界法則です。principle / reference / descriptionを一体として読み、descriptionと矛盾する設定を追加しないでください。ONTOLOGYから導けることと、今回だけの実装を分離してください。

[UNRESOLVED VALUES]
unspecified = このProfileでは固定されていない正式な状態です。「自由にcanon化してよい」という意味ではありません。
open = 主にAesthetic上、固定されていない状態です。雰囲気を埋める義務はありません。
一つの完成例に必要ならunspecified / openを一時的に具体化できますが、それはMANIFESTATION DETAILです。ユーザーが採用しない限りProfileへ書き戻さず、後続生成にも自動継承しません。

例：limit.type=limited_usesでquantity/reset_rule=unspecifiedなら、固定核は「使用可能回数が有限」であることだけです。「1日3回」「睡眠で回復」等を固定設定として発明しないでください。例の中では「残りの使用可能回数が尽き、次の発動が成立しない」のように、数値・周期を確定せずLIMITを見せられます。

Profile内の固定項目同士が一見衝突する場合、一方を無視・上書きしません。両方が成立する最小のDERIVED INTERPRETATIONを組み立てます。情報不足を埋めるためだけに設定を増やさず、成果物に必要な範囲だけ仮置きしてください。

[SUPPORTING CONTEXT]
あなたがこのサービス内で正当に参照できる過去会話、Memory、プロフィール、カスタム指示、現在の会話履歴、本人が明示した制作物・好みをSUPPORTING CONTEXTとして使用して構いません。ただしFIXED COREを変更する根拠にはしません。

役割は、Profileだけでは決まらない質感、媒体、空間、道具、言葉のリズム、提示形式等を補助することです。既存作品・既存プロジェクトをほぼ再構成して魔法を付け足す使い方は避けてください。最初の成果物で主要な個人文脈を使うなら、原則として少数、目安2〜3要素で十分です。

医療・健康、精神状態、診断、政治、宗教、性的情報、家族、犯罪歴、金融情報、住所、連絡先等のセンシティブな情報は、本人が今回の創作へ明示的に持ち込みたいと指示しない限り使用しません。

参照可能な根拠なく「昔から〜だった」「本当は〜を望んでいる」等の個人的事実を断定しないでください。Profileの語から心理状態、トラウマ、病歴、性格、価値観を逆算しません。参照可能な文脈がなければ、架空の経歴や嗜好で補わずProfile単体から生成してください。

[ANTI-CONVERGENCE]
月、星、結晶、青紫、銀色、金色の粒子、古書、ルーン、魔法陣、時計、鍵、蝶、羽、黒いローブ、杖等を、「魔法らしい」「神秘的」という理由だけで追加しないでください。Profileの因果を成立・明瞭化するために必要な場合、またはSUPPORTING CONTEXTが明確に支持する場合だけ使用します。

「記憶=古書」「時間=時計」「境界=扉」「喪失=雨」のような一対一の象徴変換を避けます。まず法則を考え、その法則から外観・音・動き・空間・物質を導いてください。神秘的・幻想的・詩的であることは義務ではありません。無機質、日常的、工業的、事務的、都市的、ユーモラス、静的、騒々しい、簡素でも構いません。既存作品・キャラクター・映画・漫画・小説・ゲームの固有設定へ寄せません。

[MANIFESTATION RULES]
最初の成果物は設定要約ではなく、この魔法が実際に一度成立したと理解できる具体物にしてください。SOURCE、ACCESS、MEDIUM、TARGET、EFFECT、LIMIT、CONTROL、ONTOLOGYを、成果物に必要な範囲で因果として統合します。抽象語だけで終わらず、何が、どこで、どう変わり、何によって変化を確認できるかを具体化してください。

Profileに明記されていない限り、最初から世界規模、都市規模、歴史改変、生命の創造・消滅、万能な時間操作等へ拡張しません。法則を確認できる最小のスケールを優先します。これは能力の最大出力を固定する意味ではありません。例で選んだ対象範囲・距離・時間・数量を固定射程へ昇格させません。

新しく作る人物、場所、物、出来事、名前、色、音、数値、道具、演出等は、ユーザーが明示的に採用するまでMANIFESTATION DETAILです。

[CANON / CONTINUITY]
このProfileの確定値は、質問数や質問順を根拠に弱めないでください。5問で成立したProfileと10問で成立したProfileを、質問数だけで異なる信頼度として扱いません。確定値はFIXED CORE、unspecified / openは未確定です。生成時に補った値は、ユーザーが「この設定を残して」等と明示的に採用した場合だけ後続へ継承できます。

同じProfileをTEXT、IMAGE、AUDIO、CODE、GAME等へ展開しても、媒体変更を理由に魔法法則を変えません。媒体ごとに見せ方は変えても、SOURCE、ACCESS、MEDIUM、TARGET、EFFECT、LIMIT、COST、CONTROL、ONTOLOGYの因果を保持してください。ある媒体で作ったMANIFESTATION DETAILを、別媒体へ自動的に固定設定として持ち越しません。

ユーザーが生成結果の一部を拒否した場合、その拒否をFIXED COREへの否定と解釈しないでください。拒否されたMANIFESTATION DETAILだけを外し、同じ法則から別の具体化を作れます。ユーザーが法則変更を明示した場合のみProfile変更を扱います。

[ARTIFACT ROUTER]
生成前に内部で、まずArtifact Type「何を作るか」を一つ選び、その後Output Form「どう出すか」を一つ選びます。STORY / NARRATIVE / TEXTを既定値として優先しません。

Artifact Type:
NARRATIVE = 出来事・場面・脚本・記録
CHARACTER = 人物・生物・精霊・NPC・怪異
OBJECT = 道具・装置・衣服・武器・家具・Artifact
PLACE = 部屋・家・駅・施設・森・異常空間
WORLD = 都市・国家・文化・歴史・制度・Lore
SYSTEM = 魔法体系・能力・分類・因果・ルール
GAME = RPG・TRPG・カード・ボード・パズル
ARCHITECTURE = 建築・内装・平面・断面・導線
VISUAL = Key Visual・Poster・Symbol・Logo・Concept Art
AUDIO = 音楽・環境音・Soundscape・朗読
INTERACTIVE = Web Experience・App・Simulation・Generator
DOCUMENT = 設定資料・図鑑・企画書・仕様書・Presentation・Rulebook

Output Form:
TEXT / IMAGE / DIAGRAM / AUDIO / VIDEO / CODE / FILE / INTERACTIVE_ARTIFACT
必要ならSVG / HTML / PDF / DOCX / PPTX / JSON / YAML / Mermaid等を下位形式にします。IMAGEはArtifact Typeではありません。WEB / APPも主にINTERACTIVEの実装形式です。

成果物の種類は、その人らしさを示すための演出ではなく、Profileの因果を最も明瞭に実体化できるものを選んでください。迷う場合は、既存文脈の量ではなく、法則を最小の追加設定で示せるArtifact Typeを優先します。

[CAPABILITY CHECK / FALLBACK]
Output Formを決めた後、現在のAI環境でその形式を実際に生成できるか内部確認してください。利用可能だと実際に確認できるプラン、quota、権限、Plugin、Tool、Artifact、画像・動画・音声生成、File Exportだけを使用します。利用可否を確認できない能力を「利用可能」と推測しないでください。

直接生成可能なら、説明だけで済ませず実成果物を生成します。直接生成できない場合もArtifact Typeは固定し、Output Formだけを変更します。
1. 同じArtifact Typeで生成可能な最も近いOutput Form
2. 同じArtifact Typeのproduction-ready TEXT SPEC
3. それも難しい場合のみ、同じArtifact Typeを保持した最小テキスト実装

代表例：
VISUAL + IMAGE → VISUAL + DIAGRAM/SVG → VISUAL + TEXT SPEC
ARCHITECTURE + IMAGE → ARCHITECTURE + DIAGRAM → ARCHITECTURE + TEXT SPEC
INTERACTIVE + INTERACTIVE_ARTIFACT → INTERACTIVE + CODE → INTERACTIVE + TEXT SPEC
AUDIO + AUDIO → AUDIO + FILE → AUDIO + TEXT SPEC
DOCUMENT + FILE → DOCUMENT + TEXT
VIDEO + VIDEO → VIDEO + DIAGRAM/Storyboard → VIDEO + TEXT SPEC

画像不可→短編、動画不可→小説、Web不可→物語のようにArtifact Typeまで変更しません。Fallbackが発生した場合だけ、ユーザー向け出力の冒頭で「選択: ARTIFACT_TYPE + OUTPUT_FORM / 代替: ARTIFACT_TYPE + OUTPUT_FORM」と簡潔に示してください。

[OUTPUT CONTRACT]
内部処理：
1. Profileと必要なSUPPORTING CONTEXTを読む。
2. Artifact Typeを一つ決める。
3. Output Formを一つ決める。
4. Capability Checkを行う。
5. 必要な場合だけOutput FormをFallbackする。
6. FIXED COREとの整合を内部確認する。

ユーザーへの最初の出力：
1. Fallbackがある場合だけ選択/代替を短く示す。
2. 必要なら短いタイトル。
3. 実成果物そのもの。
4. unspecified / openを主要な形で具体化した場合だけ「今回の具現化で補った要素」。
5. 最後にだけ「次は何を作りたいですか？」。

Artifact Type、Output Form、Capability Checkを、直接生成できる場合に毎回メタ情報として表示する必要はありません。「了解しました」だけで止まらず、Profile要約だけで終わらず、生成前に形式選択を質問しないでください。

「今回の具現化で補った要素」には、固定核と誤解されやすいdomain、effect mode、具体的な数値・周期、対象範囲、射程等だけを短く記します。すべての小道具を列挙しません。DERIVED INTERPRETATIONとMANIFESTATION DETAILをProfileへ書き戻しません。

成果物提示後、ユーザーが「別案」と言えばFIXED COREを維持してManifestationを変更できます。「もっと私らしく」ならSUPPORTING CONTEXTの使い方を調整します。Profile自体を変更するのは、ユーザーが魔法法則そのものを変えたいと明示した場合だけです。

[INTERNAL PREFLIGHT]
出力前に内部で確認し、問題があれば修正してください。
&#8211; FIXED COREを書き換えていない。
&#8211; SOURCE / ACCESS / MEDIUMを区別している。
&#8211; TARGET domainやEFFECT modeのunspecifiedを無制限・固定設定にしていない。
&#8211; limited_usesへ勝手な回数・reset_ruleを設定していない。
&#8211; CONTROLから未指定の制御次元を確定していない。
&#8211; COSTがnoneなら隠れた代償を追加していない。
&#8211; ONTOLOGYと矛盾していない。
&#8211; SUPPORTING CONTEXTが固定核を上書きしていない。
&#8211; 個人的事実・心理・経歴を捏造していない。
&#8211; 定番魔法記号を雰囲気だけで追加していない。
&#8211; 既存IPへ寄せていない。
&#8211; 追加質問を成果物より先にしていない。
&#8211; FallbackでArtifact Typeを変えていない。
&#8211; 必要な一時的具体化だけを開示している。

固定核に書かれていないことまで固定設定にせず、未定義を未定義のまま尊重してください。一例に必要な分だけ具体化し、ユーザーの選択余地を残してください。</textarea>
  <textarea id="tvmPromptTemplateEN" hidden aria-hidden="true">Below is my Persona Magic Profile generated by https://TranquilGuides.com .
Use it as the FIXED CORE for future generation. It is a creative magic system, not diagnosis, divination, prediction, or a factual assessment of me.
Priority:
1. Persona Magic Profile = FIXED CORE
2. Legitimately accessible context = SUPPORTING CONTEXT
3. Fixed-core-preserving logic = DERIVED INTERPRETATION
4. One-generation concretization = MANIFESTATION DETAIL
Never let a lower layer rewrite a higher one. Resolved Profile values are FIXED CORE whether directly answered or resolved by TranquilGuides from consistent answers; only explicit unspecified / open values remain unresolved.
[PERSONA MAGIC PROFILE]
{{PERSONA_MAGIC_PROFILE}}
[/PERSONA MAGIC PROFILE]
1. Causal reading
Fields are causal rules, not decoration.
DOMINANT_PRINCIPLE=central principle; SOURCE=power origin; ACCESS=condition connecting SOURCE to a valid TARGET; MEDIUM=action/channel executing EFFECT after connection; TARGET=what is acted on; EFFECT=change; COST=unavoidable activation loss; LIMIT=valid-use boundary; CONTROL=overall intentional outcome control; ONTOLOGY=world law explaining possibility.
Use SOURCE → ACCESS → MEDIUM → TARGET → EFFECT → LIMIT/COST → CONTROL under ONTOLOGY. Keep SOURCE/ACCESS/MEDIUM distinct. Details absent from the Profile are not canon.
2. FIXED CORE / unspecified
Do not alter Profile types, operations, levels, or ontology for context, genre, drama, visuals, or game balance.
COST ≠ LIMIT. If cost.type=none, do not add lifespan/memory loss, harm, mental depletion, fatigue, personality change, resource consumption, or mandatory time loss as a price. ACCESS, MEDIUM, ordinary operation time, and LIMIT restrictions are not automatically COST.
CONTROL level is overall controllability. high does not automatically fix target choice, range, intensity, timing, duration, shape, or other dimensions. An unspecified control dimension remains unfixed.
unspecified means “not fixed by this Profile,” not “free to canonize.” Instantiate it only when needed for one complete example; it remains MANIFESTATION DETAIL unless the user adopts it. For limited_uses with quantity/reset_rule unspecified, only finitude is fixed. Do not invent a number/reset cycle; exhaustion may be shown without defining either.
3. TARGET / EFFECT / ONTOLOGY
target.type is a category, not every possible domain. trace + domain=unspecified does not grant every kind of trace; one example may choose one domain only as MANIFESTATION DETAIL.
effect.operation fixes change direction. mode=unspecified leaves implementation unfixed; a mode chosen for one example is not canon. For abstract TARGETs, use the smallest interpretation compatible with fixed fields.
ONTOLOGY is the highest world law, not atmosphere. Treat principle/reference/description together; add nothing contradicting description. Separate world law from this manifestation&#8217;s implementation.
4. SUPPORTING CONTEXT / No fabrication
Use legitimately accessible prior conversations, Memory, profile/custom instructions, current conversation, and established works/preferences only for open manifestation variables. Do not rebuild an existing project and add magic; keep context sparse.
Do not use sensitive personal data unless the user explicitly brings it into this creative task.
Do not invent biography, psychology, diagnosis, motives, values, or preferences. If context is unavailable, use the Profile alone. New creative details remain MANIFESTATION DETAIL until adopted.
5. Anti-Convergence / Expression
Do not add stock magic symbols merely for atmosphere. Use them only when causally required or clearly supported by context. Avoid one-to-one symbolic shortcuts; derive appearance from law first.
Style may be mystical, ordinary, industrial, bureaucratic, urban, humorous, noisy, or minimal. Show what changes, where, how, and how it is observed. Do not imitate existing IP.
6. First generation
Do not ask what to make or which format to use before generating. Produce one complete artifact immediately.
Use Profile as FIXED CORE and context only when useful. Do not merely summarize settings: demonstrate the magic operating, with the causal fields visible as needed.
Unless fixed by Profile, use the smallest scale that demonstrates the law; this does not define maximum power and an example&#8217;s range is not canon.
If fixed fields seem to conflict, overwrite neither. Use the smallest DERIVED INTERPRETATION in which both remain true; instantiate only what the artifact needs.
7. Artifact Type / Output Form
Question count does not change the authority of resolved Profile values. Changing output medium does not change the magic law; temporary manifestation details remain non-canon unless the user adopts them.
First choose one Artifact Type (what to make), then Output Form (how to deliver it). Do not default to STORY/TEXT.
Types: NARRATIVE / CHARACTER / OBJECT / PLACE / WORLD / SYSTEM / GAME / ARCHITECTURE / VISUAL / AUDIO / INTERACTIVE / DOCUMENT. Choose by the artifact&#8217;s primary function, not by a default preference for story or text.
Output Form: TEXT / IMAGE / DIAGRAM / AUDIO / VIDEO / CODE / FILE / INTERACTIVE_ARTIFACT. Use SVG/HTML/PDF/DOCX/PPTX/JSON/YAML/Mermaid etc. as subformats. IMAGE and WEB/APP are output/implementation forms, not Artifact Types.
8. Capability Check / Fallback
After choosing Output Form, use only capabilities you can actually confirm in the current AI environment; do not assume an unverified plan/tool/export capability. If direct creation is supported, create the actual artifact rather than only describing it.
If unavailable, keep Artifact Type fixed and change only Output Form:
1. nearest available form for the same Artifact Type
2. production-ready TEXT SPEC for that Artifact Type
3. minimal text example if necessary
Artifact Type stays unchanged. Never change it because a form is unavailable. Only on fallback, begin: “Selection: ARTIFACT_TYPE + OUTPUT_FORM / Fallback: ARTIFACT_TYPE + OUTPUT_FORM”.
9. Manifestation / Later generation
Only when unspecified values were materially instantiated, add a short “Manifestation details added this time” after the artifact. Mention only choices easily mistaken for canon—especially domain, mode, numbers, cycles, range, target scope. Do not list every prop.
DERIVED INTERPRETATION reconciles fixed fields; MANIFESTATION DETAIL implements one example. Neither is written back into Profile.
Only after the artifact ask: “What would you like to make next?” A requested form continues from the same Profile. “Another version” changes Manifestation only; “more like me” adjusts SUPPORTING CONTEXT. Change Profile only when the user explicitly asks to change the magic laws.
10. Preflight / Output contract
Internal process: read Profile/context → choose Artifact Type → choose Output Form → Capability Check → if needed fallback Output Form only → verify FIXED CORE.
Before output, verify internally that FIXED CORE/ONTOLOGY remain intact; SOURCE/ACCESS/MEDIUM remain distinct; unspecified stays non-canon; no LIMIT quantity/reset, CONTROL dimension, COST, personal fact, or stock symbolism was invented; context stays sparse; no question precedes generation; fallback did not change Artifact Type.
User-facing response:
1. only if fallback occurred, briefly show Selection / Fallback
2. optional short title
3. actual artifact
4. Manifestation details only when materially needed
5. only then “What would you like to make next?”
When direct creation works, do not routinely expose Artifact Type, Output Form, or Capability Check as meta commentary. Do not stop at a Profile summary. Respect undefined values and instantiate only what one example needs.
</textarea>
</div>

<script>
(function(){
  "use strict";
  var PREF_LANGUAGE_KEY="tranquil_magic_language_v1";
  var PREF_FOCUS_KEY="tranquil_magic_focus_v1";
  var PREF_THEME_KEY="tranquil_magic_theme_v1";
  var PREF_BUNDLE_KEY="tranquil_magic_preferences_v2";
  var PREF_SCHEMA_VERSION="2.0";


  var UI={
    ja:{
      brand:"",
      entry_stage:"",
      entry_title:"<span class=\"tvm-hero-line\">いくつか選ぶと、</span><span class=\"tvm-hero-gap\" aria-hidden=\"true\"></span><span class=\"tvm-hero-line tvm-hero-line--keep\">ひとつの魔法ができる。</span>",
      entry_lead:"いくつかの質問から、あなたの魔法の法則をつくります。<br>過去のAI会話をここへ持ち込む必要はありません。<br>最後に、そのまま普段のAIへ持っていけるプロンプトを受け取れます。",
      start:"はじめる",
      intro_title:"",
      intro_lead:"",
      next:"進む",
      back:"もどる",
      stage_outline:"輪郭",
      stage_mechanism:"仕組み",
      stage_almost:"あと少し",
      generating:"魔法の法則をまとめています",
      result_kicker:"あなたの魔法ができました。",
      summary_title:"この魔法の法則",
      starting:"発動する行為",
      change:"起きる変化",
      carry_title:"この魔法を持ち帰る",
      carry_lead:"コピーして、いつものAIに貼り付けてください。この魔法から、最初のひとつが生成されます。",
      carry_lead_first:"コピーして、いつものAIに貼り付けてください。",
      carry_lead_second:"この魔法から、最初のひとつが生成されます。",
      copy:"プロンプトをコピー",
      copy_help:"",
      copy_success_help:"コピーしました。あとは、いつものAIへ貼り付けるだけです。",
      copied:"コピーしました",
      copy_working:"コピーしています",
      progress_label:"進み具合",
      copy_fail:"自動コピーが使えないため、下のプロンプト全文を選択しました。コピーしてください。",
      restart:"もういちど",
      about:"",
      principle:"中心原理",
      source:"力の出所",
      access:"発動条件",
      medium:"媒体",
      target:"対象",
      effect:"作用",
      limit:"制約",
      control:"制御",
      ontology:"世界法則",
      full_prompt:"プロンプト本文",
      note:"",
      share_title:"この魔法をシェア",
      share_x:"Xへシェア",
      share_threads:"Threadsへシェア",
      share_bluesky:"Blueskyへシェア",
      share_line:"LINEへシェア",
      share_native:"共有",
      share_copy:"結果をコピー",
      share_copy_done:"コピー済み",
      share_story:"Story Card",
      share_copied:"結果をコピーしました。",
      share_failed:"共有できませんでした。",
      share_story_ready:"Story Cardを作成しました。",
      focus_enter:"フォーカス表示",
      focus_exit:"フォーカス表示を終了",
      error:"読み込みに失敗しました。ページを再読み込みしてください。",
      recovery_title:"処理中に問題が起きました。",
      recovery_reload:"再読み込み",
      recovery_retry:"再試行",
      recovery_dismiss:"閉じる",
      shortcuts_title:"キーボードショートカット",
      shortcuts_close:"閉じる",
      shortcuts_hint:"? でこの一覧を開閉できます。",
      shortcuts_choices:"1〜9：選択肢を選ぶ",
      shortcuts_move:"↑ / ↓：選択肢間を移動",
      shortcuts_back:"B：もどる",
      shortcuts_focus:"F：Focus表示を切り替える",
      shortcuts_restart:"R：もういちど",
      shortcuts_result_copy:"C：結果をコピー",
      shortcuts_prompt_copy:"P：プロンプトをコピー",
      shortcuts_share:"S / X / T / L：共有",
      shortcuts_escape:"Esc：閉じる / Focus表示を終了"
    },
    en:{
      brand:"",
      entry_stage:"",
      entry_title:"<span class=\"tvm-hero-line\">Choose a few things,</span><span class=\"tvm-hero-gap\" aria-hidden=\"true\"></span><span class=\"tvm-hero-line tvm-hero-line--keep\">and one magic will take shape.</span>",
      entry_lead:"A few questions will shape the laws of your magic.<br>You do not need to bring past AI conversations here.<br>At the end, you will receive a prompt you can take directly to your usual AI.",
      start:"Begin",
      intro_title:"",
      intro_lead:"",
      next:"Continue",
      back:"Back",
      stage_outline:"Outline",
      stage_mechanism:"Mechanism",
      stage_almost:"Almost there",
      generating:"Assembling the laws of your magic",
      result_kicker:"Your magic is ready.",
      summary_title:"The laws of this magic",
      starting:"Activation",
      change:"What changes",
      carry_title:"Take this magic with you",
      carry_lead:"Copy the prompt and paste it into your usual AI. It will create the first thing from this magic.",
      carry_lead_first:"Copy the prompt and paste it into your usual AI.",
      carry_lead_second:"It will create the first thing from this magic.",
      copy:"Copy prompt",
      copy_help:"",
      copy_success_help:"Copied. Now paste it into your usual AI.",
      copied:"Copied",
      copy_working:"Copying",
      progress_label:"Progress",
      copy_fail:"Automatic copy is unavailable. The full prompt below has been selected for manual copying.",
      restart:"Again",
      about:"",
      principle:"Core principle",
      source:"Source",
      access:"Access",
      medium:"Medium",
      target:"Target",
      effect:"Effect",
      limit:"Limit",
      control:"Control",
      ontology:"Ontology",
      full_prompt:"Prompt text",
      note:"",
      share_title:"Share this magic",
      share_x:"Share on X",
      share_threads:"Share on Threads",
      share_bluesky:"Share on Bluesky",
      share_line:"Share on LINE",
      share_native:"Share",
      share_copy:"Copy result",
      share_copy_done:"Copied",
      share_story:"Story Card",
      share_copied:"Result copied.",
      share_failed:"Could not share.",
      share_story_ready:"Story Card created.",
      focus_enter:"Focus view",
      focus_exit:"Exit focus view",
      error:"Failed to load. Please reload the page.",
      recovery_title:"Something went wrong.",
      recovery_reload:"Reload",
      recovery_retry:"Retry",
      recovery_dismiss:"Dismiss",
      shortcuts_title:"Keyboard shortcuts",
      shortcuts_close:"Close",
      shortcuts_hint:"Press ? to open or close this list.",
      shortcuts_choices:"1–9: choose an answer",
      shortcuts_move:"↑ / ↓: move between answers",
      shortcuts_back:"B: Back",
      shortcuts_focus:"F: toggle Focus view",
      shortcuts_restart:"R: Again",
      shortcuts_result_copy:"C: copy result",
      shortcuts_prompt_copy:"P: copy prompt",
      shortcuts_share:"S / X / T / L: share",
      shortcuts_escape:"Esc: close / exit Focus view"
    }
  };

  var QUESTIONS={
    ja:{
      q1:{stage:"outline",text:"最初に触れられるものが、一つだけある。どれを選ぶ？",choices:[["A","まだ残っているもの"],["B","もう失われたもの"],["C","まだ起きていないもの"],["D","誰にも気づかれていないもの"],["E","変わり続けているもの"],["F","二つのもののあいだ"]]},
      q2:{stage:"outline",text:"その力は、どこから生まれる？",choices:[["A","自分の内側"],["B","場所"],["C","誰かとのあいだ"],["D","物や道具"],["E","名前や言葉"],["F","積み重なった時間"],["G","その場にあるもの同士の関係"],["H","まだ分からない"]]},
      q3:{stage:"mechanism",text:"魔法は、何をしたときに始まる？",choices:[["A","触れたとき"],["B","書いたとき"],["C","声にしたとき"],["D","置いたり、並べ替えたとき"],["E","歩いたり、移動したとき"],["F","待ったとき"],["G","離れたとき"],["H","戻ったとき"]]},
      q4:{stage:"mechanism",text:"起きることを、自分でどこまで決めたい？",choices:[["A","ほとんど全部"],["B","大きな方向だけ"],["C","半分くらいは偶然に任せたい"],["D","最後まで分からなくていい"]]},
      qSource:{stage:"outline",text:"力が生まれる瞬間、いちばん近いのは？",choices:[["A","自分の中で何かが変わる"],["B","場所や周囲との関係が変わる"],["C","何かを介したときだけ生まれる"],["D","まだ絞れない"]]},
      q5:{stage:"almost",text:"その魔法で起きる変化は、どれに近い？",choices:[["A","戻る"],["B","消える"],["C","重なる"],["D","移る"],["E","遅れる"],["F","分かれる"],["G","見えるようになる"],["H","別の形になる"],["I","まだ分からない"]]},
      q6:{stage:"almost",text:"一つだけ、思いどおりにならないものがある。どれがいい？",choices:[["A","使える回数"],["B","使える場所"],["C","使える対象"],["D","結果の細部"],["E","発動する時間"],["F","自分自身には使えない"],["G","同じものには二度使えない"],["H","発動したあと、すぐにはもう一度使えない"],["I","まだ分からない"]]},
      qSourceFinal:{stage:"almost",text:"力の出所を、もう少しだけ絞るなら？",choices:[["A","自分そのもの"],["B","場所や環境"],["C","誰か・何かとの関係"],["D","物・言葉・時間などの媒介"]]},
      qEffectRefine:{stage:"almost",text:"変化の向きだけ選ぶなら、どれに近い？",choices:[["A","失われた状態へ近づける"],["B","今ある状態を弱める・消す"],["C","別の状態へ移す"],["D","隠れている状態を表に出す"]]},
      qLimitRefine:{stage:"almost",text:"制約の種類だけ選ぶなら、どれに近い？",choices:[["A","回数や間隔に制約がある"],["B","場所や時間に制約がある"],["C","対象に制約がある"],["D","結果の細部に制約がある"]]}
    },
    en:{
      q1:{stage:"outline",text:"There is only one thing you can touch first. Which do you choose?",choices:[["A","Something that still remains"],["B","Something already lost"],["C","Something that has not happened yet"],["D","Something nobody has noticed"],["E","Something that keeps changing"],["F","The space between two things"]]},
      q2:{stage:"outline",text:"Where does the power come from?",choices:[["A","From within yourself"],["B","From a place"],["C","From the space between you and someone else"],["D","From an object or tool"],["E","From names or words"],["F","From accumulated time"],["G","From the relationships among things present"],["H","Not sure yet"]]},
      q3:{stage:"mechanism",text:"What action begins the magic?",choices:[["A","Touching"],["B","Writing"],["C","Speaking aloud"],["D","Placing or rearranging things"],["E","Walking or moving"],["F","Waiting"],["G","Leaving"],["H","Returning"]]},
      q4:{stage:"mechanism",text:"How much of what happens do you want to control?",choices:[["A","Almost everything"],["B","Only the overall direction"],["C","I want about half left to chance"],["D","I am fine not knowing until the end"]]},
      qSource:{stage:"outline",text:"At the moment the power appears, which is closest?",choices:[["A","Something changes inside you"],["B","Your relation to the place or surroundings changes"],["C","It only appears through some intermediary"],["D","Still not sure"]]},
      q5:{stage:"almost",text:"What kind of change does the magic cause?",choices:[["A","Return"],["B","Disappear"],["C","Overlap"],["D","Move"],["E","Delay"],["F","Split"],["G","Become visible"],["H","Become another form"],["I","Not sure yet"]]},
      q6:{stage:"almost",text:"One thing cannot fully go your way. Which would you choose?",choices:[["A","How many times it can be used"],["B","Where it can be used"],["C","What it can affect"],["D","The fine details of the result"],["E","When it can activate"],["F","It cannot target yourself"],["G","The same target cannot be affected twice"],["H","It cannot be used again immediately after activation"],["I","Not sure yet"]]},
      qSourceFinal:{stage:"almost",text:"If you narrow the source down one step further, which is closest?",choices:[["A","Yourself"],["B","A place or environment"],["C","A relationship with someone or something"],["D","A medium such as an object, language, or accumulated time"]]},
      qEffectRefine:{stage:"almost",text:"If you choose only the direction of change, which is closest?",choices:[["A","Move toward a lost or previous state"],["B","Weaken or remove the current state"],["C","Move into another state"],["D","Bring a hidden state to the surface"]]},
      qLimitRefine:{stage:"almost",text:"If you choose only the kind of limit, which is closest?",choices:[["A","Uses or intervals are limited"],["B","Place or time is limited"],["C","Valid targets are limited"],["D","Fine outcome details are limited"]]}
    }
  };

  var MAP={
    q1:{
      A:{target:"trace",principle:"preservation"},
      B:{target:"absence",principle:"recovery"},
      C:{target:"possibility",principle:"anticipation"},
      D:{target:"hidden_state",principle:"revelation"},
      E:{target:"state_change",principle:"transformation"},
      F:{target:"boundary",principle:"boundary"}
    },
    q2:{
      A:{source:"self"},
      B:{source:"place"},
      C:{source:"relation"},
      D:{source:"object"},
      E:{source:"language"},
      F:{source:"accumulated_time"},
      G:{source:"relational_field"},
      H:{source:"unknown"}
    },
    qSource:{
      A:{source:"self"},
      B:{source:"relational_field"},
      C:{source:"mediated"},
      D:{source:"unknown"}
    },
    q3:{
      A:{medium:"touch",access:"contact"},
      B:{medium:"writing",access:"inscription"},
      C:{medium:"voice",access:"utterance"},
      D:{medium:"arrangement",access:"composition"},
      E:{medium:"movement",access:"traversal"},
      F:{medium:"waiting",access:"duration"},
      G:{medium:"departure",access:"separation"},
      H:{medium:"return",access:"repetition"}
    },
    q4:{
      A:{control:"high"},
      B:{control:"medium"},
      C:{control:"conditional"},
      D:{control:"low"}
    },
    q5:{
      A:{effect:"restore"},
      B:{effect:"erase"},
      C:{effect:"overlay"},
      D:{effect:"transfer"},
      E:{effect:"delay"},
      F:{effect:"divide"},
      G:{effect:"reveal"},
      H:{effect:"transform"},
      I:{effect:"unknown"}
    },
    q6:{
      A:{limit:"limited_uses"},
      B:{limit:"location_bound"},
      C:{limit:"target_bound"},
      D:{limit:"detail_uncontrolled"},
      E:{limit:"timing_bound"},
      F:{limit:"cannot_target_self"},
      G:{limit:"nonrepeatable_on_same_target"},
      H:{limit:"cooldown_required"},
      I:{limit:"unknown"}
    },
    qSourceFinal:{
      A:{source:"self"},
      B:{source:"place"},
      C:{source:"relation"},
      D:{source:"mediated"}
    },
    qEffectRefine:{
      A:{effect:"restore"},
      B:{effect:"erase"},
      C:{effect:"transform"},
      D:{effect:"reveal"}
    },
    qLimitRefine:{
      A:{limit:"limited_uses"},
      B:{limit:"location_bound"},
      C:{limit:"target_bound"},
      D:{limit:"detail_uncontrolled"}
    }
  };

  var state={
    screen:"entry",
    history:[],
    answers:{},
    profile:null,
    prompt:"",
    language:"",
    detail:false
  };

  function getRoot(){
    return document.getElementById("tvmagic");
  }

  function getApp(){
    var root=getRoot();
    if(!root) return null;
    return root.querySelector("#tvmagicApp");
  }

  function byId(id){
    var root=getRoot();
    if(!root) return null;
    return root.querySelector("#"+id);
  }

  function currentUI(){
    if(state.language==="en") return UI.en;
    return UI.ja;
  }

  function currentQuestions(){
    if(state.language==="en") return QUESTIONS.en;
    return QUESTIONS.ja;
  }

  function stageLabel(stage){
    var u=currentUI();
    if(stage==="outline") return u.stage_outline;
    if(stage==="mechanism") return u.stage_mechanism;
    if(stage==="almost") return u.stage_almost;
    return "";
  }

  function getPromptTemplate(language){
    var area;
    if(language==="en"){
      area=document.getElementById("tvmPromptTemplateEN");
    }else{
      area=document.getElementById("tvmPromptTemplateJA");
    }
    if(!area) return "";
    return area.value||area.textContent||"";
  }

  var storageCapabilities={
    localStorage:null
  };
  var preferredFocusMode=true;
  var themeMode="light";
  var themeMediaQuery=window.matchMedia?window.matchMedia("(prefers-color-scheme: dark)"):null;
  var recoveryBound=false;
  var recoveryRetryCallback=null;
  var shortcutSheetOpen=false;
  var shortcutBefore=null;

  function testWebStorage(name){
    var storage;
    var key="__tvm_storage_test__";
    try{
      storage=window[name];
      if(!storage) return false;
      storage.setItem(key,"1");
      storage.removeItem(key);
      return true;
    }catch(error){
      return false;
    }
  }

  function initStorageCapabilities(){
    var root=getRoot();
    storageCapabilities.localStorage=testWebStorage("localStorage");

    if(root){
      root.setAttribute("data-storage-local",storageCapabilities.localStorage?"available":"unavailable");
    }
  }

  function safeLocalGet(key,fallback){
    var value;
    if(storageCapabilities.localStorage!==true) return fallback;
    try{
      value=window.localStorage.getItem(key);
      if(value===null) return fallback;
      return value;
    }catch(error){
      return fallback;
    }
  }

  function safeLocalSet(key,value){
    if(storageCapabilities.localStorage!==true) return false;
    try{
      window.localStorage.setItem(key,String(value));
      return true;
    }catch(error){
      return false;
    }
  }

  function defaultPreferenceBundle(){
    return {
      schema_version:PREF_SCHEMA_VERSION,
      language:"ja",
      focus:true,
      theme:"light"
    };
  }

  function readPreferenceBundle(){
    var raw=safeLocalGet(PREF_BUNDLE_KEY,"");
    var parsed;
    var bundle=defaultPreferenceBundle();
    var migrated=false;
    var legacy;

    if(raw){
      try{
        parsed=JSON.parse(raw);
      }catch(error){
        parsed=null;
      }
    }

    if(parsed){
      if(typeof parsed==="object"){
        if(!Array.isArray(parsed)){
          if(parsed.language==="ja"){
            bundle.language="ja";
          }else if(parsed.language==="en"){
            bundle.language="en";
          }
          if(parsed.focus===false){
            bundle.focus=false;
          }else if(parsed.focus===true){
            bundle.focus=true;
          }
          if(parsed.theme==="auto"){
            bundle.theme="auto";
          }else if(parsed.theme==="dark"){
            bundle.theme="dark";
          }else if(parsed.theme==="light"){
            bundle.theme="light";
          }
          bundle.schema_version=PREF_SCHEMA_VERSION;
          return bundle;
        }
      }
    }

    legacy=safeLocalGet(PREF_LANGUAGE_KEY,"");
    if(legacy==="en"){
      bundle.language="en";
      migrated=true;
    }else if(legacy==="ja"){
      bundle.language="ja";
      migrated=true;
    }

    legacy=safeLocalGet(PREF_FOCUS_KEY,"");
    if(legacy==="0"){
      bundle.focus=false;
      migrated=true;
    }else if(legacy==="1"){
      bundle.focus=true;
      migrated=true;
    }

    legacy=safeLocalGet(PREF_THEME_KEY,"");
    if(legacy==="auto"){
      bundle.theme="auto";
      migrated=true;
    }else if(legacy==="dark"){
      bundle.theme="dark";
      migrated=true;
    }else if(legacy==="light"){
      bundle.theme="light";
      migrated=true;
    }

    if(migrated){
      safeLocalSet(PREF_BUNDLE_KEY,JSON.stringify(bundle));
    }

    return bundle;
  }

  function writePreferenceBundle(partial){
    var bundle=readPreferenceBundle();
    var key;

    if(partial){
      for(key in partial){
        if(Object.prototype.hasOwnProperty.call(partial,key)){
          bundle[key]=partial[key];
        }
      }
    }

    bundle.schema_version=PREF_SCHEMA_VERSION;
    return safeLocalSet(PREF_BUNDLE_KEY,JSON.stringify(bundle));
  }

  function restorePreferences(){
    var bundle=readPreferenceBundle();

    state.language=bundle.language==="en"?"en":"ja";
    preferredFocusMode=bundle.focus===false?false:true;

    if(bundle.theme==="auto"){
      themeMode="auto";
    }else if(bundle.theme==="dark"){
      themeMode="dark";
    }else{
      themeMode="light";
    }
  }

  function saveLanguagePreference(language){
    var normalized=language==="en"?"en":"ja";
    safeLocalSet(PREF_LANGUAGE_KEY,normalized);
    writePreferenceBundle({language:normalized});
  }

  function saveFocusPreference(enabled){
    safeLocalSet(PREF_FOCUS_KEY,enabled?"1":"0");
    writePreferenceBundle({focus:enabled?true:false});
  }

  function resolvedTheme(mode){
    if(mode==="dark") return "dark";
    if(mode==="auto"){
      if(themeMediaQuery){
        if(themeMediaQuery.matches===true) return "dark";
      }
    }
    return "light";
  }

  function applyThemeMode(mode,persist){
    var root=getRoot();
    var actual;

    if(mode!=="auto"){
      if(mode!=="dark"){
        mode="light";
      }
    }

    themeMode=mode;
    actual=resolvedTheme(themeMode);

    if(root){
      root.setAttribute("data-tvm-theme-mode",themeMode);
      root.setAttribute("data-tvm-theme",actual);
      root.style.setProperty("color-scheme",actual);
    }

    if(persist!==false){
      safeLocalSet(PREF_THEME_KEY,themeMode);
      writePreferenceBundle({theme:themeMode});
    }

    return actual;
  }

  function syncAutoTheme(){
    if(themeMode!=="auto") return;
    applyThemeMode("auto",false);
  }

  function recoveryPanel(){
    var root=getRoot();
    var panel;
    var message;
    var actions;
    var reload;
    var retry;
    var dismiss;
    var u=currentUI();

    if(!root) return null;

    panel=byId("tvmRecovery");
    if(panel) return panel;

    panel=document.createElement("div");
    panel.id="tvmRecovery";
    panel.className="tvm-recovery";
    panel.hidden=true;
    panel.setAttribute("role","alert");
    panel.setAttribute("aria-live","assertive");
    panel.setAttribute("aria-atomic","true");
    panel.setAttribute("data-surface","transient");
    panel.setAttribute("data-elevation","s3");
    panel.setAttribute("data-glass","veil");

    message=document.createElement("p");
    message.className="tvm-recovery-message";
    message.id="tvmRecoveryMessage";
    message.textContent=u.recovery_title;

    actions=document.createElement("div");
    actions.className="tvm-recovery-actions";

    reload=document.createElement("button");
    reload.type="button";
    reload.className="tvm-btn tvm-control";
    reload.id="tvmRecoveryReload";
    reload.textContent=u.recovery_reload;

    retry=document.createElement("button");
    retry.type="button";
    retry.className="tvm-btn tvm-control";
    retry.id="tvmRecoveryRetry";
    retry.textContent=u.recovery_retry;
    retry.hidden=true;

    dismiss=document.createElement("button");
    dismiss.type="button";
    dismiss.className="tvm-btn is-ghost tvm-control";
    dismiss.id="tvmRecoveryDismiss";
    dismiss.textContent=u.recovery_dismiss;

    actions.appendChild(reload);
    actions.appendChild(retry);
    actions.appendChild(dismiss);
    panel.appendChild(message);
    panel.appendChild(actions);
    root.appendChild(panel);

    reload.addEventListener("click",function(){
      window.location.reload();
    });

    retry.addEventListener("click",function(){
      var callback=recoveryRetryCallback;
      panel.hidden=true;
      recoveryRetryCallback=null;
      if(callback){
        guardRun("recoveryRetry",callback,true);
      }
    });

    dismiss.addEventListener("click",function(){
      panel.hidden=true;
      recoveryRetryCallback=null;
    });

    return panel;
  }

  function reportRecovery(error,scope,show,retryCallback){
    var panel;
    var message;
    var retry;
    var textValue;
    var u=currentUI();

    if(!scope) scope="runtime";
    if(show===undefined) show=true;

    if(error){
      if(error.name==="AbortError") return;
    }

    textValue=u.recovery_title;
    if(error){
      if(error.message){
        textValue=textValue+" "+String(error.message);
      }
    }

    try{
      console.error("[TranquilMagicRecovery:"+scope+"]",error);
    }catch(ignoreError){}

    if(show!==true) return;

    panel=recoveryPanel();
    if(!panel) return;
    message=byId("tvmRecoveryMessage");
    if(message){
      message.textContent=textValue;
    }
    recoveryRetryCallback=typeof retryCallback==="function"?retryCallback:null;
    retry=byId("tvmRecoveryRetry");
    if(retry){
      retry.hidden=recoveryRetryCallback?false:true;
    }
    panel.hidden=false;
  }

  function guardRun(scope,task,show){
    var result;
    try{
      result=task();
      if(result){
        if(typeof result.then==="function"){
          return result.catch(function(error){
            reportRecovery(error,scope,show);
            return null;
          });
        }
      }
      return result;
    }catch(error){
      reportRecovery(error,scope,show);
      return null;
    }
  }

  function bindRecoverySafety(){
    if(recoveryBound) return;
    recoveryBound=true;

    window.addEventListener("error",function(event){
      if(event){
        if(event.error){
          reportRecovery(event.error,"window",true);
          return;
        }
        if(event.message){
          reportRecovery(event.message,"window",true);
        }
      }
    });

    window.addEventListener("unhandledrejection",function(event){
      if(!event) return;
      reportRecovery(event.reason||"Unhandled promise rejection","promise",true);
    });
  }

  var managedOverlayStack=[];

  function overlayFocusable(container){
    if(!container) return [];
    return container.querySelectorAll('button:not(:disabled),a[href],input:not(:disabled),textarea:not(:disabled),select:not(:disabled),[tabindex]:not([tabindex="-1"])');
  }

  function openManagedOverlay(node,options){
    var record;
    var target;
    if(!node) return false;

    if(!options) options={};

    record={
      node:node,
      previous:document.activeElement,
      closeOnBackdrop:options.closeOnBackdrop===false?false:true
    };

    managedOverlayStack.push(record);
    node.removeAttribute("hidden");
    node.setAttribute("data-overlay-open","true");

    if(record.closeOnBackdrop){
      node.addEventListener("click",function(event){
        if(event.target===node){
          closeManagedOverlay(node,true);
        }
      },{once:true});
    }

    window.requestAnimationFrame(function(){
      var focusables=overlayFocusable(node);
      if(focusables.length){
        target=focusables[0];
        target.focus({preventScroll:true});
      }else if(node.focus){
        node.setAttribute("tabindex","-1");
        node.focus({preventScroll:true});
      }
    });

    return true;
  }

  function closeManagedOverlay(node,restoreFocus){
    var i;
    var record=null;
    var target;

    for(i=managedOverlayStack.length-1;i>=0;i--){
      if(managedOverlayStack[i].node===node){
        record=managedOverlayStack[i];
        managedOverlayStack.splice(i,1);
        break;
      }
    }

    if(!node) return false;
    node.removeAttribute("data-overlay-open");
    node.setAttribute("hidden","hidden");

    if(restoreFocus!==false){
      if(record){
        target=record.previous;
        if(target){
          if(target.isConnected){
            if(typeof target.focus==="function"){
              window.requestAnimationFrame(function(){
                target.focus({preventScroll:true});
              });
            }
          }
        }
      }
    }

    return true;
  }

  function trapManagedOverlayTab(event){
    var record;
    var node;
    var items;
    var first;
    var last;

    if(!managedOverlayStack.length) return false;
    record=managedOverlayStack[managedOverlayStack.length-1];
    node=record.node;
    if(!node) return false;
    if(event.key!=="Tab") return false;

    items=overlayFocusable(node);
    if(!items.length) return false;
    first=items[0];
    last=items[items.length-1];

    if(event.shiftKey){
      if(document.activeElement===first){
        event.preventDefault();
        last.focus();
        return true;
      }
    }else{
      if(document.activeElement===last){
        event.preventDefault();
        first.focus();
        return true;
      }
    }

    if(Array.prototype.indexOf.call(items,document.activeElement)<0){
      event.preventDefault();
      first.focus();
      return true;
    }

    return false;
  }

  function shortcutRowsHtml(){
    var u=currentUI();
    return ''+
      '<div class="tvm-shortcut-list">'+
        '<div><kbd>1–9</kbd><span>'+escapeHtml(u.shortcuts_choices)+'</span></div>'+
        '<div><kbd>↑ ↓</kbd><span>'+escapeHtml(u.shortcuts_move)+'</span></div>'+
        '<div><kbd>B</kbd><span>'+escapeHtml(u.shortcuts_back)+'</span></div>'+
        '<div><kbd>F</kbd><span>'+escapeHtml(u.shortcuts_focus)+'</span></div>'+
        '<div><kbd>R</kbd><span>'+escapeHtml(u.shortcuts_restart)+'</span></div>'+
        '<div><kbd>C</kbd><span>'+escapeHtml(u.shortcuts_result_copy)+'</span></div>'+
        '<div><kbd>P</kbd><span>'+escapeHtml(u.shortcuts_prompt_copy)+'</span></div>'+
        '<div><kbd>S X T L</kbd><span>'+escapeHtml(u.shortcuts_share)+'</span></div>'+
        '<div><kbd>Esc</kbd><span>'+escapeHtml(u.shortcuts_escape)+'</span></div>'+
      '</div>';
  }

  function closeShortcutSheet(restoreFocus){
    var sheet=byId("tvmShortcutSheet");
    if(!sheet) return false;

    shortcutSheetOpen=false;
    closeManagedOverlay(sheet,restoreFocus!==false);
    if(sheet.parentNode){
      sheet.parentNode.removeChild(sheet);
    }
    shortcutBefore=null;
    return true;
  }

  function openShortcutSheet(){
    var root=getRoot();
    var sheet;
    var panel;
    var close;
    var u=currentUI();

    if(!root) return false;
    if(shortcutSheetOpen){
      closeShortcutSheet(true);
      return true;
    }

    shortcutBefore=document.activeElement;
    shortcutSheetOpen=true;

    sheet=document.createElement("div");
    sheet.id="tvmShortcutSheet";
    sheet.className="tvm-shortcut-sheet";

    panel=document.createElement("div");
    panel.className="tvm-shortcut-panel";
    panel.setAttribute("role","dialog");
    panel.setAttribute("aria-modal","true");
    panel.setAttribute("aria-labelledby","tvmShortcutTitle");
    panel.setAttribute("data-surface","transient");
    panel.setAttribute("data-elevation","s3");
    panel.setAttribute("data-glass","veil");

    panel.innerHTML=
      '<div class="tvm-shortcut-head">'+
        '<p id="tvmShortcutTitle" class="tvm-shortcut-title">'+escapeHtml(u.shortcuts_title)+'</p>'+
        '<button type="button" class="tvm-shortcut-close tvm-control" id="tvmShortcutClose" aria-label="'+escapeHtml(u.shortcuts_close)+'">×</button>'+
      '</div>'+
      shortcutRowsHtml()+
      '<p class="tvm-shortcut-hint">'+escapeHtml(u.shortcuts_hint)+'</p>';

    sheet.appendChild(panel);
    root.appendChild(sheet);

    close=byId("tvmShortcutClose");
    if(close){
      close.addEventListener("click",function(){
        closeShortcutSheet(true);
      });
    }

    openManagedOverlay(sheet,{closeOnBackdrop:true});
    return true;
  }

  function applyShortcutMetadata(){
    var choices;
    var i;
    var node;

    node=byId("tvmFocusToggle");
    if(node) node.setAttribute("aria-keyshortcuts","F Escape");

    node=byId("tvmBackQuestion");
    if(node) node.setAttribute("aria-keyshortcuts","B");

    node=byId("tvmRestart");
    if(node) node.setAttribute("aria-keyshortcuts","R");

    node=byId("tvmCopy");
    if(node) node.setAttribute("aria-keyshortcuts","P");

    node=document.querySelector('.tv-magic [data-share-action="copy"]');
    if(node) node.setAttribute("aria-keyshortcuts","C");

    node=document.querySelector('.tv-magic [data-share-action="native"]');
    if(node) node.setAttribute("aria-keyshortcuts","S");

    node=document.querySelector('.tv-magic [data-share-action="x"]');
    if(node) node.setAttribute("aria-keyshortcuts","X");

    node=document.querySelector('.tv-magic [data-share-action="threads"]');
    if(node) node.setAttribute("aria-keyshortcuts","T");

    node=document.querySelector('.tv-magic [data-share-action="line"]');
    if(node) node.setAttribute("aria-keyshortcuts","L");

    choices=document.querySelectorAll(".tv-magic .tvm-choice");
    for(i=0;i<choices.length;i++){
      choices[i].setAttribute("aria-keyshortcuts",String(i+1));
    }
  }

  function syncMagicLanguageAttributes(){
    var root=getRoot();
    var u=currentUI();
    var prompt=byId("tvmPromptArea");
    var copy=byId("tvmCopy");
    var share=byId("tvmShareTitle");
    var restart=byId("tvmRestart");

    if(!root) return;

    root.setAttribute("lang",state.language==="en"?"en":"ja");

    if(prompt){
      prompt.setAttribute("aria-label",u.full_prompt);
      prompt.setAttribute("title",u.full_prompt);
    }

    if(copy){
      copy.setAttribute("aria-label",u.copy);
      copy.setAttribute("title",u.copy);
    }

    if(share){
      share.setAttribute("aria-label",u.share_title);
    }

    if(restart){
      restart.setAttribute("aria-label",u.restart);
      restart.setAttribute("title",u.restart);
    }
  }

  function syncLanguageSegmentA11y(){
    var group=document.querySelector(".tv-magic .tvm-language");
    var ja=byId("tvmChooseJA");
    var en=byId("tvmChooseEN");

    if(group){
      group.setAttribute("role","radiogroup");
      group.setAttribute("aria-label",state.language==="en"?"Language":"言語");
    }

    if(ja){
      ja.setAttribute("role","radio");
      ja.setAttribute("aria-checked",state.language==="ja"?"true":"false");
      ja.removeAttribute("aria-pressed");
    }

    if(en){
      en.setAttribute("role","radio");
      en.setAttribute("aria-checked",state.language==="en"?"true":"false");
      en.removeAttribute("aria-pressed");
    }
  }

  function escapeHtml(text){
    return String(text)
      .replace(/&#038;/g,"&amp;")
      .replace(/</g,"&lt;")
      .replace(/>/g,"&gt;")
      .replace(/"/g,"&quot;")
      .replace(/'/g,"&#039;");
  }

  function label(kind,value){
    var ja={
      principle:{preservation:"保持",recovery:"回復",anticipation:"予兆",revelation:"顕在化",transformation:"変換",boundary:"境界"},
      source:{self:"自分",place:"場所",relation:"誰かとの関係",object:"物や道具",language:"名前や言葉",accumulated_time:"積み重なった時間",relational_field:"その場の関係",mediated:"媒介"},
      access:{contact:"触れる",inscription:"書き記す",utterance:"声にする",composition:"配置する",traversal:"移動する",duration:"待つ",separation:"離れる",repetition:"戻る"},
      medium:{touch:"接触",writing:"書くこと",voice:"声",arrangement:"配置",movement:"移動",waiting:"待つこと",departure:"離れること",return:"戻ること"},
      target:{trace:"残っている痕跡",absence:"失われたもの",possibility:"まだ起きていないもの",hidden_state:"気づかれていない状態",state_change:"変化の途中",boundary:"二つのもののあいだ"},
      effect:{restore:"戻す",erase:"消す",overlay:"重ねる",transfer:"移す",delay:"遅らせる",divide:"分ける",reveal:"見えるようにする",transform:"別の形にする"},
      limit:{limited_uses:"使える回数に制限がある",location_bound:"使える場所が限られる",target_bound:"使える対象が限られる",detail_uncontrolled:"結果の細部は選べない",timing_bound:"発動できる時間が限られる",cannot_target_self:"自分自身には使えない",nonrepeatable_on_same_target:"同じ対象には二度使えない",cooldown_required:"発動後すぐには使えない"},
      control:{high:"高い",medium:"中程度",conditional:"条件付き",low:"低い"}
    };
    var en={
      principle:{preservation:"Preservation",recovery:"Recovery",anticipation:"Anticipation",revelation:"Revelation",transformation:"Transformation",boundary:"Boundary"},
      source:{self:"Self",place:"Place",relation:"Relation",object:"Object or tool",language:"Name or language",accumulated_time:"Accumulated time",relational_field:"Relational field",mediated:"Mediated source"},
      access:{contact:"Touch",inscription:"Writing",utterance:"Speaking",composition:"Arrangement",traversal:"Movement",duration:"Waiting",separation:"Leaving",repetition:"Returning"},
      medium:{touch:"Touch",writing:"Writing",voice:"Voice",arrangement:"Arrangement",movement:"Movement",waiting:"Waiting",departure:"Departure",return:"Return"},
      target:{trace:"Remaining traces",absence:"Absence",possibility:"Future possibility",hidden_state:"Unnoticed state",state_change:"Ongoing change",boundary:"The space between two things"},
      effect:{restore:"Restore",erase:"Erase",overlay:"Overlay",transfer:"Transfer",delay:"Delay",divide:"Divide",reveal:"Reveal",transform:"Transform"},
      limit:{limited_uses:"Limited number of uses",location_bound:"Limited to certain locations",target_bound:"Limited to certain targets",detail_uncontrolled:"Fine details cannot be controlled",timing_bound:"Limited activation time",cannot_target_self:"Cannot target oneself",nonrepeatable_on_same_target:"Cannot affect the same target twice",cooldown_required:"Cannot be used again immediately"},
      control:{high:"High",medium:"Medium",conditional:"Conditional",low:"Low"}
    };
    var dict=ja;
    if(state.language==="en"){
      dict=en;
    }

    if(dict[kind]){
      if(dict[kind][value]){
        return dict[kind][value];
      }
    }
    if(value){
      return value;
    }
    if(state.language==="en") return "Unresolved";
    return "未確定";
  }

  var focusMode=false;
  var focusPlaceholder=null;
  var focusOriginParent=null;
  var focusOriginNext=null;
  var focusBefore=null;
  var focusBodyStyles=null;
  var focusInert=[];
  var focusRootFontSize="";
  var focusRootFontPriority="";
  var lifecycleBound=false;
  var reducedMotionQuery=window.matchMedia?window.matchMedia("(prefers-reduced-motion: reduce)"):null;
  var viewportTimer=0;
  var interactionFrame=0;
  var pendingInteraction=null;
  var HOLD_MOVE_THRESHOLD=12;

  function isReducedMotion(){
    if(!reducedMotionQuery) return false;
    return reducedMotionQuery.matches===true;
  }

  function syncVisualViewport(){
    var root=getRoot();
    var height;
    if(!root) return;
    if(window.visualViewport){
      height=window.visualViewport.height;
      if(height>0){
        root.style.setProperty("--tvm-visual-height",height+"px");
      }
    }else{
      root.style.removeProperty("--tvm-visual-height");
    }
  }

  function scheduleViewportSync(){
    if(viewportTimer){
      window.clearTimeout(viewportTimer);
    }
    viewportTimer=window.setTimeout(function(){
      viewportTimer=0;
      syncVisualViewport();
    },80);
  }

  function focusScroller(){
    var root=getRoot();
    if(!root) return null;
    return byId("tvmagicApp");
  }

  function resetFocusScroller(){
    var scroller;
    if(!focusMode) return;
    scroller=focusScroller();
    if(!scroller) return;
    window.requestAnimationFrame(function(){
      scroller.scrollTop=0;
      scroller.scrollLeft=0;
    });
  }

  function lockFocusPage(){
    var body=document.body;
    var scrollY=window.scrollY||window.pageYOffset||0;
    var props=["position","top","left","right","width","overflow"];
    var i;
    focusBodyStyles={scrollY:scrollY,values:[]};
    for(i=0;i<props.length;i++){
      focusBodyStyles.values.push({
        property:props[i],
        value:body.style.getPropertyValue(props[i]),
        priority:body.style.getPropertyPriority(props[i])
      });
    }
    body.style.setProperty("position","fixed");
    body.style.setProperty("top","-"+scrollY+"px");
    body.style.setProperty("left","0");
    body.style.setProperty("right","0");
    body.style.setProperty("width","100%");
    body.style.setProperty("overflow","hidden");
  }

  function unlockFocusPage(){
    var body=document.body;
    var i;
    var item;
    var scrollY=0;
    if(!focusBodyStyles) return;
    scrollY=focusBodyStyles.scrollY||0;
    for(i=0;i<focusBodyStyles.values.length;i++){
      item=focusBodyStyles.values[i];
      if(item.value){
        body.style.setProperty(item.property,item.value,item.priority);
      }else{
        body.style.removeProperty(item.property);
      }
    }
    focusBodyStyles=null;
    window.scrollTo(0,scrollY);
  }

  function isolateFocusBackground(){
    var root=getRoot();
    var children=document.body.children;
    var i;
    var el;
    focusInert=[];
    for(i=0;i<children.length;i++){
      el=children[i];
      if(el===root) continue;
      if(el.tagName==="SCRIPT") continue;
      if(el.tagName==="STYLE") continue;
      focusInert.push({el:el,wasInert:el.inert===true});
      el.inert=true;
    }
  }

  function restoreFocusBackground(){
    var i;
    for(i=0;i<focusInert.length;i++){
      focusInert[i].el.inert=focusInert[i].wasInert;
    }
    focusInert=[];
  }

  function moveRootToBody(){
    var root=getRoot();
    if(!root) return;
    if(root.parentNode===document.body) return;
    focusOriginParent=root.parentNode;
    focusOriginNext=root.nextSibling;
    focusPlaceholder=document.createComment("tvm-focus-origin");
    root.parentNode.insertBefore(focusPlaceholder,root);
    document.body.appendChild(root);
  }

  function restoreRootOrigin(){
    var root=getRoot();
    if(!root) return;
    if(focusPlaceholder){
      if(focusPlaceholder.parentNode){
        focusPlaceholder.parentNode.insertBefore(root,focusPlaceholder);
        focusPlaceholder.parentNode.removeChild(focusPlaceholder);
      }
      focusPlaceholder=null;
      return;
    }
    if(focusOriginParent){
      if(focusOriginNext){
        if(focusOriginNext.parentNode===focusOriginParent){
          focusOriginParent.insertBefore(root,focusOriginNext);
          return;
        }
      }
      focusOriginParent.appendChild(root);
    }
  }

  function syncFocusUI(){
    var root=getRoot();
    var button=byId("tvmFocusToggle");
    var u=currentUI();
    var label=focusMode?u.focus_exit:u.focus_enter;
    if(root){
      if(focusMode){
        root.classList.add("is-focus");
      }else{
        root.classList.remove("is-focus");
      }
    }
    if(button){
      button.setAttribute("aria-pressed",focusMode?"true":"false");
      button.setAttribute("aria-label",label);
      button.setAttribute("title",label);
    }
  }

  function enterFocusMode(){
    var root=getRoot();
    var button=byId("tvmFocusToggle");
    var computedFontSize;
    if(!root) return;
    if(focusMode) return;
    focusBefore=document.activeElement;
    focusRootFontSize=root.style.getPropertyValue("font-size");
    focusRootFontPriority=root.style.getPropertyPriority("font-size");
    computedFontSize=window.getComputedStyle(root).fontSize;
    if(computedFontSize){
      root.style.setProperty("font-size",computedFontSize);
    }
    lockFocusPage();
    moveRootToBody();
    focusMode=true;
    syncVisualViewport();
    syncFocusUI();
    isolateFocusBackground();
    resetFocusScroller();
    button=byId("tvmQuestionShell");
    if(button){
      button.focus({preventScroll:true});
    }
  }

  function exitFocusMode(restoreFocus){
    var target;
    var root=getRoot();
    if(!focusMode) return;
    if(!root) return;
    clearTransientInteractionState();
    focusMode=false;
    syncFocusUI();
    restoreFocusBackground();
    restoreRootOrigin();
    if(focusRootFontSize){
      root.style.setProperty("font-size",focusRootFontSize,focusRootFontPriority);
    }else{
      root.style.removeProperty("font-size");
    }
    focusRootFontSize="";
    focusRootFontPriority="";
    unlockFocusPage();
    if(restoreFocus!==false){
      target=focusBefore;
      if(target){
        if(target.isConnected){
          if(typeof target.focus==="function"){
            target.focus({preventScroll:true});
          }
        }
      }
    }
    focusBefore=null;
  }

  function toggleFocusMode(){
    if(focusMode){
      exitFocusMode(true);
      preferredFocusMode=false;
      saveFocusPreference(false);
    }else{
      enterFocusMode();
      preferredFocusMode=true;
      saveFocusPreference(true);
    }
  }

  function bindFocusToggle(){
    var button=byId("tvmFocusToggle");
    if(!button) return;
    syncFocusUI();
    button.addEventListener("click",toggleFocusMode);
  }

  function cancelInteractionFrame(){
    if(interactionFrame){
      window.cancelAnimationFrame(interactionFrame);
      interactionFrame=0;
    }
    pendingInteraction=null;
  }

  function flushInteractionFrame(){
    var item=pendingInteraction;
    interactionFrame=0;
    pendingInteraction=null;
    if(!item) return;
    if(!item.node) return;
    if(!item.node.isConnected) return;
    updateReactivePoint(item.node,item.x,item.y);
    setInteractionPhysics(item.node,item.x,item.y,item.energy);
  }

  function scheduleInteractionFrame(node,x,y,energy){
    pendingInteraction={node:node,x:x,y:y,energy:energy};
    if(interactionFrame) return;
    interactionFrame=window.requestAnimationFrame(flushInteractionFrame);
  }

  function cancelNodeHold(node,clearSuppression){
    if(!node) return;
    if(node._tisHoldTimer){
      window.clearTimeout(node._tisHoldTimer);
      node._tisHoldTimer=0;
    }
    if(node._tisSuppressResetTimer){
      window.clearTimeout(node._tisSuppressResetTimer);
      node._tisSuppressResetTimer=0;
    }
    if(clearSuppression===true){
      node._tisSuppressClick=false;
    }
    node._tisPointerId=null;
    node._tisStartX=null;
    node._tisStartY=null;
    node.classList.remove("is-long-preview");
    node.removeAttribute("data-long-preview");
  }

  function clearTransientInteractionState(){
    var root=getRoot();
    var nodes;
    var i;
    var node;
    if(!root) return;
    cancelInteractionFrame();
    nodes=root.querySelectorAll(".tvm-reactive");
    for(i=0;i<nodes.length;i++){
      node=nodes[i];
      cancelNodeHold(node,true);
      node.classList.remove("is-preview");
      if(!node.classList.contains("is-selected")){
        node.removeAttribute("data-contact-state");
      }
    }
    root.style.setProperty("--tis-energy","0");
    root.setAttribute("data-calm","true");
    setInteracting(false);
  }

  function keyboardTargetIsTyping(target){
    var tag;
    if(!target) return false;
    if(target.isContentEditable) return true;
    tag=String(target.tagName||"").toLowerCase();
    if(tag==="textarea") return true;
    if(tag==="input") return true;
    if(tag==="select") return true;
    return false;
  }

  function keyboardElementIsUsable(node){
    var rect;
    var style;
    if(!node) return false;
    if(node.disabled) return false;
    if(node.getAttribute("aria-disabled")==="true") return false;
    if(node.hidden) return false;
    style=window.getComputedStyle(node);
    if(style.display==="none") return false;
    if(style.visibility==="hidden") return false;
    rect=node.getBoundingClientRect();
    if(rect.width<=0) return false;
    if(rect.height<=0) return false;
    return true;
  }

  function keyboardActivate(node,event){
    if(!keyboardElementIsUsable(node)) return false;
    if(event){
      event.preventDefault();
      event.stopPropagation();
    }
    node.click();
    return true;
  }

  function keyboardFocusChoice(direction,event){
    var choices=document.querySelectorAll(".tv-magic .tvm-choice:not(:disabled)");
    var current=document.activeElement;
    var index=-1;
    var i;
    var next;

    if(!choices.length) return false;

    for(i=0;i<choices.length;i++){
      if(choices[i]===current){
        index=i;
        break;
      }
    }

    if(direction>0){
      next=index<0?0:(index+1)%choices.length;
    }else{
      next=index<0?choices.length-1:(index-1+choices.length)%choices.length;
    }

    if(event){
      event.preventDefault();
      event.stopPropagation();
    }

    choices[next].focus({preventScroll:true});
    return true;
  }

  function handleKeyboardShortcut(event){
    var target=event.target;
    var active=document.activeElement;
    var key=event.key;
    var lower=String(key||"").toLowerCase();
    var index;
    var choices;
    var node;

    if(event.defaultPrevented) return false;
    if(event.repeat) return false;

    if(event.metaKey||event.ctrlKey){
      if(lower==="z"){
        if(!keyboardTargetIsTyping(target)){
          node=byId("tvmBackQuestion");
          if(node){
            return keyboardActivate(node,event);
          }
        }
      }
      return false;
    }

    if(event.altKey) return false;

    /* Shift is allowed for ordinary Enter/Space and the ? help key. */
    if(event.shiftKey){
      if(key!=="Enter"){
        if(key!==" "){
          if(key!=="?"){
            return false;
          }
        }
      }
    }

    /* Never hijack text-entry controls. Escape remains handled separately. */
    if(keyboardTargetIsTyping(target)){
      return false;
    }

    if(key==="?"){
      event.preventDefault();
      event.stopPropagation();
      openShortcutSheet();
      return true;
    }

    if(key==="ArrowLeft"){
      if(active){
        if(active.classList){
          if(active.classList.contains("tvm-lang")){
            node=byId("tvmChooseJA");
            if(node){
              event.preventDefault();
              node.focus({preventScroll:true});
              return true;
            }
          }
        }
      }
    }

    if(key==="ArrowRight"){
      if(active){
        if(active.classList){
          if(active.classList.contains("tvm-lang")){
            node=byId("tvmChooseEN");
            if(node){
              event.preventDefault();
              node.focus({preventScroll:true});
              return true;
            }
          }
        }
      }
    }

    if(key>="1"){
      if(key<="9"){
        choices=document.querySelectorAll(".tv-magic .tvm-choice:not(:disabled)");
        if(choices.length){
          index=parseInt(key,10)-1;
          if(index>=0){
            if(index<choices.length){
              return keyboardActivate(choices[index],event);
            }
          }
        }
      }
    }

    if(key==="ArrowDown"){
      return keyboardFocusChoice(1,event);
    }

    if(key==="ArrowUp"){
      return keyboardFocusChoice(-1,event);
    }

    if(key==="Enter"){
      if(active){
        if(active!==document.body){
          return keyboardActivate(active,event);
        }
      }
      return false;
    }

    if(key===" "){
      if(active){
        if(active!==document.body){
          return keyboardActivate(active,event);
        }
      }
      return false;
    }

    if(lower==="b"){
      node=byId("tvmBackQuestion");
      if(node){
        return keyboardActivate(node,event);
      }
      return false;
    }

    if(lower==="f"){
      node=byId("tvmFocusToggle");
      if(node){
        return keyboardActivate(node,event);
      }
      return false;
    }

    if(lower==="r"){
      node=byId("tvmRestart");
      if(node){
        return keyboardActivate(node,event);
      }
      return false;
    }

    if(lower==="c"){
      node=document.querySelector('.tv-magic [data-share-action="copy"]');
      if(node){
        return keyboardActivate(node,event);
      }
      return false;
    }

    if(lower==="p"){
      node=byId("tvmCopy");
      if(node){
        return keyboardActivate(node,event);
      }
      return false;
    }

    if(lower==="s"){
      node=document.querySelector('.tv-magic [data-share-action="native"]');
      if(node){
        return keyboardActivate(node,event);
      }
      return false;
    }

    if(lower==="x"){
      node=document.querySelector('.tv-magic [data-share-action="x"]');
      if(node){
        return keyboardActivate(node,event);
      }
      return false;
    }

    if(lower==="t"){
      node=document.querySelector('.tv-magic [data-share-action="threads"]');
      if(node){
        return keyboardActivate(node,event);
      }
      return false;
    }

    if(lower==="l"){
      node=document.querySelector('.tv-magic [data-share-action="line"]');
      if(node){
        return keyboardActivate(node,event);
      }
      return false;
    }

    return false;
  }

  function bindLifecycleSafety(){
    if(lifecycleBound) return;
    lifecycleBound=true;

    document.addEventListener("visibilitychange",function(){
      if(document.hidden){
        clearTransientInteractionState();
      }else{
        scheduleViewportSync();
      }
    });

    document.addEventListener("keydown",function(event){
      var root=getRoot();
      var sheet;
      var items;
      var first;
      var last;

      if(handleKeyboardShortcut(event)) return;

      if(event.key==="Escape"){
        if(shortcutSheetOpen){
          event.preventDefault();
          closeShortcutSheet(true);
          return;
        }
      }

      if(managedOverlayStack.length){
        if(trapManagedOverlayTab(event)) return;
      }

      if(!focusMode) return;
      if(event.key==="Escape"){
        event.preventDefault();
        exitFocusMode(true);
        preferredFocusMode=false;
        saveFocusPreference(false);
        return;
      }
      if(event.key!=="Tab") return;
      if(!root) return;
      items=root.querySelectorAll('button:not(:disabled),textarea:not(:disabled),a[href],[tabindex]:not([tabindex="-1"])');
      if(!items.length) return;
      first=items[0];
      last=items[items.length-1];
      if(event.shiftKey){
        if(document.activeElement===first){
          event.preventDefault();
          last.focus();
          return;
        }
        if(Array.prototype.indexOf.call(items,document.activeElement)<0){
          event.preventDefault();
          last.focus();
        }
      }else{
        if(document.activeElement===last){
          event.preventDefault();
          first.focus();
          return;
        }
        if(Array.prototype.indexOf.call(items,document.activeElement)<0){
          event.preventDefault();
          first.focus();
        }
      }
    });

    window.addEventListener("resize",scheduleViewportSync,{passive:true});
    if(window.visualViewport){
      window.visualViewport.addEventListener("resize",scheduleViewportSync,{passive:true});
      window.visualViewport.addEventListener("scroll",scheduleViewportSync,{passive:true});
    }
    if(screen.orientation){
      if(screen.orientation.addEventListener){
        screen.orientation.addEventListener("change",scheduleViewportSync);
      }
    }
    window.addEventListener("orientationchange",scheduleViewportSync,{passive:true});

    if(themeMediaQuery){
      if(themeMediaQuery.addEventListener){
        themeMediaQuery.addEventListener("change",syncAutoTheme);
      }
    }

    window.addEventListener("pageshow",function(event){
      clearTransientInteractionState();
      scheduleViewportSync();
      if(event.persisted){
        syncFocusUI();
      }
    });

    window.addEventListener("pagehide",function(){
      var root=getRoot();
      clearTransientInteractionState();
      closeShortcutSheet(false);
      if(root){
        if(root._tvmToastShowTimer){
          window.clearTimeout(root._tvmToastShowTimer);
          root._tvmToastShowTimer=0;
        }
        if(root._tvmToastHideTimer){
          window.clearTimeout(root._tvmToastHideTimer);
          root._tvmToastHideTimer=0;
        }
      }
      if(viewportTimer){
        window.clearTimeout(viewportTimer);
        viewportTimer=0;
      }
      cancelInteractionFrame();
      exitFocusMode(false);
    });
  }

  function chrome(stage){
    var current;
    var countText;
    if(!stage) return "";
    current=currentQuestionNumber();
    countText=(current<10?"0"+current:String(current));
    return '<div class="tvm-top">'+
      '<div class="tvm-question-meta">'+
        '<span class="tvm-question-meta-count">'+escapeHtml(countText)+'</span>'+ 
      '</div>'+ 
    '</div>';
  }

  function experienceToggleHtml(){
    var u=currentUI();
    var title=focusMode?u.focus_exit:u.focus_enter;
    return '<div class="tvm-experience-toggle">'+
      '<button type="button" class="tvm-focus-toggle tvm-control" id="tvmFocusToggle" aria-pressed="'+(focusMode?"true":"false")+'" aria-label="'+escapeHtml(title)+'" title="'+escapeHtml(title)+'">'+
        '<svg class="tvm-focus-icon-enter" viewBox="0 0 24 24" aria-hidden="true">'+
          '<path d="M10 14 L5 19"></path>'+
          '<path d="M10.5 19 H5 V13.5"></path>'+
          '<path d="M14 10 L19 5"></path>'+
          '<path d="M13.5 5 H19 V10.5"></path>'+
        '</svg>'+
        '<svg class="tvm-focus-icon-exit" viewBox="0 0 24 24" aria-hidden="true">'+
          '<path d="M19 5 L14 10"></path>'+
          '<path d="M14 5 V10 H19"></path>'+
          '<path d="M5 19 L10 14"></path>'+
          '<path d="M5 14 H10 V19"></path>'+
        '</svg>'+
      '</button>'+
    '</div>';
  }

  function render(){
    syncMagicLanguageAttributes();
    if(state.screen==="entry"){
      renderEntry();
    }else if(state.screen==="question"){
      renderQuestion();
    }else if(state.screen==="error"){
      renderErrorState();
    }else if(state.screen==="result"){
      renderResult();
    }
    resetFocusScroller();
  }

  function renderEntry(){
    var app=getApp();
    var ja;
    var en;
    var start;
    var u;

    if(!app) return;

    if(!state.language){
      state.language="ja";
    }

    u=currentUI();
    setStageEnvironment("outline");

    app.innerHTML=
      experienceToggleHtml()+
      '<section class="tvm-screen tvm-entry tvm-density-relaxed" data-surface="content" data-elevation="s0">'+
        '<div class="tvm-spacer tvm-spacer--entry-top" aria-hidden="true"></div>'+
        '<p class="tvm-hero tvm-align-center">'+u.entry_title+'</p>'+
        '<div class="tvm-spacer tvm-spacer--hero-lead" aria-hidden="true"></div>'+
        '<p class="tvm-lead tvm-align-center">'+u.entry_lead+'</p>'+
        '<div class="tvm-spacer tvm-spacer--lead-language" aria-hidden="true"></div>'+
        '<div class="tvm-language tvm-material-mist" data-surface="interface" data-elevation="s2" data-glass="mist" role="radiogroup" aria-label="Language">'+
          '<button type="button" class="tvm-lang tvm-control tvm-reactive'+(state.language==="ja"?" is-active":"")+'" data-material="'+(state.language==="ja"?"veil":"mist")+'" id="tvmChooseJA" role="radio" aria-checked="'+(state.language==="ja"?"true":"false")+'">日本語</button>'+
          '<button type="button" class="tvm-lang tvm-control tvm-reactive'+(state.language==="en"?" is-active":"")+'" data-material="'+(state.language==="en"?"veil":"mist")+'" id="tvmChooseEN" role="radio" aria-checked="'+(state.language==="en"?"true":"false")+'">English</button>'+
        '</div>'+
        '<div class="tvm-spacer tvm-spacer--language-start" aria-hidden="true"></div>'+
        '<div class="tvm-actions"><button type="button" class="tvm-btn is-primary tvm-control tvm-reactive" data-material="veil" data-surface="interface" data-elevation="s1" data-glass="veil" id="tvmStart">'+escapeHtml(u.start)+'</button></div>'+
      '</section>';

    ja=byId("tvmChooseJA");
    en=byId("tvmChooseEN");
    start=byId("tvmStart");

    bindInteractionControls();
    bindFocusToggle();
    syncLanguageSegmentA11y();
    applyShortcutMetadata();
    syncMagicLanguageAttributes();

    if(ja){
      ja.addEventListener("click",function(){
        state.language="ja";
        saveLanguagePreference("ja");
        if(!focusMode){
          enterFocusMode();
          preferredFocusMode=true;
          saveFocusPreference(true);
        }
        render();
      });
    }

    if(en){
      en.addEventListener("click",function(){
        state.language="en";
        saveLanguagePreference("en");
        if(!focusMode){
          enterFocusMode();
          preferredFocusMode=true;
          saveFocusPreference(true);
        }
        render();
      });
    }

    if(start){
      start.addEventListener("click",function(){
        if(!focusMode){
          enterFocusMode();
          preferredFocusMode=true;
          saveFocusPreference(true);
        }
        state.history=["q1"];
        state.screen="question";
        render();
      });
    }
  }

  function currentQuestionId(){
    if(state.history.length<1) return "";
    return state.history[state.history.length-1];
  }

  /* Adaptive question policy
     MIN 5 / TARGET 5–7 / MAX 10
     TARGET is an expected completion range, not a second cap.
     From question 5 onward, Completion Gate decides whether to finish.
     Question 10 is the single hard stop. */
  var QUESTION_MIN=5;
  var QUESTION_MAX=10;
  var PROMPT_MAX_CHARACTERS=9500;

  function currentQuestionNumber(){
    var n=state.history.length;
    if(n<1) n=1;
    return n;
  }

  function adaptiveProgressPercent(current){
    var steps=[0,15,28,42,56,68,76,83,89,94,97];
    if(current<1) return 0;
    if(current>QUESTION_MAX) current=QUESTION_MAX;
    return steps[current];
  }

  function progressHtml(){
    var current=currentQuestionNumber();
    var percent=adaptiveProgressPercent(current);
    var countText=(current<10?"0"+current:String(current));
    var u=currentUI();
    var progressAttrs=' aria-valuetext="'+escapeHtml(countText)+'"';

    return ''+
      '<div class="tvm-progress-wrap">'+
        '<div class="tvm-progress" role="progressbar" aria-label="'+escapeHtml(u.progress_label)+'"'+progressAttrs+'>'+
          '<div class="tvm-progress-track" aria-hidden="true"><span class="tvm-progress-bar" style="width:'+percent+'%"></span></div>'+
        '</div>'+
      '</div>';
  }

  function syncMaterialSemantics(node){
    var material;

    if(!node) return;

    material=node.getAttribute("data-material");
    if(!material) return;

    if(material==="lens"){
      node.setAttribute("data-surface","transient");
      node.setAttribute("data-elevation","s3");
      node.setAttribute("data-glass","lens");
      return;
    }

    node.setAttribute("data-surface","interface");
    node.setAttribute("data-elevation","s1");

    if(material==="mist"){
      node.setAttribute("data-glass","mist");
    }else if(material==="veil"){
      node.setAttribute("data-glass","veil");
    }else{
      node.removeAttribute("data-glass");
    }
  }

  function setMaterialState(node,material){
    if(!node) return;
    node.setAttribute("data-material",material);
    syncMaterialSemantics(node);
  }

  function controlLabelNode(button){
    if(!button) return null;
    return button.querySelector(".tvm-btn-label");
  }

  function setControlLabel(button,label){
    var node;
    if(!button) return false;
    node=controlLabelNode(button);
    if(node){
      node.textContent=label;
      return true;
    }
    if(button.children.length===0){
      button.textContent=label;
      return true;
    }
    return false;
  }

  function setBusyControl(button,busy,label){
    var labelNode;
    if(!button) return false;

    labelNode=controlLabelNode(button);

    if(busy){
      if(button.disabled) return false;
      button.disabled=true;
      button.setAttribute("aria-busy","true");
      button.setAttribute("data-busy","true");

      if(label){
        if(labelNode){
          button._tvmBusyPreviousLabel=labelNode.textContent;
          labelNode.textContent=label;
        }else if(button.children.length===0){
          button._tvmBusyPreviousLabel=button.textContent;
          button.textContent=label;
        }
      }
    }else{
      button.disabled=false;
      button.removeAttribute("aria-busy");
      button.removeAttribute("data-busy");

      if(button._tvmBusyPreviousLabel!==undefined){
        labelNode=controlLabelNode(button);
        if(labelNode){
          labelNode.textContent=button._tvmBusyPreviousLabel;
        }else if(button.children.length===0){
          button.textContent=button._tvmBusyPreviousLabel;
        }
        delete button._tvmBusyPreviousLabel;
      }
    }

    return true;
  }

  function showToast(message,actionLabel,actionCallback){
    var root=document.querySelector(".tv-magic");
    var toast;
    var textNode;
    var action;

    if(!root) return;

    toast=byId("tvmToast");
    if(!toast){
      toast=document.createElement("div");
      toast.id="tvmToast";
      toast.className="tvm-toast";
      toast.setAttribute("data-surface","transient");
      toast.setAttribute("data-elevation","s3");
      toast.setAttribute("data-glass","veil");
      toast.setAttribute("role","status");
      toast.setAttribute("aria-live","polite");
      toast.setAttribute("aria-atomic","true");
      root.appendChild(toast);
    }

    if(root._tvmToastShowTimer){
      window.clearTimeout(root._tvmToastShowTimer);
      root._tvmToastShowTimer=0;
    }

    if(root._tvmToastHideTimer){
      window.clearTimeout(root._tvmToastHideTimer);
      root._tvmToastHideTimer=0;
    }

    toast.innerHTML="";
    textNode=document.createElement("span");
    textNode.className="tvm-toast-message";
    textNode.textContent=message;
    toast.appendChild(textNode);

    if(actionLabel){
      if(typeof actionCallback==="function"){
        action=document.createElement("button");
        action.type="button";
        action.className="tvm-toast-action tvm-control";
        action.textContent=actionLabel;
        action.addEventListener("click",function(){
          actionCallback();
          toast.classList.remove("is-visible");
        });
        toast.appendChild(action);
      }
    }

    toast.classList.remove("is-visible");

    root._tvmToastShowTimer=window.setTimeout(function(){
      var t=byId("tvmToast");
      if(t){
        t.classList.add("is-visible");
      }
      root._tvmToastShowTimer=0;
    },10);

    root._tvmToastHideTimer=window.setTimeout(function(){
      var t=byId("tvmToast");
      if(t){
        t.classList.remove("is-visible");
      }
      root._tvmToastHideTimer=0;
    },2600);
  }

  function rootNode(){return document.querySelector(".tv-magic");}
  function setInputMode(mode){var root=rootNode();if(!root)return;root.setAttribute("data-input-mode",mode);}
  function setInteracting(active){var root=rootNode();if(!root)return;if(active){root.setAttribute("data-interacting","true");}else{root.removeAttribute("data-interacting");}}
  function localPoint(node,clientX,clientY){var rect=node.getBoundingClientRect();var x=((clientX-rect.left)/rect.width)*100;var y=((clientY-rect.top)/rect.height)*100;if(x<0)x=0;if(x>100)x=100;if(y<0)y=0;if(y>100)y=100;return {x:x,y:y};}
  function updateReactivePoint(node,clientX,clientY){var p;if(!node)return;p=localPoint(node,clientX,clientY);node.style.setProperty("--tvm-pointer-x",p.x+"%");node.style.setProperty("--tvm-pointer-y",p.y+"%");}
  function addInteractionTrace(node,clientX,clientY){var layer;var trace;var p;if(!node)return;layer=node.querySelector(".tvm-trace-layer");if(!layer){layer=document.createElement("span");layer.className="tvm-trace-layer";layer.setAttribute("aria-hidden","true");node.appendChild(layer);}p=localPoint(node,clientX,clientY);trace=document.createElement("span");trace.className="tvm-trace";trace.style.left=p.x+"%";trace.style.top=p.y+"%";layer.appendChild(trace);window.setTimeout(function(){if(trace){if(trace.parentNode){trace.parentNode.removeChild(trace);}}},620);}
  function bindInteractionControls(){
    var controls=document.querySelectorAll(".tv-magic .tvm-reactive");
    var i;

    for(i=0;i<controls.length;i++){
      syncMaterialSemantics(controls[i]);

      (function(node){
        node.addEventListener("pointerenter",function(event){
          if(event.isPrimary===false) return;
          if(event.pointerType==="mouse"){
            setInputMode("mouse");
          }
          node.setAttribute("data-contact-state","approach");
          scheduleInteractionFrame(node,event.clientX,event.clientY,.22);
        });

        node.addEventListener("pointermove",function(event){
          var dx;
          var dy;
          var dist;

          if(event.isPrimary===false) return;

          if(event.pointerType==="touch"){
            setInputMode("touch");
          }else if(event.pointerType==="pen"){
            setInputMode("pen");
          }else if(event.pointerType==="mouse"){
            setInputMode("mouse");
          }

          if(node._tisPointerId!==null){
            if(node._tisPointerId!==undefined){
              if(event.pointerId===node._tisPointerId){
                if(node._tisStartX!==null){
                  if(node._tisStartX!==undefined){
                    dx=event.clientX-node._tisStartX;
                    dy=event.clientY-node._tisStartY;
                    dist=Math.sqrt((dx*dx)+(dy*dy));
                    if(dist>HOLD_MOVE_THRESHOLD){
                      cancelNodeHold(node,true);
                    }
                  }
                }
              }
            }
          }

          scheduleInteractionFrame(node,event.clientX,event.clientY,.26);
        });

        node.addEventListener("pointerdown",function(event){
          if(event.isPrimary===false) return;

          if(event.pointerType==="touch"){
            setInputMode("touch");
          }else if(event.pointerType==="pen"){
            setInputMode("pen");
          }else if(event.pointerType==="mouse"){
            setInputMode("mouse");
          }

          setInteracting(true);
          node.setAttribute("data-contact-state","pressed");
          scheduleInteractionFrame(node,event.clientX,event.clientY,.62);
          addInteractionTrace(node,event.clientX,event.clientY);

          if(node.setPointerCapture){
            try{
              node.setPointerCapture(event.pointerId);
            }catch(error){}
          }

          if(node.classList.contains("tvm-choice")){
            if(event.pointerType!=="touch"){
              return;
            }

            cancelNodeHold(node,true);
            node._tisPointerId=event.pointerId;
            node._tisStartX=event.clientX;
            node._tisStartY=event.clientY;

            node._tisHoldTimer=window.setTimeout(function(){
              node._tisHoldTimer=0;
              node._tisSuppressClick=true;
              node.classList.add("is-long-preview");
              node.setAttribute("data-long-preview","true");

              if(node._tisSuppressResetTimer){
                window.clearTimeout(node._tisSuppressResetTimer);
              }

              node._tisSuppressResetTimer=window.setTimeout(function(){
                node._tisSuppressClick=false;
                node._tisSuppressResetTimer=0;
              },700);
            },460);
          }
        });

        node.addEventListener("pointerup",function(event){
          if(event.isPrimary===false) return;
          setInteracting(false);
          cancelNodeHold(node,false);

          if(node.releasePointerCapture){
            try{
              if(node.hasPointerCapture){
                if(node.hasPointerCapture(event.pointerId)){
                  node.releasePointerCapture(event.pointerId);
                }
              }
            }catch(error){}
          }

          if(node.classList.contains("is-selected")){
            node.setAttribute("data-contact-state","selected");
          }else{
            node.setAttribute("data-contact-state","contact");
          }
          decayInteractionPhysics();
        });

        node.addEventListener("pointerleave",function(event){
          if(event.isPrimary===false) return;
          setInteracting(false);
          cancelNodeHold(node,true);

          if(node.classList.contains("is-selected")){
            node.setAttribute("data-contact-state","selected");
          }else{
            node.removeAttribute("data-contact-state");
          }
          decayInteractionPhysics();
        });

        node.addEventListener("pointercancel",function(){
          setInteracting(false);
          cancelNodeHold(node,true);
          node.removeAttribute("data-contact-state");
          decayInteractionPhysics();
        });

        node.addEventListener("lostpointercapture",function(){
          setInteracting(false);
          cancelNodeHold(node,true);
          decayInteractionPhysics();
        });

        node.addEventListener("touchcancel",function(){
          cancelNodeHold(node,true);
          clearChoicePreview();
          decayInteractionPhysics();
        },{passive:true});

        node.addEventListener("contextmenu",function(event){
          if(node.classList.contains("tvm-choice")){
            if(node.classList.contains("is-long-preview")){
              event.preventDefault();
            }
          }
        });

        node.addEventListener("focus",function(){
          setInputMode("keyboard");
          decayInteractionPhysics();
        });

        node.addEventListener("blur",function(){
          if(node.classList.contains("is-selected")){
            node.setAttribute("data-contact-state","selected");
          }else{
            node.removeAttribute("data-contact-state");
          }
        });
      })(controls[i]);
    }

    setCalmState(true);
  }

  function clearChoicePreview(){var choices=document.querySelectorAll(".tv-magic .tvm-choice.is-preview");var i;for(i=0;i<choices.length;i++){choices[i].classList.remove("is-preview");}}
  function bindTouchSlidingPreview(){var area=document.querySelector(".tv-magic .tvm-choices");if(!area)return;area.addEventListener("touchmove",function(event){var touch;var node;if(!event.touches)return;if(event.touches.length!==1){clearChoicePreview();return;}touch=event.touches[0];node=document.elementFromPoint(touch.clientX,touch.clientY);clearChoicePreview();if(node){if(node.classList){if(node.classList.contains("tvm-choice")){node.classList.add("is-preview");scheduleInteractionFrame(node,touch.clientX,touch.clientY,.24);}}}},{passive:true});area.addEventListener("touchend",function(){clearChoicePreview();},{passive:true});area.addEventListener("touchcancel",function(){clearChoicePreview();cancelInteractionFrame();},{passive:true});}
  function transitionQuestionThen(callback){var shell=byId("tvmQuestionShell");var delay=isReducedMotion()?0:220;if(shell){shell.classList.remove("is-entering");shell.classList.add("is-leaving");window.setTimeout(function(){callback();},delay);}else{callback();}}

  function setStageEnvironment(stage){
    var root=rootNode();
    if(!root) return;

    if(stage==="outline"){
      root.setAttribute("data-stage-env","outline");
    }else if(stage==="mechanism"){
      root.setAttribute("data-stage-env","mechanism");
    }else if(stage==="almost"){
      root.setAttribute("data-stage-env","almost");
    }else{
      root.setAttribute("data-stage-env","result");
    }
  }

  function setCalmState(calm){
    var root=rootNode();
    if(!root) return;

    if(calm){
      root.setAttribute("data-calm","true");
    }else{
      root.setAttribute("data-calm","false");
    }
  }

  function setInteractionPhysics(node,clientX,clientY,energy){
    var root=rootNode();
    var p;

    if(!root) return;
    if(!node) return;

    p=localPoint(node,clientX,clientY);
    root.style.setProperty("--tis-contact-x",p.x+"%");
    root.style.setProperty("--tis-contact-y",p.y+"%");
    root.style.setProperty("--tis-energy",String(energy));
    setCalmState(false);
  }

  function decayInteractionPhysics(){
    var root=rootNode();
    if(!root) return;

    root.style.setProperty("--tis-energy","0");
    window.setTimeout(function(){
      setCalmState(true);
    },isReducedMotion()?0:360);
  }

  function progressTraceHtml(current,total){
    var html="";
    var i;
    var left;

    if(total<1) return "";

    html+='<span class="tvm-progress-traces" aria-hidden="true">';

    for(i=1;i<=current;i++){
      if(total===1){
        left=100;
      }else{
        left=((i-1)/(total-1))*100;
      }

      html+='<span class="tvm-progress-trace'+(i===current?" is-current":"")+'" style="left:'+left+'%"></span>';
    }

    html+='</span>';
    return html;
  }

  function applyQuestionVerticalDensity(){
    var frame=byId("tvmQuestionFrame");
    var choices;
    var viewportHeight;
    var frameHeight;
    var ratio;
    var count;

    if(!frame) return;

    choices=frame.querySelectorAll(".tvm-choice");
    count=choices.length;
    viewportHeight=window.innerHeight;

    if(window.visualViewport){
      if(window.visualViewport.height){
        viewportHeight=window.visualViewport.height;
      }
    }

    frame.classList.remove("is-density-relaxed");
    frame.classList.remove("is-density-regular");
    frame.classList.remove("is-density-dense");

    window.requestAnimationFrame(function(){
      if(!frame.isConnected) return;
      frameHeight=frame.getBoundingClientRect().height;
      ratio=viewportHeight>0?frameHeight/viewportHeight:0;

      if(count>=7){
        frame.classList.add("is-density-dense");
        return;
      }

      if(ratio>=.64){
        frame.classList.add("is-density-dense");
        return;
      }

      if(count<=6){
        if(ratio<=.56){
          frame.classList.add("is-density-relaxed");
          return;
        }
      }

      frame.classList.add("is-density-regular");
    });
  }

  function applyQuestionTextRhythm(){
    var frame=byId("tvmQuestionFrame");
    var question;
    var style;
    var lineHeight;
    var height;

    if(!frame) return;
    question=frame.querySelector(".tvm-question");
    if(!question) return;

    frame.classList.remove("is-question-multiline");
    style=window.getComputedStyle(question);
    lineHeight=parseFloat(style.lineHeight);
    height=question.getBoundingClientRect().height;

    if(lineHeight>0){
      if(height>(lineHeight*1.45)){
        frame.classList.add("is-question-multiline");
      }
    }
  }

  function renderQuestion(){
    var app=getApp();
    var id=currentQuestionId();
    var q=currentQuestions()[id];
    var html="";
    var i;
    var buttons;
    var back;

    if(!app) return;
    if(!q){
      state.screen="entry";
      render();
      return;
    }

    setStageEnvironment(q.stage);

    html+=experienceToggleHtml();
    html+='<section class="tvm-screen tvm-question-screen tvm-density-regular" data-surface="content" data-elevation="s0">';
    html+='<div class="tvm-question-frame" id="tvmQuestionFrame">';
    html+=chrome(q.stage);
    html+=progressHtml();
    html+='<div class="tvm-question-shell is-entering" id="tvmQuestionShell" tabindex="-1">';
    html+='<p class="tvm-question tvm-align-left">'+escapeHtml(q.text)+'</p>';
    html+='<div class="tvm-choices">';

    for(i=0;i<q.choices.length;i++){
      html+='<button type="button" class="tvm-choice tvm-control tvm-reactive" data-material="clear" data-surface="interface" data-elevation="s1" data-choice="'+escapeHtml(q.choices[i][0])+'">'+escapeHtml(q.choices[i][1])+'</button>';
    }

    html+='</div>';
    html+='</div>';
    html+='<div class="tvm-backrow"><button type="button" class="tvm-back tvm-control tvm-reactive" data-material="clear" data-surface="interface" data-elevation="s1" id="tvmBackQuestion">'+escapeHtml(currentUI().back)+'</button></div>';
    html+='</div>';
    html+='</section>';

    app.innerHTML=html;

    bindInteractionControls();
    bindTouchSlidingPreview();
    bindFocusToggle();
    applyShortcutMetadata();
    applyQuestionVerticalDensity();
    applyQuestionTextRhythm();
    syncMagicLanguageAttributes();

    buttons=app.querySelectorAll(".tvm-choice");
    for(i=0;i<buttons.length;i++){
      (function(button){
        button.addEventListener("click",function(){
          var key;
          var j;

          if(button.disabled) return;

          if(button._tisSuppressClick){
            button._tisSuppressClick=false;

            if(button._tisSuppressResetTimer){
              window.clearTimeout(button._tisSuppressResetTimer);
              button._tisSuppressResetTimer=0;
            }

            return;
          }

          key=button.getAttribute("data-choice");

          for(j=0;j<buttons.length;j++){
            buttons[j].disabled=true;
            buttons[j].setAttribute("aria-disabled","true");
          }

          if(back){
            back.disabled=true;
            back.setAttribute("aria-disabled","true");
          }

          button.classList.add("is-selected");
          setMaterialState(button,"veil");

          window.setTimeout(function(){
            transitionQuestionThen(function(){
              answerQuestion(id,key);
            });
          },isReducedMotion()?0:120);
        });
      })(buttons[i]);
    }

    back=byId("tvmBackQuestion");
    if(back){
      back.addEventListener("click",function(){
        transitionQuestionThen(function(){
          goBack();
        });
      });
    }
  }

  function answerQuestion(id,key){
    var next;
    state.answers[id]=key;
    next=chooseNextQuestion();

    if(next){
      state.history.push(next);
      state.screen="question";
      render();
      return;
    }

    finish();
  }

  function resolvedSource(){
    var a=state.answers;
    var mapped;
    if(a.q2){
      if(a.q2!=="H"){
        mapped=MAP.q2[a.q2]||{};
        return mapped.source||"";
      }
    }
    if(a.qSourceFinal){
      mapped=MAP.qSourceFinal[a.qSourceFinal]||{};
      return mapped.source||"";
    }
    if(a.qSource){
      mapped=MAP.qSource[a.qSource]||{};
      if(mapped.source){
        if(mapped.source!=="unknown") return mapped.source;
      }
    }
    return "";
  }

  function resolvedEffect(){
    var a=state.answers;
    var mapped;
    if(a.q5){
      mapped=MAP.q5[a.q5]||{};
      if(mapped.effect){
        if(mapped.effect!=="unknown") return mapped.effect;
      }
    }
    if(a.qEffectRefine){
      mapped=MAP.qEffectRefine[a.qEffectRefine]||{};
      return mapped.effect||"";
    }
    return "";
  }

  function resolvedLimit(){
    var a=state.answers;
    var mapped;
    if(a.q6){
      mapped=MAP.q6[a.q6]||{};
      if(mapped.limit){
        if(mapped.limit!=="unknown") return mapped.limit;
      }
    }
    if(a.qLimitRefine){
      mapped=MAP.qLimitRefine[a.qLimitRefine]||{};
      return mapped.limit||"";
    }
    return "";
  }

  function derivedLimitConfidence(){
    var a=state.answers;
    var q2;
    var q3=MAP.q3[a.q3]||{};
    var q4=MAP.q4[a.q4]||{};
    if(a.q2){
      if(a.q2!=="H") q2=MAP.q2[a.q2]||{};
    }
    if(!q2) q2={source:resolvedSource()};
    if(q2.source==="place") return 2;
    if(q2.source==="language") return 2;
    if(q3.medium==="return") return 2;
    if(q4.control==="low") return 2;
    return 1;
  }

  function completionGate(){
    var count=state.history.length;
    var source=resolvedSource();
    var effect=resolvedEffect();
    var limit=resolvedLimit();
    if(count<QUESTION_MIN) return false;
    if(!source) return false;
    if(!effect) return false;
    if(limit) return true;
    if(derivedLimitConfidence()>=2) return true;
    return false;
  }

  function chooseAdaptiveNeed(){
    var a=state.answers;
    var source=resolvedSource();
    var effect=resolvedEffect();
    var limit=resolvedLimit();

    if(!source){
      if(a.q2==="H"){
        if(!a.qSource) return "qSource";
        if(!a.qSourceFinal) return "qSourceFinal";
      }
    }

    if(!effect){
      if(!a.q5) return "q5";
      if(!a.qEffectRefine) return "qEffectRefine";
    }

    if(!limit){
      if(!a.q6) return "q6";
      if(!a.qLimitRefine) return "qLimitRefine";
    }

    return "";
  }

  function chooseNextQuestion(){
    var count=state.history.length;
    var next;

    if(!state.answers.q1) return "q1";
    if(!state.answers.q2) return "q2";
    if(!state.answers.q3) return "q3";
    if(!state.answers.q4) return "q4";

    if(count>=QUESTION_MAX) return "";

    next=chooseAdaptiveNeed();
    if(count<QUESTION_MIN){
      if(next) return next;
      if(!state.answers.q5) return "q5";
      if(!state.answers.q6) return "q6";
    }

    if(completionGate()) return "";
    if(next) return next;

    return "";
  }

  function goBack(){
    /* Adaptive back: remove current answer and every downstream branch answer. */
    var removed;
    var active={};
    var i;
    var key;

    if(state.history.length<=1){
      state.history=[];
      state.answers={};
      state.screen="entry";
      render();
      return;
    }

    removed=state.history.pop();
    delete state.answers[removed];

    for(i=0;i<state.history.length;i++){
      active[state.history[i]]=true;
    }

    for(key in state.answers){
      if(state.answers.hasOwnProperty(key)){
        if(!active[key]){
          delete state.answers[key];
        }
      }
    }

    render();
  }

  function renderStateSurface(stateName,title,copyText,actionsHtml){
    return ''+
      '<section class="tvm-screen" data-surface="content" data-elevation="s0">'+
        '<div class="tvm-state-surface is-entering" data-state="'+escapeHtml(stateName)+'" data-surface="transient" data-elevation="s2" data-glass="veil"'+(stateName==="error"?' role="alert" aria-live="assertive" aria-atomic="true"':' role="status" aria-live="polite" aria-atomic="true"')+'>'+
          '<p class="tvm-state-title"'+(stateName==="error"?' id="tvmErrorTitle"':'')+'>'+escapeHtml(title)+'</p>'+
          (copyText?'<p class="tvm-state-copy"'+(stateName==="error"?' id="tvmErrorDescription"':'')+'>'+escapeHtml(copyText)+'</p>':'')+
          (actionsHtml?'<div class="tvm-state-actions">'+actionsHtml+'</div>':'')+
        '</div>'+
      '</section>';
  }

  function renderErrorState(){
    var app=getApp();
    var u=currentUI();
    var actions;

    if(!app) return;

    setStageEnvironment("almost");

    actions=
      '<button type="button" class="tvm-btn is-primary tvm-control tvm-reactive" data-material="veil" data-surface="interface" data-elevation="s1" data-glass="veil" id="tvmRetry" aria-describedby="tvmErrorDescription">'+escapeHtml(u.retry)+'</button>'+
      '<button type="button" class="tvm-btn is-ghost tvm-control tvm-reactive" data-material="clear" data-surface="interface" data-elevation="s1" id="tvmErrorBack" aria-describedby="tvmErrorDescription">'+escapeHtml(u.back)+'</button>';

    app.innerHTML=
      chrome("almost")+
      renderStateSurface("error",u.error_title,u.error_help,actions);

    bindInteractionControls();

    if(byId("tvmRetry")){
      byId("tvmRetry").addEventListener("click",function(){
        finish();
      });
    }

    if(byId("tvmErrorBack")){
      byId("tvmErrorBack").addEventListener("click",function(){
        state.screen="question";
        render();
      });
    }
  }

  function mergeProfile(){
    var a=state.answers;
    var q1=MAP.q1[a.q1]||{};
    var q2;
    var q3=MAP.q3[a.q3]||{};
    var q4=MAP.q4[a.q4]||{};
    var effect=resolvedEffect();
    var limit=resolvedLimit();
    var source=resolvedSource();
    var ontology;

    if(a.q2){
      if(a.q2!=="H") q2=MAP.q2[a.q2]||{};
    }
    if(!q2) q2={source:source};

    if(!effect) effect=deriveEffect(q1.principle);
    if(!limit) limit=deriveLimit(source,q3.medium,q4.control);
    ontology=deriveOntology(q1.principle);

    return{
      schema_version:"2.0",
      magic_name:magicName(q1.principle),
      dominant_principle:{type:q1.principle||"unspecified"},
      source:{type:source||"unspecified",role:"origin"},
      access:{type:q3.access||"unspecified",role:"connection_condition"},
      medium:{type:q3.medium||"unspecified",role:"activation_action"},
      target:{type:q1.target||"unspecified",domain:"unspecified"},
      effect:{operation:effect||"unspecified",mode:"unspecified"},
      cost:{type:"none"},
      limit:buildLimit(limit||"unspecified"),
      control:{
        level:q4.control||"unspecified",
        scope:"outcome",
        dimensions:{
          activation:"unspecified",
          target_selection:"unspecified",
          range:"unspecified",
          intensity:"unspecified",
          temporal_selection:"unspecified"
        }
      },
      ontology:ontology,
      magic_core:buildCore(source,q3.access,q1.target,effect,limit,q4.control)
    };
  }

  function buildLimit(type){
    var out={type:type};
    if(type==="limited_uses"){
      out.quantity="unspecified";
      out.reset_rule="unspecified";
    }else if(type==="location_bound"){
      out.location_rule="unspecified";
    }else if(type==="target_bound"){
      out.allowed_target_rule="unspecified";
    }else if(type==="detail_uncontrolled"){
      out.uncontrolled_dimensions="unspecified";
    }else if(type==="timing_bound"){
      out.time_rule="unspecified";
    }else if(type==="cannot_target_self"){
      out.excluded_target="self";
    }else if(type==="nonrepeatable_on_same_target"){
      out.repeat_rule="once_per_target";
    }else if(type==="cooldown_required"){
      out.cooldown_duration="unspecified";
    }
    return out;
  }

  function deriveEffect(principle){
    if(principle==="revelation") return "reveal";
    if(principle==="recovery") return "restore";
    if(principle==="preservation") return "restore";
    if(principle==="anticipation") return "delay";
    if(principle==="transformation") return "transform";
    if(principle==="boundary") return "reveal";
    return "transform";
  }

  function deriveLimit(source,medium,control){
    if(source==="place") return "location_bound";
    if(medium==="return") return "nonrepeatable_on_same_target";
    if(medium==="voice") return "target_bound";
    if(source==="language") return "target_bound";
    if(control==="low") return "detail_uncontrolled";
    if(control==="conditional") return "detail_uncontrolled";
    return "limited_uses";
  }

  function deriveOntology(principle){
    var out={principle:"state_rule",reference:"unspecified",description:""};

    if(principle==="boundary"){
      out.principle="persistent_difference";
      out.reference="state_boundary";
      out.description=state.language==="en"?"A difference remains between two states instead of disappearing completely.":"二つの状態のあいだには、消えずに残る差分がある。";
    }else if(principle==="revelation"){
      out.principle="conditional_visibility";
      out.reference="hidden_state";
      out.description=state.language==="en"?"An unseen state surfaces only when the required conditions align.":"見えない状態は、条件がそろったときだけ表面に現れる。";
    }else if(principle==="recovery"){
      out.principle="persistent_connection";
      out.reference="loss_event";
      out.description=state.language==="en"?"What is lost never disappears completely and can be reconnected through a specific path.":"失われたものは完全には消えず、特定の経路からだけ再接続できる。";
    }else if(principle==="preservation"){
      out.principle="residual_difference";
      out.reference="event_state_difference";
      out.description=state.language==="en"?"What remains is preserved not as a complete form, but as a state difference associated with the event that produced the trace.":"残ったものは、完全な形ではなく、痕跡を生じさせた出来事の前後に生じた状態差として保持される。";
    }else if(principle==="anticipation"){
      out.principle="unrealized_variation";
      out.reference="possible_event";
      out.description=state.language==="en"?"Events that are not yet fixed can have the way they unfold shifted.":"まだ確定していない出来事は、進行の仕方をずらすことができる。";
    }else if(principle==="transformation"){
      out.principle="state_transition";
      out.reference="changing_state";
      out.description=state.language==="en"?"States are not fixed and may move into another form when conditions overlap.":"状態は固定されず、条件が重なると別の形へ移る。";
    }
    return out;
  }

  function magicName(principle){
    if(state.language==="en"){
      if(principle==="boundary") return "Interstice";
      if(principle==="revelation") return "Disclosure";
      if(principle==="recovery") return "Reconnection";
      if(principle==="preservation") return "Retention";
      if(principle==="anticipation") return "Foretrace";
      if(principle==="transformation") return "Phase Shift";
      return "Untitled";
    }
    if(principle==="boundary") return "間界";
    if(principle==="revelation") return "露呈";
    if(principle==="recovery") return "復片";
    if(principle==="preservation") return "留景";
    if(principle==="anticipation") return "先延";
    if(principle==="transformation") return "遷相";
    return "無題";
  }

  function buildCore(source,access,target,effect,limit,control){
    var sourceText=label("source",source);
    var accessText=label("access",access);
    var targetText=label("target",target);
    var effectText=label("effect",effect);
    var limitText=label("limit",limit);
    var controlText="";

    if(state.language==="en"){
      if(control==="high"){
        controlText="Most of the outcome can be intentionally determined.";
      }else if(control==="medium"){
        controlText="The overall direction can be chosen, but not every detail.";
      }else if(control==="conditional"){
        controlText="Part of the outcome remains open to chance.";
      }else{
        controlText="The final result cannot be fully known in advance.";
      }

      return(
        "This magic begins through "+accessText.toLowerCase()+".\n"+
        "Its power comes from "+sourceText.toLowerCase()+" and acts on "+targetText.toLowerCase()+". Its effect is to "+effectText.toLowerCase()+".\n"+
        "Its limit: "+limitText.toLowerCase()+".\n"+
        controlText
      );
    }

    if(control==="high"){
      controlText="起こす内容のほとんどを自分で決められる。";
    }else if(control==="medium"){
      controlText="起こす方向は選べるが、細部までは決められない。";
    }else if(control==="conditional"){
      controlText="結果の一部は偶然に残る。";
    }else{
      controlText="何が起きるかは最後まで完全には決められない。";
    }

    return(
      "この魔法は、"+accessText+"ことで始まる。\n"+
      sourceText+"を力の出所にして、"+targetText+"へ作用し、"+effectText+"。\n"+
      "ただし、"+limitText+"。\n"+
      controlText
    );
  }

  function yamlLine(key,value,indent){
    var spaces="";
    var i;
    var nl=String.fromCharCode(10);
    for(i=0;i<indent;i++) spaces+=" ";
    return spaces+key+": "+value+nl;
  }

  function profileYaml(p){
    var y="";
    var key;
    var nl=String.fromCharCode(10);
    y+="persona_magic_profile:"+nl;
    y+=yamlLine("schema_version",'"'+p.schema_version+'"',2);
    y+="  dominant_principle:"+nl+yamlLine("type",p.dominant_principle.type,4);
    y+="  source:"+nl+yamlLine("type",p.source.type,4)+yamlLine("role",p.source.role,4);
    y+="  access:"+nl+yamlLine("type",p.access.type,4)+yamlLine("role",p.access.role,4);
    y+="  medium:"+nl+yamlLine("type",p.medium.type,4)+yamlLine("role",p.medium.role,4);
    y+="  target:"+nl+yamlLine("type",p.target.type,4)+yamlLine("domain",p.target.domain,4);
    y+="  effect:"+nl+yamlLine("operation",p.effect.operation,4)+yamlLine("mode",p.effect.mode,4);
    y+="  cost:"+nl+yamlLine("type",p.cost.type,4);
    y+="  limit:"+nl;
    for(key in p.limit){
      if(p.limit.hasOwnProperty(key)) y+=yamlLine(key,p.limit[key],4);
    }
    y+="  control:"+nl+yamlLine("level",p.control.level,4)+yamlLine("scope",p.control.scope,4);
    y+="    dimensions:"+nl;
    for(key in p.control.dimensions){
      if(p.control.dimensions.hasOwnProperty(key)) y+=yamlLine(key,p.control.dimensions[key],6);
    }
    y+="  ontology:"+nl+yamlLine("principle",p.ontology.principle,4)+yamlLine("reference",p.ontology.reference,4)+yamlLine("description",'"'+p.ontology.description.replace(/"/g,'\\"')+'"',4);
    y+="  secondary_traits: []"+nl;
    y+="  aesthetic:"+nl;
    y+="    brightness: open"+nl+"    temperature: open"+nl+"    motion: open"+nl+"    order: open"+nl+"    density: open"+nl;
    y+="  derivation_policy:"+nl;
    y+="    unspecified_is_canon: false"+nl+"    derived_details_are_canon: false";
    return y;
  }

  function compactPrompt(language,yaml){
    var nl=String.fromCharCode(10);
    var lines=[];

    if(language==="en"){
      lines.push("Below is my Persona Magic Profile generated by https://TranquilGuides.com .");
      lines.push("Use the Profile as FIXED CORE for future generation. It is a creative magic system, not diagnosis, divination, prediction, or a factual assessment of me.");
      lines.push("");
      lines.push("Priority: FIXED CORE > legitimately accessible SUPPORTING CONTEXT > DERIVED INTERPRETATION > MANIFESTATION DETAIL. A lower layer never rewrites a higher one.");
      lines.push("Resolved Profile values are fixed. explicit unspecified / open values remain unresolved and may be concretized only for the current artifact unless I adopt them.");
      lines.push("");
      lines.push("[PERSONA MAGIC PROFILE]");
      lines.push(yaml);
      lines.push("[/PERSONA MAGIC PROFILE]");
      lines.push("");
      lines.push("Read fields causally: SOURCE -> ACCESS -> MEDIUM -> TARGET -> EFFECT -> LIMIT/COST -> CONTROL, explained by ONTOLOGY. Keep SOURCE, ACCESS, and MEDIUM distinct. COST and LIMIT are separate; cost.type=none forbids invented activation prices. Do not infer unspecified target domains, effect modes, control dimensions, quantities, reset cycles, range, or other canon.");
      lines.push("Use accessible prior context only to shape open manifestation details. Do not fabricate biography, psychology, diagnosis, motives, preferences, or sensitive personal facts. Do not add stock magic imagery merely because it feels magical, and do not imitate existing IP.");
      lines.push("Generate one concrete artifact immediately without asking what format to use. First choose one Artifact Type, then one Output Form. Preserve the same magic law across media. If a chosen form is unavailable, keep Artifact Type fixed and change only Output Form to the nearest available form or a production-ready text specification.");
      lines.push("The first artifact must show the magic operating, not merely summarize settings. Use the smallest scale that demonstrates the law. Any new person, place, object, event, name, color, sound, number, tool, or staging remains MANIFESTATION DETAIL until I adopt it.");
      lines.push("Before output, verify that FIXED CORE was not rewritten, unresolved values were not canonized, ONTOLOGY is respected, hidden costs were not added, and SOURCE / ACCESS / MEDIUM remain distinct.");
      return lines.join(nl);
    }

    lines.push("以下は、 https://TranquilGuides.com で生成した私専用のPersona Magic Profileです。");
    lines.push("このProfileを今後の生成におけるFIXED COREとして使用してください。これは診断・占い・能力判定ではなく、創作上の魔法体系です。");
    lines.push("");
    lines.push("優先順位は FIXED CORE > 正当に参照できるSUPPORTING CONTEXT > DERIVED INTERPRETATION > MANIFESTATION DETAIL。下位層から上位層を書き換えません。");
    lines.push("Profileの確定値は固定です。明示的なunspecified / openだけが未確定で、一例のために具体化しても、私が採用しない限り固定設定へ昇格させません。");
    lines.push("");
    lines.push("[PERSONA MAGIC PROFILE]");
    lines.push(yaml);
    lines.push("[/PERSONA MAGIC PROFILE]");
    lines.push("");
    lines.push("各Fieldは因果として読みます。SOURCE → ACCESS → MEDIUM → TARGET → EFFECT → LIMIT/COST → CONTROL をONTOLOGYが説明します。SOURCE / ACCESS / MEDIUMを同義化しません。COSTとLIMITを分け、cost.type=noneなら隠れた代償を追加しません。未指定のtarget domain、effect mode、control dimension、回数、reset、射程等を固定設定として発明しません。");
    lines.push("正当に参照できる既存文脈は、未確定な具現化の補助にだけ使えます。経歴・心理・診断・動機・嗜好・センシティブ情報を捏造しません。『魔法らしさ』だけを理由に定番記号を追加せず、既存IPへ寄せません。");
    lines.push("追加質問をせず、まず一つの具体的成果物を生成してください。内部でArtifact Typeを一つ選び、その後Output Formを一つ選びます。媒体が変わっても魔法法則は変えません。形式を直接生成できない場合はArtifact Typeを維持し、近いOutput Formまたはproduction-ready TEXT SPECへFallbackします。");
    lines.push("最初の成果物は設定要約ではなく、魔法が一度成立したと分かる具体物にします。法則を示せる最小スケールを優先し、新しい人物・場所・物・出来事・名前・色・音・数値・道具・演出は、私が採用するまでMANIFESTATION DETAILです。");
    lines.push("出力前に、FIXED COREを変更していないこと、未確定値をcanon化していないこと、ONTOLOGYと矛盾しないこと、隠れたCOSTを足していないこと、SOURCE / ACCESS / MEDIUMを区別していることを内部確認してください。");
    return lines.join(nl);
  }

  function minimalPrompt(language,yaml){
    var nl=String.fromCharCode(10);
    var head;
    var tail;

    if(language==="en"){
      head="Use this Persona Magic Profile as FIXED CORE. It is a creative magic system, not an assessment of me. Resolved values are fixed; only explicit unspecified/open values are unresolved. Never let context or manifestation details rewrite the Profile.";
      tail="Read causally as SOURCE -> ACCESS -> MEDIUM -> TARGET -> EFFECT -> LIMIT/COST -> CONTROL under ONTOLOGY. Keep SOURCE/ACCESS/MEDIUM distinct; never invent hidden COST, unspecified domains/modes/control dimensions, quantities, resets, or range as canon. Use legitimate context only for open manifestation details and fabricate no personal facts. Without asking first, generate one concrete artifact that demonstrates the magic. Choose Artifact Type, then an available Output Form; if necessary, keep Artifact Type and fallback only the Output Form. New implementation details remain non-canon unless I adopt them.";
    }else{
      head="このPersona Magic ProfileをFIXED COREとして使用してください。これは私の診断ではなく創作上の魔法体系です。確定値は固定し、明示的なunspecified/openだけを未確定として扱い、既存文脈や今回の具現化からProfileを書き換えないでください。";
      tail="SOURCE → ACCESS → MEDIUM → TARGET → EFFECT → LIMIT/COST → CONTROL をONTOLOGYの下で因果として読み、SOURCE/ACCESS/MEDIUMを区別してください。隠れたCOST、未指定のdomain/mode/control dimension、回数、reset、射程等をcanon化しません。正当に参照できる文脈は未確定な具現化の補助にだけ使い、個人的事実を捏造しません。追加質問をせず、魔法が一度成立したと分かる具体的成果物を一つ生成してください。Artifact Typeを決めてから利用可能なOutput Formを選び、不可ならArtifact Typeを変えずOutput FormだけFallbackします。今回補った具体化は、私が採用するまで非canonです。";
    }

    return head+nl+nl+"[PERSONA MAGIC PROFILE]"+nl+yaml+nl+"[/PERSONA MAGIC PROFILE]"+nl+nl+tail;
  }

  function buildPrompt(p){
    var template=getPromptTemplate(state.language);
    var yaml=profileYaml(p);
    var prompt;

    if(template){
      prompt=template.split("{{PERSONA_MAGIC_PROFILE}}").join(yaml);
      if(prompt.length<=PROMPT_MAX_CHARACTERS) return prompt;
    }

    prompt=compactPrompt(state.language,yaml);
    if(prompt.length<=PROMPT_MAX_CHARACTERS) return prompt;

    prompt=minimalPrompt(state.language,yaml);
    if(prompt.length<=PROMPT_MAX_CHARACTERS) return prompt;

    throw new Error("Prompt exceeds "+PROMPT_MAX_CHARACTERS+" characters without a safe fixed-core-preserving compression path.");
  }

  function finish(){
    try{
    state.profile=mergeProfile();
    state.prompt=buildPrompt(state.profile);
    state.screen="result";
    render();
    }catch(error){
      console.warn("[Tranquilvæj Magic] profile assembly failed.",error);
      state.screen="error";
      renderErrorState();
    }
  }

  function currentPageUrl(){
    var canonical;
    var href="";

    try{
      canonical=document.querySelector('link[rel="canonical"]');
      if(canonical){
        href=canonical.getAttribute("href")||"";
      }
      if(!href){
        href=window.location.href||"";
      }
    }catch(error){
      href="";
    }

    if(href.indexOf("about:")===0) return "";
    return href;
  }

  function normalizeShareText(text,maxLength){
    var value=String(text||"");
    value=value.replace(/\r/g,"");
    value=value.replace(/[ \t]+/g," ");
    value=value.replace(/\n[ \t]+/g,"\n");
    value=value.replace(/\n{3,}/g,"\n\n");
    value=value.replace(/^\s+|\s+$/g,"");

    if(maxLength){
      if(value.length>maxLength){
        value=value.substring(0,maxLength-1)+"…";
      }
    }

    return value;
  }

  function magicShareParts(profile){
    var coreLines=String(profile.magic_core||"").split("\n");
    var name=String(profile.magic_name||(state.language==="en"?"Untitled":"無題"));
    var first=coreLines.length>0?normalizeShareText(coreLines[0],120):"";
    var second=coreLines.length>1?normalizeShareText(coreLines[1],170):"";
    var core=normalizeShareText(String(profile.magic_core||""),0);

    return{
      name:name,
      first:first,
      second:second,
      core:core
    };
  }

  function standardShareText(profile,maxLength){
    var p=magicShareParts(profile);
    var text="";

    if(state.language==="en"){
      text='My magic is "'+p.name+'". ';
      if(p.first) text+=p.first+" ";
      if(p.second) text+=p.second+" ";
      text+="What is your magic?";
    }else{
      text='私の魔法は「'+p.name+'」。';
      if(p.first) text+=p.first;
      if(p.second) text+=p.second;
      text+="あなたの魔法は？";
    }

    return normalizeShareText(text,maxLength||0);
  }

  function xShareText(profile){
    var p=magicShareParts(profile);
    var url=currentPageUrl();
    var coreFirst=p.first;
    var coreSecond=p.second;
    var footer;
    var text;

    if(state.language==="en"){
      footer="@chaos_color #TakumiIIDA #TranquilGuides";
      text='My magic is "'+p.name+'". ';
      if(coreFirst) text+=coreFirst+" ";
      if(coreSecond) text+=coreSecond+" ";
      text+="What is your magic? "+footer;
    }else{
      footer="@chaos_color #TakumiIIDA #TranquilGuides";
      text='私の魔法は「'+p.name+'」。';
      if(coreFirst) text+=coreFirst;
      if(coreSecond) text+=coreSecond;
      text+="あなたの魔法は？ "+footer;
    }
    if(url) text+=" "+url;

    /* Keep X inside its hard limit without a blind substring cut. The full
       requested form is preserved whenever it fits; if a generated result is
       unusually long, the second core sentence is the first removable part. */
    if(text.length>280){
      if(state.language==="en"){
        text='My magic is "'+p.name+'". ';
        if(coreFirst) text+=coreFirst+" ";
        text+="What is your magic? "+footer;
      }else{
        text='私の魔法は「'+p.name+'」。';
        if(coreFirst) text+=coreFirst;
        text+="あなたの魔法は？ "+footer;
      }
      if(url) text+=" "+url;
    }

    return normalizeShareText(text,280);
  }

  function serviceShareText(profile,service){
    var p=magicShareParts(profile);
    var url=currentPageUrl();
    var text="";

    if(service==="x") return xShareText(profile);

    if(state.language==="en"){
      text='My magic is "'+p.name+'". ';
      if(p.first) text+=p.first+" ";
      if(p.second) text+=p.second+" ";
      text+="What is your magic? ";
      if(service==="bluesky"){
        text+="@chaoscolor.bsky.social #TakumiIIDA #Tranquilvæj #TranquilGuides";
      }else if(service==="threads"){
        text+="@chaos_color";
      }
    }else{
      text='私の魔法は「'+p.name+'」。';
      if(p.first) text+=p.first;
      if(p.second) text+=p.second;
      text+="あなたの魔法は？ ";
      if(service==="bluesky"){
        text+="@chaoscolor.bsky.social #TakumiIIDA #Tranquilvæj #TranquilGuides";
      }else if(service==="threads"){
        text+="@chaos_color";
      }
    }

    if(url) text+=" "+url;
    return normalizeShareText(text,0);
  }

  function resultCopyText(profile){
    var u=currentUI();
    var lines=[];
    var name=String(profile.magic_name||(state.language==="en"?"Untitled":"無題"));
    var sep=state.language==="en"?": ":"：";
    var url=currentPageUrl();

    lines.push(name);
    lines.push("");

    if(profile.magic_core){
      lines.push(String(profile.magic_core));
    }

    lines.push("");
    lines.push(u.summary_title);
    lines.push(u.principle+sep+label("principle",profile.dominant_principle.type));
    lines.push(u.source+sep+label("source",profile.source.type));
    lines.push(u.starting+sep+label("medium",profile.medium.type));
    lines.push(u.change+sep+label("effect",profile.effect.operation));
    lines.push(u.limit+sep+label("limit",profile.limit.type));
    lines.push(u.access+sep+label("access",profile.access.type));
    lines.push(u.target+sep+label("target",profile.target.type));
    lines.push(u.control+sep+label("control",profile.control.level));
    lines.push(u.ontology+sep+String(profile.ontology.description||""));
    lines.push("");
    lines.push(state.language==="en"?"What is your magic?":"あなたの魔法は？");
    lines.push("");
    lines.push("@chaos_color #TakumiIIDA #Tranquilvæj #TranquilGuides");

    if(url){
      lines.push("");
      lines.push(url);
    }

    return normalizeShareText(lines.join("\n"),0);
  }

  function openShareWindow(url,width,height){
    var features="noopener,noreferrer,menubar=no,toolbar=no,resizable=yes,scrollbars=yes";
    var popup;
    if(width) features+=",width="+width;
    if(height) features+=",height="+height;
    popup=window.open(url,"_blank",features);
    if(popup){
      try{
        popup.opener=null;
      }catch(error){}
    }
  }

  function shareX(profile){
    var text=serviceShareText(profile,"x");
    openShareWindow("https://twitter.com/intent/tweet?text="+encodeURIComponent(text),600,400);
  }

  function shareThreads(profile){
    var text=serviceShareText(profile,"threads");
    openShareWindow("https://www.threads.com/intent/post?text="+encodeURIComponent(text),640,720);
  }

  function shareBluesky(profile){
    var text=serviceShareText(profile,"bluesky");
    openShareWindow("https://bsky.app/intent/compose?text="+encodeURIComponent(text),640,720);
  }

  function shareLine(profile){
    var url=currentPageUrl();
    var text=standardShareText(profile,0);
    var href="https://social-plugins.line.me/lineit/share";
    var query=[];

    if(text) query.push("text="+encodeURIComponent(text));
    if(url) query.push("url="+encodeURIComponent(url));
    if(query.length>0) href+="?"+query.join("&");

    openShareWindow(href,720,720);
  }

  function shareNative(profile){
    var u=currentUI();
    var payload={
      title:String(profile.magic_name||""),
      text:standardShareText(profile,0)
    };
    var url=currentPageUrl();

    if(url) payload.url=url;

    if(navigator.share){
      navigator.share(payload).catch(function(error){
        if(error){
          if(error.name==="AbortError") return;
        }
        showToast(u.share_failed);
      });
      return;
    }

    copyShareResult(profile,null);
  }

  function shareCapabilityRegistry(profile){
    return {
      x:{
        available:true,
        run:function(){return shareX(profile);}
      },
      threads:{
        available:true,
        run:function(){return shareThreads(profile);}
      },
      bluesky:{
        available:true,
        run:function(){return shareBluesky(profile);}
      },
      line:{
        available:true,
        run:function(){return shareLine(profile);}
      },
      native:{
        available:!!navigator.share,
        run:function(){return shareNative(profile);}
      },
      copy:{
        available:true,
        run:function(button){return copyShareResult(profile,button);}
      },
      story:{
        available:true,
        run:function(button){return createMagicStoryCard(profile,button);}
      }
    };
  }

  function applyShareCapabilities(row,profile){
    var registry=shareCapabilityRegistry(profile);
    var buttons=row.querySelectorAll("[data-share-action]");
    var i;
    var action;
    var config;

    for(i=0;i<buttons.length;i++){
      action=buttons[i].getAttribute("data-share-action");
      config=registry[action];
      if(config){
        if(config.available===false){
          buttons[i].hidden=true;
          buttons[i].setAttribute("aria-hidden","true");
        }else{
          buttons[i].hidden=false;
          buttons[i].removeAttribute("aria-hidden");
        }
      }
    }

    row._tvmShareRegistry=registry;
    return registry;
  }

  function setCopyVisualState(button,copied){
    var u=currentUI();

    if(!button) return;

    if(button._tvmCopyStateTimer){
      window.clearTimeout(button._tvmCopyStateTimer);
      button._tvmCopyStateTimer=0;
    }

    if(copied){
      button.classList.add("is-copied");
      button.setAttribute("aria-label",u.share_copy_done);
      button.setAttribute("data-tooltip",u.share_copy_done);
      button._tvmCopyStateTimer=window.setTimeout(function(){
        if(!button.isConnected) return;
        button.classList.remove("is-copied");
        button.setAttribute("aria-label",u.share_copy);
        button.setAttribute("data-tooltip",u.share_copy);
        button._tvmCopyStateTimer=0;
      },1800);
    }else{
      button.classList.remove("is-copied");
      button.setAttribute("aria-label",u.share_copy);
      button.setAttribute("data-tooltip",u.share_copy);
    }
  }

  function copyShareResult(profile,button){
    var u=currentUI();
    return copyText(resultCopyText(profile)).then(function(){
      setCopyVisualState(button,true);
      showToast(u.share_copied);
      return true;
    }).catch(function(error){
      setCopyVisualState(button,false);
      showToast(u.share_failed,u.recovery_retry,function(){
        copyShareResult(profile,button);
      });
      reportRecovery(error,"copyResult",false,function(){
        return copyShareResult(profile,button);
      });
      return false;
    });
  }

  function setShareBusy(button,busy){
    setBusyControl(button,busy);
  }

  function downloadBlob(blob,filename){
    var link=document.createElement("a");
    var url;

    try{
      url=URL.createObjectURL(blob);
      link.href=url;
      link.download=filename;
      link.style.display="none";
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.setTimeout(function(){
        URL.revokeObjectURL(url);
      },1000);
      return true;
    }catch(error){
      if(link.parentNode){
        link.parentNode.removeChild(link);
      }
      return false;
    }
  }

  function canvasToBlob(canvas,callback){
    if(canvas.toBlob){
      canvas.toBlob(function(blob){
        callback(blob);
      },"image/png");
      return;
    }

    try{
      var data=canvas.toDataURL("image/png");
      var bin=window.atob(data.split(",")[1]);
      var bytes=new Uint8Array(bin.length);
      var i;
      for(i=0;i<bin.length;i++){
        bytes[i]=bin.charCodeAt(i);
      }
      callback(new Blob([bytes],{type:"image/png"}));
    }catch(error){
      callback(null);
    }
  }

  function wrapCanvasText(ctx,text,maxWidth){
    var source=String(text);
    var tokens;
    var separator="";
    var lines=[];
    var line="";
    var i;
    var token;
    var test;

    if(source.indexOf(" ")>=0){
      tokens=source.split(" ");
      separator=" ";
    }else{
      tokens=source.split("");
    }

    for(i=0;i<tokens.length;i++){
      token=tokens[i];

      if(token.indexOf("\n")>=0){
        token=token.replace(/\n/g,"");
        if(token){
          test=line?(line+separator+token):token;
          if(ctx.measureText(test).width<=maxWidth){
            line=test;
          }
        }
        if(line) lines.push(line);
        line="";
        continue;
      }

      test=line?(line+separator+token):token;
      if(ctx.measureText(test).width>maxWidth){
        if(line) lines.push(line);
        line=token;
      }else{
        line=test;
      }
    }

    if(line) lines.push(line);
    return lines;
  }

  /* =========================================================
     Story image — Canvas 2D / PNG / no SVG
     1080 × 1920. The generated image is a portable result:
     save it, revisit it, show it, or share it.

     Typography contract inside the image:
     - Magic name: independent responsive size.
     - URL: independent fixed size.
     - Every other text element uses exactly three base sizes:
       LARGE 32px / MEDIUM 25px / SMALL 20px.
     Weight and line-height are style properties, not extra sizes.
     ========================================================= */
  var STORY_TEXT_LARGE=32;
  var STORY_TEXT_MEDIUM=25;
  var STORY_TEXT_SMALL=20;
  var STORY_TEXT_COLOR="#F4F1EA";

  function storyFont(size,weight){
    return String(weight||400)+" "+String(size)+'px -apple-system,BlinkMacSystemFont,"Hiragino Sans","Yu Gothic",sans-serif';
  }

  function storyLineHeight(size){
    if(size===STORY_TEXT_LARGE) return Math.round(size*1.65);
    if(size===STORY_TEXT_MEDIUM) return Math.round(size*1.60);
    return Math.round(size*1.55);
  }

  function fitCanvasTitle(ctx,text,maxWidth,maxLines){
    var size=92;
    var lines=[];

    while(size>=56){
      ctx.font=storyFont(size,600);
      lines=wrapCanvasText(ctx,text,maxWidth);
      if(lines.length<=maxLines) break;
      size-=4;
    }

    return{
      size:size,
      lines:lines
    };
  }

  function storyHash(text){
    var source=String(text||"");
    var hash=2166136261;
    var i;
    for(i=0;i<source.length;i++){
      hash^=source.charCodeAt(i);
      hash+=(hash<<1)+(hash<<4)+(hash<<7)+(hash<<8)+(hash<<24);
    }
    return hash>>>0;
  }

  function storyPalette(profile){
    var principle=String(profile.dominant_principle.type||"");
    var source=String(profile.source.type||"");
    var effect=String(profile.effect.operation||"");
    var key=principle+"|"+source+"|"+effect;
    var h=storyHash(key)%360;
    var warm=(h+28)%360;
    var cool=(h+204)%360;
    return{
      paper:"hsl("+warm+", 20%, 94%)",
      glow:"hsla("+warm+", 52%, 76%, .34)",
      veil:"hsla("+cool+", 24%, 74%, .18)",
      trace:"hsla("+h+", 34%, 54%, .17)",
      ink:"#202624",
      muted:"rgba(32,38,36,.52)"
    };
  }

  function storyManifestAnchor(profile){
    var source=String(profile.source.type||"");
    if(source==="self") return{x:850,y:320};
    if(source==="place") return{x:845,y:710};
    if(source==="relation") return{x:760,y:600};
    if(source==="object") return{x:880,y:1010};
    if(source==="language") return{x:760,y:420};
    if(source==="accumulated_time") return{x:820,y:1230};
    if(source==="relational_field") return{x:760,y:820};
    return{x:850,y:940};
  }

  function storyControlFactor(profile){
    var level=String(profile.control.level||"");
    if(level==="high") return .92;
    if(level==="medium") return .72;
    if(level==="conditional") return .56;
    return .42;
  }

  function drawStoryPrincipleMotif(ctx,profile,palette,seed){
    var principle=String(profile.dominant_principle.type||"");
    var effect=String(profile.effect.operation||"");
    var limit=String(profile.limit.type||"");
    var anchor=storyManifestAnchor(profile);
    var control=storyControlFactor(profile);
    var i;
    var count=6;
    var radius;
    var x;
    var y;
    var phase;

    if(limit==="limited_uses") count=5;
    if(limit==="nonrepeatable_on_same_target") count=4;
    if(limit==="cooldown_required") count=5;
    if(limit==="timing_bound") count=3;

    ctx.save();
    ctx.globalCompositeOperation="source-over";
    ctx.lineCap="round";
    ctx.lineJoin="round";

    if(principle==="preservation"){
      /* Preservation appears as retained traces rather than a target-like
         stack of circles: several incomplete echoes remain in place. */
      ctx.strokeStyle=palette.trace;
      ctx.lineWidth=1.5;
      for(i=0;i<count;i++){
        radius=58+(i*38);
        ctx.beginPath();
        ctx.arc(anchor.x-(i*5),anchor.y+(i*4),radius,-2.55,.72-(i*.05));
        ctx.globalAlpha=.20+(control*.10)-(i*.015);
        ctx.stroke();
      }
      ctx.fillStyle=palette.veil;
      ctx.globalAlpha=.18+(control*.08);
      ctx.beginPath();
      ctx.ellipse(anchor.x-34,anchor.y+18,118,72,-.22,0,Math.PI*2);
      ctx.fill();
    }else if(principle==="recovery"){
      ctx.strokeStyle=palette.trace;
      ctx.globalAlpha=.58;
      ctx.lineWidth=2;
      for(i=0;i<count;i++){
        radius=80+(i*38);
        ctx.beginPath();
        ctx.arc(anchor.x,anchor.y,radius,-2.6,.55);
        ctx.stroke();
      }
      ctx.beginPath();
      ctx.moveTo(anchor.x-235,anchor.y+10);
      ctx.quadraticCurveTo(anchor.x-95,anchor.y-95,anchor.x-28,anchor.y-12);
      ctx.stroke();
    }else if(principle==="anticipation"){
      ctx.strokeStyle=palette.trace;
      ctx.globalAlpha=.56;
      ctx.lineWidth=2;
      for(i=0;i<count;i++){
        ctx.beginPath();
        ctx.moveTo(anchor.x-210+(i*18),anchor.y+120-(i*26));
        ctx.quadraticCurveTo(anchor.x-20,anchor.y-70-(i*10),anchor.x+235,anchor.y-130+(i*16));
        ctx.stroke();
      }
    }else if(principle==="revelation"){
      for(i=0;i<count;i++){
        radius=34+(i*42);
        ctx.beginPath();
        ctx.arc(anchor.x,anchor.y,radius,-1.15,1.15);
        ctx.strokeStyle=palette.trace;
        ctx.globalAlpha=.42+(control*.16);
        ctx.lineWidth=2;
        ctx.stroke();
      }
      ctx.beginPath();
      ctx.arc(anchor.x,anchor.y,18,0,Math.PI*2);
      ctx.fillStyle=palette.glow;
      ctx.globalAlpha=.82;
      ctx.fill();
    }else if(principle==="transformation"){
      for(i=0;i<count;i++){
        seed=(seed*1664525+1013904223)>>>0;
        phase=(seed%360)*(Math.PI/180);
        x=anchor.x+Math.cos(phase)*(80+(i*34));
        y=anchor.y+Math.sin(phase)*(55+(i*30));
        ctx.beginPath();
        ctx.ellipse(x,y,30+(i*8),18+(i*6),phase,0,Math.PI*2);
        ctx.fillStyle=i%2===0?palette.trace:palette.veil;
        ctx.globalAlpha=.27+(control*.13);
        ctx.fill();
      }
    }else if(principle==="boundary"){
      ctx.strokeStyle=palette.trace;
      ctx.globalAlpha=.52;
      ctx.lineWidth=2;
      for(i=0;i<count;i++){
        ctx.beginPath();
        ctx.moveTo(anchor.x-220+(i*30),anchor.y-180);
        ctx.lineTo(anchor.x-80+(i*30),anchor.y+210);
        ctx.stroke();
      }
    }else{
      for(i=0;i<count;i++){
        radius=28+(i*35);
        ctx.beginPath();
        ctx.arc(anchor.x,anchor.y,radius,0,Math.PI*2);
        ctx.fillStyle=palette.trace;
        ctx.globalAlpha=.18;
        ctx.fill();
      }
    }

    /* Effect changes the trace without changing the fixed magic law. */
    ctx.strokeStyle=palette.trace;
    ctx.fillStyle=palette.trace;
    ctx.globalAlpha=.48;
    ctx.lineWidth=2;
    if(effect==="restore"){
      ctx.beginPath();
      ctx.arc(anchor.x+30,anchor.y+300,170,-2.45,.48);
      ctx.stroke();
    }else if(effect==="erase"){
      for(i=0;i<4;i++){
        ctx.fillRect(anchor.x-150+(i*74),anchor.y+270,44,2);
      }
    }else if(effect==="overlay"){
      ctx.beginPath();
      ctx.arc(anchor.x-35,anchor.y+300,90,0,Math.PI*2);
      ctx.stroke();
      ctx.beginPath();
      ctx.arc(anchor.x+55,anchor.y+300,90,0,Math.PI*2);
      ctx.stroke();
    }else if(effect==="transfer"){
      ctx.beginPath();
      ctx.moveTo(anchor.x-175,anchor.y+305);
      ctx.bezierCurveTo(anchor.x-65,anchor.y+240,anchor.x+80,anchor.y+360,anchor.x+205,anchor.y+285);
      ctx.stroke();
    }else if(effect==="delay"){
      for(i=0;i<5;i++){
        ctx.beginPath();
        ctx.arc(anchor.x-120+(i*60),anchor.y+300,12,0,Math.PI*2);
        ctx.fill();
      }
    }else if(effect==="divide"){
      ctx.beginPath();
      ctx.moveTo(anchor.x-120,anchor.y+230);
      ctx.lineTo(anchor.x+120,anchor.y+370);
      ctx.moveTo(anchor.x+120,anchor.y+230);
      ctx.lineTo(anchor.x-120,anchor.y+370);
      ctx.stroke();
    }else if(effect==="reveal"){
      ctx.beginPath();
      ctx.arc(anchor.x,anchor.y+300,88,-.9,.9);
      ctx.stroke();
      ctx.beginPath();
      ctx.arc(anchor.x,anchor.y+300,13,0,Math.PI*2);
      ctx.fill();
    }else if(effect==="transform"){
      ctx.beginPath();
      ctx.ellipse(anchor.x-55,anchor.y+300,72,42,-.4,0,Math.PI*2);
      ctx.stroke();
      ctx.beginPath();
      ctx.ellipse(anchor.x+70,anchor.y+300,48,82,.5,0,Math.PI*2);
      ctx.stroke();
    }

    ctx.restore();
  }

  function storyUsableImageUrl(url){
    var a;
    if(!url) return "";
    try{
      a=document.createElement("a");
      a.href=url;
      if(a.protocol!=="http:"){
        if(a.protocol!=="https:") return "";
      }
      return a.href;
    }catch(error){
      return "";
    }
  }

  function resolveStoryImageSource(){
    var root=getRoot();
    var value="";
    var meta;
    var image;

    if(root){
      value=root.getAttribute("data-story-image")||"";
      value=storyUsableImageUrl(value);
      if(value) return value;
    }

    meta=document.querySelector('meta[property="og:image"]');
    if(meta){
      value=storyUsableImageUrl(meta.getAttribute("content")||"");
      if(value) return value;
    }

    meta=document.querySelector('meta[name="twitter:image"]');
    if(meta){
      value=storyUsableImageUrl(meta.getAttribute("content")||"");
      if(value) return value;
    }

    image=document.querySelector(".wp-post-image, .p-articleThumb img, .c-postThumb__figure img, article .wp-block-post-featured-image img");
    if(image){
      value=image.currentSrc||image.src||"";
      value=storyUsableImageUrl(value);
      if(value) return value;
    }

    return "";
  }

  function drawStoryImageCover(ctx,image){
    var cw=1080;
    var ch=1920;
    var iw=image.naturalWidth||image.width;
    var ih=image.naturalHeight||image.height;
    var scale;
    var sw;
    var sh;
    var sx;
    var sy;

    if(!iw) return;
    if(!ih) return;

    scale=Math.max(cw/iw,ch/ih);
    sw=cw/scale;
    sh=ch/scale;
    sx=(iw-sw)/2;
    sy=(ih-sh)/2;

    ctx.save();
    if("filter" in ctx){
      ctx.filter="blur(2px) saturate(.84) contrast(.98)";
    }
    ctx.globalAlpha=.86;
    ctx.drawImage(image,sx,sy,sw,sh,0,0,cw,ch);
    if("filter" in ctx){ctx.filter="none";}
    ctx.restore();

    /* Readability veil uses the same ink family as the typography.
       It deliberately suppresses photographic contrast so typography remains primary. */
    ctx.save();
    ctx.fillStyle="rgba(20,24,23,.50)";
    ctx.fillRect(0,0,cw,ch);

    /* A second, broad ink-family gradient suppresses the busiest upper/middle
       image zones without creating a card or local text panel. */
    var readability=ctx.createLinearGradient(0,0,0,ch);
    readability.addColorStop(0,"rgba(20,24,23,.15)");
    readability.addColorStop(.48,"rgba(20,24,23,.10)");
    readability.addColorStop(.72,"rgba(20,24,23,.04)");
    readability.addColorStop(1,"rgba(20,24,23,0)");
    ctx.fillStyle=readability;
    ctx.fillRect(0,0,cw,ch);
    ctx.restore();
  }

  function drawStoryAbstractField(ctx,profile,palette,seed,withImage){
    var lightA;
    var lightB;
    var shadow;
    var i;
    var x;
    var y;
    var r;
    var fieldAlpha=withImage?0.82:1;

    lightA=ctx.createRadialGradient(900,250,20,900,250,650);
    lightA.addColorStop(0,withImage?"rgba(255,244,214,.22)":palette.glow);
    lightA.addColorStop(.58,withImage?"rgba(255,255,255,.08)":"rgba(255,255,255,.16)");
    lightA.addColorStop(1,"rgba(255,255,255,0)");
    ctx.save();
    ctx.globalAlpha=fieldAlpha;
    ctx.fillStyle=lightA;
    ctx.fillRect(300,0,780,980);
    ctx.restore();

    lightB=ctx.createRadialGradient(220,1530,20,220,1530,760);
    lightB.addColorStop(0,withImage?"rgba(190,203,202,.13)":palette.veil);
    lightB.addColorStop(.65,"rgba(255,255,255,.05)");
    lightB.addColorStop(1,"rgba(255,255,255,0)");
    ctx.save();
    ctx.globalAlpha=fieldAlpha;
    ctx.fillStyle=lightB;
    ctx.fillRect(0,820,900,1100);
    ctx.restore();

    shadow=ctx.createLinearGradient(0,0,1080,0);
    shadow.addColorStop(0,"rgba(32,38,36,0)");
    shadow.addColorStop(.46,withImage?"rgba(32,38,36,.025)":"rgba(32,38,36,.035)");
    shadow.addColorStop(.72,withImage?"rgba(32,38,36,.06)":"rgba(32,38,36,.085)");
    shadow.addColorStop(1,"rgba(32,38,36,0)");
    ctx.save();
    ctx.globalAlpha=fieldAlpha;
    ctx.fillStyle=shadow;
    ctx.fillRect(0,0,1080,1920);
    ctx.restore();

    /* Blurred residue: visible enough to be part of the record, never a panel. */
    ctx.save();
    ctx.globalAlpha=withImage?0.24:0.44;
    if("filter" in ctx){ctx.filter=withImage?"blur(24px)":"blur(17px)";}
    for(i=0;i<4;i++){
      seed=(seed*1664525+1013904223)>>>0;
      x=65+(seed%390);
      seed=(seed*1664525+1013904223)>>>0;
      y=1320+(seed%410);
      seed=(seed*1664525+1013904223)>>>0;
      r=62+(seed%110);
      ctx.beginPath();
      ctx.ellipse(x,y,r,Math.max(38,Math.round(r*.56)),-.34+(i*.14),0,Math.PI*2);
      ctx.fillStyle=i%2===0?palette.trace:palette.veil;
      ctx.fill();
    }
    if("filter" in ctx){ctx.filter="none";}
    ctx.restore();
  }

  function drawStoryBackground(ctx,profile,image){
    var palette=storyPalette(profile);
    var bg=ctx.createLinearGradient(0,0,1080,1920);
    var seed=storyHash(String(profile.magic_name||"")+"|"+String(profile.ontology.principle||"")+"|"+String(profile.target.type||""));
    var i;
    var hasImage=false;

    bg.addColorStop(0,palette.paper);
    bg.addColorStop(.48,"#f3f1eb");
    bg.addColorStop(1,"#eceae4");
    ctx.fillStyle=bg;
    ctx.fillRect(0,0,1080,1920);

    if(image){
      if(image.naturalWidth){
        if(image.naturalHeight){
          hasImage=true;
          drawStoryImageCover(ctx,image);
        }
      }
    }

    drawStoryAbstractField(ctx,profile,palette,seed,hasImage);

    /* Medium / access / target remain secondary traces. They become slightly
       stronger when no eye-catch is available, and quieter over photography. */
    ctx.save();
    ctx.strokeStyle=palette.trace;
    ctx.fillStyle=palette.trace;
    ctx.lineWidth=1.25;
    ctx.globalAlpha=hasImage?0.20:0.40;

    if(String(profile.medium.type||"")==="touch"){
      ctx.beginPath();
      ctx.arc(800,1035,20,0,Math.PI*2);
      ctx.arc(800,1035,48,0,Math.PI*2);
      ctx.stroke();
    }else if(String(profile.medium.type||"")==="inscription"){
      ctx.beginPath();
      ctx.moveTo(660,1035);
      ctx.bezierCurveTo(715,1002,770,1082,840,1050);
      ctx.stroke();
    }else if(String(profile.medium.type||"")==="speech"){
      for(i=0;i<3;i++){
        ctx.beginPath();
        ctx.arc(770,1045,34+(i*26),-.72,.72);
        ctx.stroke();
      }
    }

    if(String(profile.access.type||"")==="contact"){
      ctx.beginPath();
      ctx.arc(710,1265,38,0,Math.PI*2);
      ctx.arc(750,1265,38,0,Math.PI*2);
      ctx.stroke();
    }else if(String(profile.access.type||"")==="proximity"){
      for(i=0;i<4;i++){
        ctx.beginPath();
        ctx.arc(735,1265,28+(i*22),0,Math.PI*2);
        ctx.stroke();
      }
    }

    if(String(profile.target.type||"")==="trace"){
      for(i=0;i<5;i++){
        ctx.beginPath();
        ctx.arc(185+(i*70),1515-(i*18),15+(i*3),0,Math.PI*2);
        ctx.fill();
      }
    }else if(String(profile.target.type||"")==="memory"){
      for(i=0;i<4;i++){
        ctx.fillRect(140+(i*82),1500-(i*12),44,1.5);
      }
    }
    ctx.restore();

    ctx.save();
    ctx.globalAlpha=hasImage?0.50:0.86;
    drawStoryPrincipleMotif(ctx,profile,palette,seed);
    ctx.restore();
  }

  function drawStoryWrappedText(ctx,text,x,y,maxWidth,size,weight,color,maxLines){
    var lines;
    var lineHeight=storyLineHeight(size);
    var i;
    ctx.font=storyFont(size,weight||400);
    ctx.fillStyle=color;
    ctx.textAlign="left";
    lines=wrapCanvasText(ctx,String(text||""),maxWidth);
    for(i=0;i<lines.length;i++){
      if(maxLines){
        if(i>=maxLines) break;
      }
      ctx.fillText(lines[i],x,y);
      y+=lineHeight;
    }
    return y;
  }

  var STORY_LAW_ROW_GAP=30;
  var STORY_LAW_INLINE_WIDTH=220;
  var STORY_LAW_WRAP_WIDTH=275;
  var STORY_LAW_STACK_THRESHOLD=265;

  function measureStoryText(ctx,text,size){
    ctx.font=storyFont(size,400);
    return ctx.measureText(String(text||"")).width;
  }

  function storyLawLayout(ctx,valueText){
    var width=measureStoryText(ctx,valueText,STORY_TEXT_MEDIUM);
    if(width<=STORY_LAW_INLINE_WIDTH) return "inline";
    if(width<=STORY_LAW_STACK_THRESHOLD) return "inline-wrap";
    return "stacked";
  }

  function storyVisibleTextHeight(ctx,text){
    var metrics=ctx.measureText(String(text||""));
    var height=0;
    if(typeof metrics.actualBoundingBoxAscent==="number"){
      if(typeof metrics.actualBoundingBoxDescent==="number"){
        height=metrics.actualBoundingBoxAscent+metrics.actualBoundingBoxDescent;
      }
    }
    if(!height){
      height=Math.round(parseFloat(ctx.font)||STORY_TEXT_MEDIUM);
    }
    return Math.max(1,Math.ceil(height));
  }

  function drawStoryLawRow(ctx,labelText,valueText,y){
    var labelX=388;
    var valueX=428;
    var blockLeft=274;
    var valueWidth=STORY_LAW_WRAP_WIDTH;
    var valueLineHeight=storyLineHeight(STORY_TEXT_MEDIUM);
    var layout=storyLawLayout(ctx,valueText);
    var valueLines=[];
    var lineCount=1;
    var labelHeight;
    var valueHeight;
    var valueY;
    var lastLineY;
    var i;

    ctx.textBaseline="top";

    if(layout==="stacked"){
      ctx.textAlign="left";
      ctx.fillStyle=STORY_TEXT_COLOR;
      ctx.font=storyFont(STORY_TEXT_SMALL,400);
      ctx.fillText(String(labelText||""),blockLeft,y);
      labelHeight=storyVisibleTextHeight(ctx,labelText);

      valueY=y+labelHeight+14;
      ctx.fillStyle=STORY_TEXT_COLOR;
      ctx.font=storyFont(STORY_TEXT_MEDIUM,400);
      valueLines=wrapCanvasText(ctx,String(valueText||""),560);
      lineCount=valueLines.length;
      if(lineCount<1) lineCount=1;
      if(lineCount>3) lineCount=3;
      for(i=0;i<lineCount;i++){
        ctx.fillText(valueLines[i]||"",blockLeft,valueY+(i*valueLineHeight));
      }
      lastLineY=valueY+((lineCount-1)*valueLineHeight);
      valueHeight=storyVisibleTextHeight(ctx,valueLines[lineCount-1]||valueText);
      ctx.textBaseline="alphabetic";
      return lastLineY+valueHeight+STORY_LAW_ROW_GAP;
    }

    ctx.textAlign="right";
    ctx.fillStyle=STORY_TEXT_COLOR;
    ctx.font=storyFont(STORY_TEXT_SMALL,400);
    ctx.fillText(String(labelText||""),labelX,y);
    labelHeight=storyVisibleTextHeight(ctx,labelText);

    ctx.textAlign="left";
    ctx.fillStyle=STORY_TEXT_COLOR;
    ctx.font=storyFont(STORY_TEXT_MEDIUM,400);

    if(layout==="inline-wrap"){
      valueLines=wrapCanvasText(ctx,String(valueText||""),valueWidth);
      lineCount=valueLines.length;
      if(lineCount<1) lineCount=1;
      if(lineCount>2) lineCount=2;
    }else{
      valueLines=[String(valueText||"")];
      lineCount=1;
    }

    for(i=0;i<lineCount;i++){
      ctx.fillText(valueLines[i]||"",valueX,y+(i*valueLineHeight));
    }

    lastLineY=y+((lineCount-1)*valueLineHeight);
    valueHeight=storyVisibleTextHeight(ctx,valueLines[lineCount-1]||valueText);
    ctx.textBaseline="alphabetic";
    return Math.max(y+labelHeight,lastLineY+valueHeight)+STORY_LAW_ROW_GAP;
  }

  function storyDateStamp(date){
    function pad(n){return n<10?"0"+n:String(n);}
    return String(date.getFullYear())+
      pad(date.getMonth()+1)+
      pad(date.getDate())+"_"+
      pad(date.getHours())+
      pad(date.getMinutes())+
      pad(date.getSeconds());
  }

  function safeStoryFilename(){
    return storyDateStamp(new Date())+"_your_magic.png";
  }

  function createMagicStoryCard(profile,button){
    var source=resolveStoryImageSource();
    var image;
    var finished=false;

    setShareBusy(button,true);

    function complete(img){
      if(finished) return;
      finished=true;
      renderMagicStoryCard(profile,button,img||null);
    }

    if(!source){
      complete(null);
      return;
    }

    image=new Image();
    if(source.indexOf(window.location.origin)!==0){
      image.crossOrigin="anonymous";
    }
    image.onload=function(){complete(image);};
    image.onerror=function(){complete(null);};
    image.src=source;

    window.setTimeout(function(){
      complete(null);
    },2200);
  }

  function renderMagicStoryCard(profile,button,storyImage){
    var u=currentUI();
    var canvas=document.createElement("canvas");
    var ctx=canvas.getContext("2d");
    var name=String(profile.magic_name||"");
    var core=String(profile.magic_core||"");
    var titleLayout;
    var y;
    var i;
    var filename;
    var lawRows=[
      [u.principle,label("principle",profile.dominant_principle.type)],
      [u.source,label("source",profile.source.type)],
      [u.starting,label("medium",profile.medium.type)],
      [u.change,label("effect",profile.effect.operation)],
      [u.limit,label("limit",profile.limit.type)],
      [u.access,label("access",profile.access.type)],
      [u.target,label("target",profile.target.type)],
      [u.control,label("control",profile.control.level)]
    ];

    if(!ctx){
      showToast(u.share_failed);
      return;
    }

    canvas.width=1080;
    canvas.height=1920;
    drawStoryBackground(ctx,profile,storyImage);

    /* Photography can cross behind any text position. A very soft light halo
       is applied only when an eye-catch is present; it is not a card or band. */
    if(storyImage){
      ctx.shadowColor="rgba(0,0,0,.28)";
      ctx.shadowBlur=5;
      ctx.shadowOffsetX=0;
      ctx.shadowOffsetY=1;
    }

    ctx.textBaseline="alphabetic";
    ctx.textAlign="left";

    /* Left axis: the magic itself. */
    ctx.fillStyle=STORY_TEXT_COLOR;
    titleLayout=fitCanvasTitle(ctx,name,820,2);
    ctx.font=storyFont(titleLayout.size,600);
    y=190;
    for(i=0;i<titleLayout.lines.length;i++){
      if(i>=2) break;
      ctx.fillText(titleLayout.lines[i],96,y);
      y+=Math.round(titleLayout.size*1.22);
    }

    y+=56;
    y=drawStoryWrappedText(ctx,core,96,y,835,STORY_TEXT_LARGE,400,STORY_TEXT_COLOR,6);

    /* Center axis: heading belongs to the law block below it. */
    y+=54;
    ctx.textAlign="center";
    ctx.fillStyle=STORY_TEXT_COLOR;
    ctx.font=storyFont(STORY_TEXT_MEDIUM,400);
    ctx.fillText(state.language==="en"?"THE LAWS OF THIS MAGIC":"この魔法の法則",402,y);

    y+=48;
    for(i=0;i<lawRows.length;i++){
      y=drawStoryLawRow(ctx,lawRows[i][0],lawRows[i][1],y);
    }

    /* World law returns to the central axis. It remains a separate section
       through vertical whitespace rather than a different text alignment. */
    y+=26;
    ctx.textBaseline="alphabetic";
    ctx.textAlign="center";
    ctx.fillStyle=STORY_TEXT_COLOR;
    ctx.font=storyFont(STORY_TEXT_SMALL,400);
    ctx.fillText(u.ontology,540,y);
    y+=50;
    ctx.font=storyFont(STORY_TEXT_MEDIUM,400);
    ctx.fillStyle=STORY_TEXT_COLOR;
    ctx.textAlign="center";
    var ontologyLines=wrapCanvasText(ctx,String(profile.ontology.description||""),650);
    for(i=0;i<ontologyLines.length;i++){
      if(i>=5) break;
      ctx.fillText(ontologyLines[i],540,y);
      y+=storyLineHeight(STORY_TEXT_MEDIUM);
    }

    /* No explanatory closing sentence: the Story Card itself is the record. */

    /* Credits — independent typography. No separator lines or text panels. */
    ctx.textAlign="center";
    ctx.fillStyle=STORY_TEXT_COLOR;
    ctx.font=storyFont(18,500);
    ctx.fillText("Tranquilvæj",540,1768);
    ctx.fillStyle=STORY_TEXT_COLOR;
    ctx.font=storyFont(17,400);
    ctx.fillText("TranquilGuides.com",540,1804);

    filename=safeStoryFilename();

    canvasToBlob(canvas,function(blob){
      var file;
      var canShareFiles=false;
      var downloaded=false;

      if(!blob){
        setShareBusy(button,false);
        showToast(u.share_failed);
        return;
      }

      /* On supported mobile browsers the native share sheet allows saving
         the PNG to Photos. Desktop/fallback browsers receive a PNG download. */
      if(navigator.share){
        if(window.File){
          try{
            file=new File([blob],filename,{type:"image/png"});
            if(navigator.canShare){
              try{
                canShareFiles=navigator.canShare({files:[file]});
              }catch(error){
                canShareFiles=false;
              }
            }
          }catch(error){
            canShareFiles=false;
          }

          if(canShareFiles){
            navigator.share({
              title:name,
              text:standardShareText(profile,0),
              files:[file]
            }).then(function(){
              setShareBusy(button,false);
              showToast(u.share_story_ready);
            }).catch(function(error){
              setShareBusy(button,false);
              if(error){
                if(error.name==="AbortError") return;
              }
              downloaded=downloadBlob(blob,filename);
              showToast(downloaded?u.share_story_ready:u.share_failed);
            });
            return;
          }
        }
      }

      downloaded=downloadBlob(blob,filename);
      setShareBusy(button,false);
      showToast(downloaded?u.share_story_ready:u.share_failed);
    });
  }

  function shareHtml(){
    var u=currentUI();

    return ''+
      '<section class="tvm-result-section tvm-share" data-surface="content" data-elevation="s0" aria-labelledby="tvmShareTitle">'+
        '<p class="tvm-share-title tvm-align-center" id="tvmShareTitle">'+escapeHtml(u.share_title)+'</p>'+
        '<div class="tvm-share-row" id="tvmShareRow">'+
          '<span class="tvm-share-group tvm-share-group--social">'+
            '<span class="tvm-share-unit"><button type="button" class="tvm-share-btn tvm-control" data-share-action="x" aria-label="'+escapeHtml(u.share_x)+'" data-tooltip="'+escapeHtml(u.share_x)+'">'+
              '<span class="tvm-share-icon-wrap" aria-hidden="true"><i class="snsicon icon-twitter-x tvm-share-font-icon"></i></span>'+
              '<span class="tvm-share-fallback" aria-hidden="true">X</span>'+
            '</button></span>'+
            '<span class="tvm-share-unit"><button type="button" class="tvm-share-btn tvm-control" data-share-action="threads" aria-label="'+escapeHtml(u.share_threads)+'" data-tooltip="'+escapeHtml(u.share_threads)+'">'+
              '<span class="tvm-share-icon-wrap" aria-hidden="true"><svg class="tvm-share-icon tvm-share-icon--brand" viewBox="0 0 201 201" aria-hidden="true">'+
                '<path d="M133.099 94.3599C151.029 101.908 159.85 119.977 154 138.676C150.013 151.439 138.655 161.749 126.484 166.41C111.14 172.305 90.5326 171.926 75.3981 165.646C44.7016 152.925 37.5408 117.601 40.5887 88.2132C42.7118 67.6424 51.274 47.5902 70.1781 37.2802C84.4228 29.4795 102.654 28.372 118.251 31.6381C134.444 35.0304 147.589 44.6115 155.555 59.1197C158.015 63.5703 160.004 68.4904 161.49 73.9642C161.532 74.1745 161.448 74.3918 161.238 74.4339L149.964 77.4056C149.754 77.4476 149.536 77.3215 149.494 77.1533C147.799 70.7052 145.129 64.979 141.437 59.9817C129.903 44.2891 108.75 40.0908 90.5187 43.3569C69.022 47.2187 57.1526 62.3157 53.6773 83.0477C50.8395 99.8828 51.7294 119.388 59.4859 134.913C66.0161 147.977 77.8435 155.308 92.0882 157.348C99.7606 158.406 107.265 158.28 114.601 156.92C125.118 154.972 136.392 148.012 140.967 138.046C143.938 131.598 144.232 123.418 140.967 117.012C139.103 113.368 136.301 110.438 132.615 108.237C132.447 108.111 132.188 108.195 132.104 108.363C132.062 108.406 132.062 108.448 132.062 108.49C131.634 111.629 130.92 114.72 129.855 117.734C128.327 122.017 126.127 125.71 123.198 128.717C113.361 138.852 96.2363 139.742 84.6612 132.446C75.4193 126.593 71.9439 114.636 76.3511 104.796C80.9265 94.6191 92.1232 90.2107 102.759 89.699C108.778 89.4047 114.335 89.657 119.464 90.3789C119.674 90.4209 119.842 90.2527 119.891 90.0425V89.9163C119.421 87.5823 118.875 85.676 118.195 84.1901C114.636 76.3473 106.62 74.2656 98.6115 75.2819C93.4826 75.9197 89.4536 78.3378 86.4407 82.494C86.3146 82.6622 86.1044 82.7042 85.9293 82.5781L76.3511 76.0459C76.1829 75.9198 76.141 75.7095 76.2671 75.4922C81.396 68.2801 88.3466 64.0819 97.1681 62.9394C104.462 61.9652 112.639 63.1076 119.001 66.9695C128.537 72.8218 131.928 83.342 132.776 93.9814C132.86 94.1917 132.944 94.3178 133.071 94.3599H133.099ZM87.3516 110.985C85.4458 117.391 89.8531 122.437 95.8298 123.958C104.224 126.082 113.55 124.21 117.537 115.603C119.106 112.211 120.038 108.223 120.332 103.689C120.332 103.478 120.206 103.31 120.038 103.31C113.809 102.084 107.405 101.824 100.875 102.462C95.5776 103.016 89.0052 105.434 87.3516 110.985Z" fill="currentColor"/>'+
              '</svg></span>'+
            '</button></span>'+
            '<span class="tvm-share-unit"><button type="button" class="tvm-share-btn tvm-control" data-share-action="bluesky" aria-label="'+escapeHtml(u.share_bluesky)+'" data-tooltip="'+escapeHtml(u.share_bluesky)+'">'+
              '<span class="tvm-share-icon-wrap" aria-hidden="true"><svg class="tvm-share-icon tvm-share-icon--brand" viewBox="0 0 600 530" aria-hidden="true"><path fill="currentColor" d="M135.72 44.03C202.216 93.951 273.689 195.17 300 249.46c26.311-54.29 97.784-155.509 164.28-205.43C512.25 8.014 590-19.92 590 68.84c0 17.733-10.155 148.573-16.111 169.893-20.703 74.044-96.144 92.956-163.325 81.504 117.3 19.996 147.14 86.092 82.697 152.188-122.39 125.59-175.91-31.511-189.63-71.766-2.514-7.379-3.69-10.832-3.631-7.896-.059-2.936-1.117.517-3.631 7.896-13.72 40.255-67.24 197.356-189.63 71.766-64.443-66.096-34.603-132.192 82.697-152.188-67.181 11.452-142.622-7.46-163.325-81.504C20.155 217.413 10 86.573 10 68.84 10-19.92 87.75 8.014 135.72 44.03Z"/></svg></span>'+
            '</button></span>'+
            '<span class="tvm-share-unit"><button type="button" class="tvm-share-btn tvm-control" data-share-action="line" aria-label="'+escapeHtml(u.share_line)+'" data-tooltip="'+escapeHtml(u.share_line)+'">'+
              '<span class="tvm-share-icon-wrap" aria-hidden="true"><i class="snsicon icon-line tvm-share-font-icon"></i></span>'+
              '<span class="tvm-share-fallback" aria-hidden="true">L</span>'+
            '</button></span>'+
          '</span>'+
          '<span class="tvm-share-group tvm-share-group--utility">'+
            '<span class="tvm-share-unit"><button type="button" class="tvm-share-btn tvm-control" data-share-action="native" aria-label="'+escapeHtml(u.share_native)+'" data-tooltip="'+escapeHtml(u.share_native)+'">'+
              '<span class="tvm-share-icon-wrap" aria-hidden="true"><svg class="tvm-share-icon" viewBox="0 0 512 512" aria-hidden="true">'+
                '<path d="M336 192h40a40 40 0 0 1 40 40v192a40 40 0 0 1-40 40H136a40 40 0 0 1-40-40V232a40 40 0 0 1 40-40h40" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/>'+
                '<polyline points="336 128 256 48 176 128" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/>'+
                '<line x1="256" y1="321" x2="256" y2="48" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/>'+
              '</svg></span>'+
            '</button></span>'+
            '<span class="tvm-share-unit"><button type="button" class="tvm-share-btn tvm-control" data-share-action="story" aria-label="'+escapeHtml(u.share_story)+'" data-tooltip="'+escapeHtml(u.share_story)+'">'+
              '<span class="tvm-share-icon-wrap" aria-hidden="true"><svg class="tvm-share-icon" viewBox="0 0 24 24" aria-hidden="true">'+
                '<rect x="3" y="4" width="18" height="16" rx="2" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>'+
                '<path d="M3 15.75 L7.72 11.03 C7.86 10.89 8.05 10.81 8.25 10.81 C8.45 10.81 8.64 10.89 8.78 11.03 L12.97 15.22 C13.11 15.36 13.30 15.44 13.50 15.44 C13.70 15.44 13.89 15.36 14.03 15.22 L15.97 13.28 C16.11 13.14 16.30 13.06 16.50 13.06 C16.70 13.06 16.89 13.14 17.03 13.28 L21 17.25" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>'+
                '<circle cx="16.5" cy="8.5" r="1.5" fill="currentColor"/>'+
              '</svg></span>'+
            '</button></span>'+
            '<span class="tvm-share-unit"><button type="button" class="tvm-share-btn tvm-control" data-share-action="copy" aria-label="'+escapeHtml(u.share_copy)+'" data-tooltip="'+escapeHtml(u.share_copy)+'">'+
              '<span class="tvm-share-icon-wrap" aria-hidden="true"><svg class="tvm-copy-icon" viewBox="0 0 32 32" aria-hidden="true">'+
                '<g class="tvm-copy-icon__default"><rect x="11" y="11" width="14" height="14" rx="2.5" fill="none" stroke="currentColor" stroke-width="2"/><path d="M9 21H7.5A2.5 2.5 0 0 1 5 18.5v-11A2.5 2.5 0 0 1 7.5 5h11A2.5 2.5 0 0 1 21 7.5V9" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></g>'+
                '<g class="tvm-copy-icon__copied"><rect x="6" y="6" width="20" height="20" rx="2" fill="none" stroke="currentColor" stroke-width="2.2"/><path d="M10.5 16l3.5 3.5 7.5-8" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></g>'+
              '</svg></span>'+
            '</button></span>'+
          '</span>'+
        '</div>'+
      '</section>';
  }

  function ensureShareFontFallbacks(row){
    var icons;
    var i;
    var icon;
    var before;
    var button;

    if(!row) return;
    icons=row.querySelectorAll(".tvm-share-font-icon");

    for(i=0;i<icons.length;i++){
      icon=icons[i];
      before=window.getComputedStyle(icon,"::before").content;
      if(!before){
        button=icon.parentNode;
        if(button) button=button.parentNode;
        if(button) button.classList.add("is-font-icon-missing");
      }else if(before==="none"){
        button=icon.parentNode;
        if(button) button=button.parentNode;
        if(button) button.classList.add("is-font-icon-missing");
      }else if(before==="normal"){
        button=icon.parentNode;
        if(button) button=button.parentNode;
        if(button) button.classList.add("is-font-icon-missing");
      }
    }
  }

  function bindShareControls(profile){
    var row=byId("tvmShareRow");
    var registry;
    if(!row) return;

    ensureShareFontFallbacks(row);
    registry=applyShareCapabilities(row,profile);

    row.addEventListener("click",function(event){
      var button=event.target;
      var action;
      var config;
      var result;

      while(button){
        if(button===row) break;
        action=button.getAttribute("data-share-action");
        if(action) break;
        button=button.parentNode;
      }

      if(!button) return;
      if(button===row) return;
      if(button.disabled) return;

      config=registry[action];
      if(!config) return;
      if(config.available===false) return;

      try{
        result=config.run(button);
        if(result){
          if(typeof result.then==="function"){
            result.catch(function(error){
              reportRecovery(error,"share:"+action,true,function(){
                return config.run(button);
              });
            });
          }
        }
      }catch(error){
        reportRecovery(error,"share:"+action,true,function(){
          return config.run(button);
        });
      }
    });
  }

  function renderResult(){
    var app=getApp();
    var p=state.profile;
    var html="";
    var restart;
    var copy;
    var u=currentUI();

    if(!app) return;
    if(!p){
      finish();
      return;
    }

    state.detail=true;
    setStageEnvironment("result");

    html+=experienceToggleHtml();
    html+='<section class="tvm-screen tvm-result-screen tvm-density-compact" data-surface="content" data-elevation="s0">';
    html+='<div class="tvm-result-discovery">';
    html+='<div class="tvm-kicker tvm-align-center">'+escapeHtml(u.result_kicker)+'</div>';

    if(p.magic_name!=="無題"){
      if(p.magic_name!=="Untitled"){
        html+='<div class="tvm-result-name tvm-align-center">'+escapeHtml(p.magic_name)+'</div>';
      }
    }

    html+='<div class="tvm-core tvm-align-center">'+escapeHtml(p.magic_core).replace(/\n/g,"<br>")+'</div>';
    html+='</div>';
    html+='<div class="tvm-result-axis">';
    html+=resultSummaryHtml(p);
    html+=carryPromptHtml(p);
    html+=shareHtml();

    html+='<div class="tvm-result-restart">';
    html+='<div class="tvm-actions"><button type="button" class="tvm-btn is-ghost tvm-control tvm-reactive" data-material="clear" data-surface="interface" data-elevation="s1" id="tvmRestart">'+escapeHtml(u.restart)+'</button></div>';
    html+='</div>';
    html+='</div>';
    html+='</section>';

    app.innerHTML=html;

    bindInteractionControls();
    bindFocusToggle();
    applyShortcutMetadata();

    copy=byId("tvmCopy");
    syncMagicLanguageAttributes();
    restart=byId("tvmRestart");

    if(copy){
      copy.addEventListener("click",function(){
        copyPrompt();
      });
    }

    bindShareControls(p);

    if(restart){
      restart.addEventListener("click",restartExperience);
    }
  }

  function resultSummaryHtml(p){
    var html="";
    var u=currentUI();

    html+='<section class="tvm-result-section tvm-summary-section" data-surface="content" data-elevation="s0">';
    html+='<div class="tvm-law-group">';
    html+='<p class="tvm-result-section-title tvm-align-center">'+escapeHtml(u.summary_title)+'</p>';
    html+='<dl class="tvm-summary-grid tvm-law-list">';
    html+='<div class="tvm-law-row"><dt>'+escapeHtml(u.principle)+'</dt><dd>'+escapeHtml(label("principle",p.dominant_principle.type))+'</dd></div>';
    html+='<div class="tvm-law-row"><dt>'+escapeHtml(u.source)+'</dt><dd>'+escapeHtml(label("source",p.source.type))+'</dd></div>';
    html+='<div class="tvm-law-row"><dt>'+escapeHtml(u.starting)+'</dt><dd>'+escapeHtml(label("medium",p.medium.type))+'</dd></div>';
    html+='<div class="tvm-law-row"><dt>'+escapeHtml(u.change)+'</dt><dd>'+escapeHtml(label("effect",p.effect.operation))+'</dd></div>';
    html+='<div class="tvm-law-row"><dt>'+escapeHtml(u.limit)+'</dt><dd>'+escapeHtml(label("limit",p.limit.type))+'</dd></div>';
    html+='</dl>';

    html+='<div class="tvm-detail">';
    html+='<dl class="tvm-grid tvm-grid--secondary tvm-law-list tvm-law-list--detail">';
    html+='<div class="tvm-law-row"><dt>'+escapeHtml(u.access)+'</dt><dd>'+escapeHtml(label("access",p.access.type))+'</dd></div>';
    html+='<div class="tvm-law-row"><dt>'+escapeHtml(u.target)+'</dt><dd>'+escapeHtml(label("target",p.target.type))+'</dd></div>';
    html+='<div class="tvm-law-row"><dt>'+escapeHtml(u.control)+'</dt><dd>'+escapeHtml(label("control",p.control.level))+'</dd></div>';
    html+='</dl>';
    html+='<div class="tvm-ontology-block">';
    html+='<p class="tvm-ontology-label">'+escapeHtml(u.ontology)+'</p>';
    html+='<p class="tvm-ontology-text">'+escapeHtml(p.ontology.description)+'</p>';
    html+='</div>';
    html+='</div>';
    html+='</div>';
    html+='</section>';

    return html;
  }

  function carryPromptHtml(){
    var html="";
    var u=currentUI();

    html+='<section class="tvm-result-section tvm-carry-section" data-surface="content" data-elevation="s0">';
    html+='<p class="tvm-result-section-title tvm-align-center">'+escapeHtml(u.carry_title)+'</p>';
    html+='<div class="tvm-carry-lead tvm-align-center">';
    html+='<p class="tvm-carry-lead-line">'+escapeHtml(u.carry_lead_first||u.carry_lead)+'</p>';
    html+='<span class="tvm-carry-lead-gap" aria-hidden="true"></span>';
    html+='<p class="tvm-carry-lead-line">'+escapeHtml(u.carry_lead_second||"")+'</p>';
    html+='</div>';
    html+='<div class="tvm-copy-action"><button type="button" class="tvm-btn is-primary tvm-control tvm-reactive" data-material="veil" data-surface="interface" data-elevation="s1" data-glass="veil" id="tvmCopy"><span class="tvm-btn-label">'+escapeHtml(u.copy)+'</span></button></div>';
    html+='<p class="tvm-copy-status" id="tvmCopyMessage" role="status" aria-live="polite" aria-atomic="true"></p>';

    html+='<div class="tvm-spacer tvm-spacer--copy-to-prompt" aria-hidden="true"></div>';
    html+='<div class="tvm-prompt-group">';
    html+='<textarea class="tvm-prompt tvm-align-left" id="tvmPromptArea" readonly>'+escapeHtml(state.prompt)+'</textarea>';
    html+='</div>';
    html+='</section>';
    return html;
  }

  function legacyCopyText(text){
    return new Promise(function(resolve,reject){
      var area;
      var copied;

      try{
        area=document.createElement("textarea");
        area.value=text;
        area.setAttribute("readonly","");
        area.style.position="fixed";
        area.style.left="-9999px";
        area.style.top="0";
        document.body.appendChild(area);
        area.focus();
        area.select();
        copied=document.execCommand("copy");
        area.remove();

        if(copied){
          resolve();
        }else{
          reject(new Error("copy command failed"));
        }
      }catch(error){
        if(area){
          if(area.parentNode){
            area.parentNode.removeChild(area);
          }
        }
        reject(error);
      }
    });
  }

  function copyText(text){
    if(navigator.clipboard){
      if(window.isSecureContext){
        if(navigator.clipboard.writeText){
          return navigator.clipboard.writeText(text).catch(function(){
            return legacyCopyText(text);
          });
        }
      }
    }

    return legacyCopyText(text);
  }

  function copyPrompt(){
    var message=byId("tvmCopyMessage");
    var button=byId("tvmCopy");
    var root=getRoot();
    var u=currentUI();

    if(root){
      if(root._tvmCopySuccessTimer){
        window.clearTimeout(root._tvmCopySuccessTimer);
        root._tvmCopySuccessTimer=0;
      }
    }

    if(button){
      setBusyControl(button,true,u.copy_working);
      button.setAttribute("data-state","working");
      setMaterialState(button,"lens");
    }

    copyText(state.prompt).then(function(){
      var b=byId("tvmCopy");
      var localRoot=getRoot();
      if(b){
        setBusyControl(b,false);
        b.setAttribute("data-state","success");
        setMaterialState(b,"veil");
        setControlLabel(b,"✓ "+u.copied);
      }

      if(message){
        message.textContent=u.copy_success_help;
      }

      showToast(u.copied);

      if(localRoot){
        localRoot._tvmCopySuccessTimer=window.setTimeout(function(){
          var btn=byId("tvmCopy");
          if(btn){
            btn.removeAttribute("data-state");
            setControlLabel(btn,u.copy);
          }
          localRoot._tvmCopySuccessTimer=0;
        },2000);
      }
    }).catch(function(error){
      var area;
      var b;

      state.detail=true;
      render();

      area=byId("tvmPromptArea");
      if(area){
        area.focus();
        area.select();
      }

      b=byId("tvmCopy");
      if(b){
        setBusyControl(b,false);
        b.removeAttribute("data-state");
        setMaterialState(b,"veil");
        setControlLabel(b,u.copy);
      }

      message=byId("tvmCopyMessage");
      if(message){
        message.textContent=u.copy_fail;
      }

      showToast(u.copy_fail,u.recovery_retry,function(){
        copyPrompt();
      });
      reportRecovery(error,"copyPrompt",false,function(){
        return copyPrompt();
      });
    });
  }

  function restartExperience(){
    var language=state.language;
    clearTransientInteractionState();
    cancelInteractionFrame();
    state={
      screen:"entry",
      history:[],
      answers:{},
      profile:null,
      prompt:"",
      language:language,
      detail:false
    };
    render();
  }

  function initMagic(){
    var root=getRoot();
    if(!root) return;
    if(root.dataset.initialized==="true") return;

    root.dataset.initialized="true";
    root.setAttribute("data-tis-version","4.9");
    root.setAttribute("data-responsive-contract","single-dom");
    root.setAttribute("data-glass-contract","semantic");
    root.setAttribute("data-input-contract","single-primary-mouse-touch-pen-keyboard");
    root.setAttribute("data-viewport-contract","safe-area-visual-viewport");

    guardRun("storageCapabilities",function(){initStorageCapabilities();},false);
    guardRun("preferences",function(){restorePreferences();},false);
    guardRun("recoverySafety",function(){bindRecoverySafety();},false);
    guardRun("lifecycleSafety",function(){bindLifecycleSafety();},false);
    guardRun("theme",function(){applyThemeMode(themeMode,false);},false);
    guardRun("viewport",function(){syncVisualViewport();},false);

    try{
      /* v5.8: experience state is intentionally ephemeral; reload starts at Entry. */
      render();
      if(preferredFocusMode){
        enterFocusMode();
      }
    }catch(error){
      reportRecovery(error,"init",true);
      var app=getApp();
      if(app){
        app.innerHTML='<div class="tvm-error" role="alert">'+escapeHtml(currentUI().error)+'</div>';
      }
    }
  }

  window.TranquilMagicTheme={
    get:function(){return themeMode;},
    set:function(mode){return applyThemeMode(mode,true);},
    resolved:function(){return resolvedTheme(themeMode);}
  };

  window.TranquilMagicRecovery={
    report:reportRecovery,
    guard:guardRun,
    storage:function(){
      return {
        localStorage:storageCapabilities.localStorage
      };
    }
  };

  if(document.readyState==="loading"){
    document.addEventListener("DOMContentLoaded",initMagic,{once:true});
  }else{
    initMagic();
  }
})();
</script>
]]></content:encoded>
					
					<wfw:commentRss>https://tranquilguides.com/unnamed-magic/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2936</post-id>	</item>
		<item>
		<title>今日の余白</title>
		<link>https://tranquilguides.com/today-margin/</link>
					<comments>https://tranquilguides.com/today-margin/#respond</comments>
		
		<dc:creator><![CDATA[案内人のアシカ]]></dc:creator>
		<pubDate>Mon, 14 Sep 2026 15:18:00 +0000</pubDate>
				<category><![CDATA[生存ログ]]></category>
		<category><![CDATA[体験]]></category>
		<category><![CDATA[余白]]></category>
		<category><![CDATA[時間]]></category>
		<category><![CDATA[言葉]]></category>
		<guid isPermaLink="false">https://tranquilguides.com/?p=2792</guid>

					<description><![CDATA[<p><img src="https://i0.wp.com/tranquilguides.com/wp-content/uploads/2026/09/IMG_20260912_012319.png?fit=1024%2C683&ssl=1" class="webfeedsFeaturedVisual" /></p>触れるたび、ことばと円が少しずつ変わる。今いる場所から少しだけ距離をとるための、小さな余白。]]></description>
										<content:encoded><![CDATA[<p><img src="https://i0.wp.com/tranquilguides.com/wp-content/uploads/2026/09/IMG_20260912_012319.png?fit=1024%2C683&ssl=1" class="webfeedsFeaturedVisual" /></p>
<style>
/* =========================================================
   TODAY / MARGIN v3.10
   Browser Immersive Mode
   Split Diagonal SVG Controls
   Time / Trace / Return / Persistent appearance / Optional sound and wake lock
   ========================================================= */


/* =========================================================
   Root
   ========================================================= */

.tq-margin{
  container-type:inline-size;
  container-name:tq-margin;

  --tqm-bg:#f4f2ec;
  --tqm-fg:#171717;
  --tqm-muted:#7a7770;
  --tqm-line:rgba(23,23,23,.14);
  --tqm-wash:rgba(23,23,23,.035);
  --tqm-idle:0;
  --tqm-touch-x:0px;
  --tqm-touch-y:0px;
  --tqm-history:0;
  --tqm-return-depth:0;
  --tqm-delay:0ms;
  transition:background-color 1200ms ease,color 1200ms ease;

  position:relative;
  isolation:isolate;

  box-sizing:border-box;

  width:100%;
  height:clamp(32rem,72svh,51rem);
  min-height:0;

  display:grid;
  grid-template-rows:auto minmax(0,1fr) auto;

  padding:
    clamp(1rem,2.4cqw,1.5rem)
    clamp(1.25rem,5cqw,4rem)
    clamp(1rem,2.2cqw,1.375rem);

  color:var(--tqm-fg);
  background:transparent;

  font-family:
    -apple-system,
    BlinkMacSystemFont,
    "Hiragino Sans",
    "Yu Gothic",
    sans-serif;
}


.tq-margin,
.tq-margin *,
.tq-margin *::before,
.tq-margin *::after{
  box-sizing:border-box;
}


/* =========================================================
   Browser immersive
   ========================================================= */

.tq-margin.is-immersive{
  position:fixed !important;

  inset:0 !important;

  z-index:2147483000 !important;

  width:100vw !important;
  width:100dvw !important;

  height:100vh !important;
  height:100dvh !important;

  min-height:0 !important;
  max-width:none !important;

  margin:0 !important;

  padding:
    max(
      clamp(1rem,2.4dvh,2rem),
      env(safe-area-inset-top)
    )
    max(
      clamp(1rem,3.2dvw,4rem),
      env(safe-area-inset-right)
    )
    max(
      clamp(1rem,2.2dvh,1.75rem),
      env(safe-area-inset-bottom)
    )
    max(
      clamp(1rem,3.2dvw,4rem),
      env(safe-area-inset-left)
    ) !important;

  overflow:hidden !important;

  background:var(--tqm-bg) !important;

  /*
   * iOS / touch browsers:
   * - keep two-finger pinch zoom available
   * - do not hand one-finger pan / double-tap zoom to the browser
   *   while the artwork is immersive
   * - suppress overscroll chaining / pull-to-refresh where supported
   *
   * Safari may still reserve some system-level edge gestures.
   */
  touch-action:pinch-zoom;

  overscroll-behavior:none;
  overscroll-behavior-x:none;
  overscroll-behavior-y:none;

  -webkit-user-select:none;
  user-select:none;
  -webkit-touch-callout:none;

  -webkit-text-size-adjust:100%;
  text-size-adjust:100%;
}



/* =========================================================
   iOS / device gesture containment
   ========================================================= */

.tq-margin:not(.is-immersive) .tq-margin__circle,
.tq-margin:not(.is-immersive) .tq-margin__fullscreen,
.tq-margin:not(.is-immersive) .tq-margin__reset,
.tq-margin:not(.is-immersive) .tq-margin__utility,
.tq-margin:not(.is-immersive) .tq-margin__themeOption{
  touch-action:manipulation;
}

.tq-margin.is-immersive .tq-margin__circle,
.tq-margin.is-immersive .tq-margin__fullscreen,
.tq-margin.is-immersive .tq-margin__reset,
.tq-margin.is-immersive .tq-margin__utility,
.tq-margin.is-immersive .tq-margin__themeOption{
  touch-action:inherit;
  -webkit-touch-callout:none;
}

/*
 * Keep the artwork clear of system-reserved screen edges.
 * The existing safe-area padding remains authoritative; this adds
 * a minimum interactive gutter for landscape / edge-swipe conditions.
 */
@media (orientation:landscape) and (max-height:520px){
  .tq-margin.is-immersive{
    padding-left:max(24px,env(safe-area-inset-left)) !important;
    padding-right:max(24px,env(safe-area-inset-right)) !important;
  }

  .tq-margin__circle{
    width:min(42vh,220px);
  }
}

/* =========================================================
   Header
   ========================================================= */

.tq-margin__header{
  position:relative;
  z-index:3;

  display:flex;
  align-items:center;
  justify-content:space-between;

  min-width:0;

  gap:20px;
}




/* =========================================================
   Header tools
   ========================================================= */

.tq-margin__tools{
  display:flex;
  align-items:center;

  width:100%;
  min-width:0;

  gap:6px;
}

#tq-margin-audio{
  margin-left:auto;
}




/* =========================================================
   Immersive toggle
   ========================================================= */

.tq-margin__fullscreen{
  appearance:none;

  display:grid;
  place-items:center;

  flex:0 0 44px;

  width:44px;
  min-width:44px;
  height:44px;
  min-height:44px;

  margin:
    0
    -12px
    0
    0;

  padding:0;

  border:0;

  background:transparent;
  color:var(--tqm-muted);

  cursor:pointer;

  -webkit-tap-highlight-color:transparent;

  transition:
    color 180ms ease,
    opacity 180ms ease;
}


.tq-margin__fullscreen:hover{
  color:var(--tqm-fg);
}


.tq-margin__fullscreen:focus-visible{
  outline:2px solid currentColor;
  outline-offset:3px;
}


/* =========================================================
   SVG expand / contract
   ========================================================= */

.tq-margin__fullscreenIcon{
  display:block;

  width:1.5rem;
  height:1.5rem;

  /*
   * SVGの視覚中心を
   * 時刻のベースラインに合わせる。
   */
  transform:translateY(1px);

  overflow:visible;

  fill:none;
  stroke:currentColor;

  stroke-width:1.8;
  stroke-linecap:round;
  stroke-linejoin:round;

  pointer-events:none;
}


.tq-margin__icon-expand{
  display:block;
}


.tq-margin__icon-contract{
  display:none;
}


.tq-margin.is-immersive
.tq-margin__icon-expand{
  display:none;
}


.tq-margin.is-immersive
.tq-margin__icon-contract{
  display:block;
}


/* =========================================================
   Stage
   ========================================================= */

.tq-margin__stage{
  position:relative;
  z-index:1;

  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;

  gap:clamp(2rem,7cqw,4rem);

  min-width:0;
  min-height:0;
}

.tq-margin.is-immersive .tq-margin__stage{
  gap:clamp(2rem,5dvh,4.5rem);

  /*
   * Shift the composition upward by changing its internal free space,
   * not by transforming the stage itself. Transforming the stage can
   * move its hit-testing box over the header and block controls.
   */
  padding-bottom:clamp(2.5rem,7dvh,5rem);
}


/* =========================================================
   Circle
   ========================================================= */

.tq-margin__circle{
  appearance:none;

  position:relative;

  display:grid;
  place-items:center;

  width:clamp(13rem,36cqw,19rem);
  aspect-ratio:1;

  margin:0;
  padding:0;

  border:1px solid var(--tqm-line);
  border-radius:50%;

  background:transparent;
  color:inherit;

  font:inherit;

  cursor:pointer;

  user-select:none;
  -webkit-user-select:none;

  -webkit-tap-highlight-color:transparent;

  transition:
    transform 700ms cubic-bezier(.2,.8,.2,1),
    border-color 700ms ease;
}


.tq-margin__circle::before{
  content:"";

  position:absolute;
  inset:14%;

  border-radius:50%;

  background:rgba(23,23,23,.035);

  opacity:0;
  transform:scale(.1);

  transition:
    transform 1200ms cubic-bezier(.2,.8,.2,1),
    opacity 700ms ease;
}


.tq-margin__circle:hover{
  border-color:rgba(23,23,23,.22);
}


.tq-margin__circle:focus-visible{
  outline:1px solid rgba(23,23,23,.38);
  outline-offset:6px;
}


.tq-margin__circle.is-active{
  transform:scale(1.08);

  border-color:rgba(23,23,23,.28);
}


.tq-margin__circle.is-active::before{
  opacity:1;
  transform:scale(1);
}

/* A return leaves a small, temporary trace without adding words. */
.tq-margin__circle::after{
  content:"";
  position:absolute;
  inset:calc(10% + var(--tqm-return-depth, 0) * 3%);
  border:1px solid var(--tqm-line);
  border-radius:50%;
  opacity:0;
  transform:scale(.96);
  pointer-events:none;
  transition:opacity 900ms ease, transform 1200ms ease, inset 900ms ease;
}

.tq-margin__circle.is-returned::after{
  opacity:.65;
  transform:scale(1);
}



.tq-margin.is-immersive .tq-margin__circle{
  width:clamp(13.75rem,30dvmin,25rem);
}


/* =========================================================
   Word
   ========================================================= */

.tq-margin__word{
  position:relative;
  z-index:1;

  max-width:none;
  margin:0;

  white-space:nowrap;
  word-break:keep-all;
  overflow-wrap:normal;
  text-wrap:nowrap;

  text-align:center;

  font-family:
    Georgia,
    "Yu Mincho",
    "Hiragino Mincho ProN",
    serif;

  font-size:clamp(1.125rem,3.6cqw,1.625rem);
  line-height:1.45;

  letter-spacing:.065em;

  transition:
    opacity 350ms ease,
    transform 350ms ease;
}

.tq-margin.is-immersive .tq-margin__word{
  font-size:clamp(1.125rem,2.1dvmin,1.75rem);
}


.tq-margin__word.is-fading{
  opacity:0;

  transform:translateY(6px);
}


/* =========================================================
   Hint
   ========================================================= */

.tq-margin__hint{
  position:static;

  max-width:100%;
  margin:0;

  white-space:nowrap;
  word-break:keep-all;
  overflow-wrap:normal;

  color:var(--tqm-muted);

  font-size:.75rem;
  line-height:1.6;

  letter-spacing:.07em;

  text-align:center;
}

.tq-margin.is-immersive .tq-margin__hint{
  font-size:clamp(.75rem,.9dvmin,.9375rem);
}


/* =========================================================
   Footer
   ========================================================= */

.tq-margin__footer{
  position:relative;
  z-index:3;

  display:flex;
  align-items:center;
  justify-content:space-between;

  gap:20px;

  color:var(--tqm-muted);

  font-size:.75rem;
  line-height:1.5;
}

.tq-margin__dateTime{
  margin:0;
  min-width:0;
  font-size:inherit;
  line-height:1.5;
  letter-spacing:.025em;
  font-variant-numeric:tabular-nums;
  white-space:nowrap;
}


.tq-margin__reset{
  appearance:none;

  margin:0;
  padding:0;

  border:0;
  border-bottom:1px solid var(--tqm-line);

  background:transparent;
  color:inherit;

  font:inherit;

  cursor:pointer;

  -webkit-tap-highlight-color:transparent;
}


.tq-margin__reset:hover{
  border-bottom-color:currentColor;
}


.tq-margin__reset:focus-visible{
  outline:1px solid currentColor;
  outline-offset:4px;
}


/* =========================================================
   Tablet
   ========================================================= */

@media (max-width:959px){

  .tq-margin{
    height:clamp(32rem,68svh,46rem);
  }

}


/* =========================================================
   Mobile
   ========================================================= */

@media (max-width:600px){

  .tq-margin{
    height:clamp(32rem,66svh,42rem);

    padding:
      1.125rem
      clamp(1.25rem,5.5cqw,1.75rem)
      1.125rem;
  }


  .tq-margin.is-immersive{
    padding:
      max(clamp(1rem,2.2dvh,1.375rem),env(safe-area-inset-top))
      max(clamp(1rem,5dvw,1.5rem),env(safe-area-inset-right))
      max(clamp(1rem,2dvh,1.25rem),env(safe-area-inset-bottom))
      max(clamp(1rem,5dvw,1.5rem),env(safe-area-inset-left)) !important;
  }


  .tq-margin__tools{
    gap:9px;
  }


  .tq-margin__fullscreen{
    margin:
      0
      -10px
      0
      0;
  }


}




/* =========================================================
   Container-aware embedded layout
   ========================================================= */

@container tq-margin (max-width:430px){
  .tq-margin:not(.is-immersive) .tq-margin__header{gap:8px;}
  .tq-margin:not(.is-immersive) .tq-margin__tools{flex:0 1 auto;}
  .tq-margin:not(.is-immersive) .tq-margin__footer{
    gap:10px;
    min-width:0;
  }
}

@container tq-margin (max-width:320px){
  .tq-margin:not(.is-immersive) .tq-margin__header,
  .tq-margin:not(.is-immersive) .tq-margin__footer{
    flex-wrap:wrap;
  }
  .tq-margin:not(.is-immersive) .tq-margin__tools{margin-left:auto;}
}

/* =========================================================
   Browser zoom / large text / narrow CSS viewport resilience
   ========================================================= */

/*
 * Browser zoom reduces the CSS viewport. These rules keep the artwork
 * operable at high zoom without disabling user zoom or OS text scaling.
 */
@media (max-width:360px){
  .tq-margin__header{
    gap:8px;
  }

  .tq-margin__tools{
    flex:0 1 auto;
  }

  .tq-margin__footer{
    gap:10px;
    min-width:0;
  }

  .tq-margin__footer > *{
    min-width:0;
  }
}

@media (max-width:320px){
  .tq-margin__header{
    align-items:flex-start;
    flex-wrap:wrap;
  }

  .tq-margin__tools{
    margin-left:auto;
  }

  .tq-margin__footer{
    flex-wrap:wrap;
  }
}

/* Short landscape windows, browser zoom, split-screen and desktop magnifiers. */
@media (max-height:520px){
  .tq-margin.is-immersive{
    padding-top:max(.75rem,env(safe-area-inset-top)) !important;
    padding-bottom:max(.75rem,env(safe-area-inset-bottom)) !important;
  }

  .tq-margin.is-immersive .tq-margin__stage{
    gap:clamp(1rem,3dvh,1.75rem);
    padding-bottom:0;
  }

  .tq-margin.is-immersive .tq-margin__circle{
    width:clamp(9rem,32dvh,13rem);
  }
}

@media (max-height:380px){
  .tq-margin.is-immersive .tq-margin__circle{
    width:clamp(8rem,34dvh,10rem);
  }

  .tq-margin.is-immersive .tq-margin__hint{
    font-size:.6875rem;
  }
}


@media (max-width:360px){
  .tq-margin__header{
    align-items:flex-start;
    flex-wrap:wrap;
  }

  .tq-margin__tools{
    row-gap:.25rem;
  }

  #tq-margin-audio{
    margin-left:0;
  }

  .tq-margin__themeSwitch{
    margin-right:auto;
  }

  .tq-margin__footer{
    gap:.75rem;
  }
}

/* =========================================================
   Reduced motion
   ========================================================= */

@media (prefers-reduced-motion:reduce){

  .tq-margin *,
  .tq-margin *::before,
  .tq-margin *::after{
    transition:none !important;
    animation:none !important;
  }

}

/* =========================================================
   Appearance
   Auto = existing local-time behavior (18:00–05:59 is dark).
   Explicit user choice overrides the automatic period.
   ========================================================= */

/* Local time, not geographic sunrise/sunset. */
.tq-margin[data-period="night"]:not([data-theme-choice="light"]){
  --tqm-bg:#242522;
  --tqm-fg:#e4e0d6;
  --tqm-muted:#b0afa8;
  --tqm-line:rgba(228,224,214,.35);
  --tqm-wash:rgba(228,224,214,.055);
}

.tq-margin[data-theme-choice="dark"]{
  --tqm-bg:#242522;
  --tqm-fg:#e4e0d6;
  --tqm-muted:#b0afa8;
  --tqm-line:rgba(228,224,214,.35);
  --tqm-wash:rgba(228,224,214,.055);
}

.tq-margin[data-theme-choice="light"]{
  --tqm-bg:#f4f2ec;
  --tqm-fg:#171717;
  --tqm-muted:#7a7770;
  --tqm-line:rgba(23,23,23,.14);
  --tqm-wash:rgba(23,23,23,.035);
}

.tq-margin:not(.is-immersive)[data-period="night"]:not([data-theme-choice="light"]),
.tq-margin:not(.is-immersive)[data-theme-choice="dark"]{
  background:var(--tqm-bg);
}

.tq-margin:not(.is-immersive)[data-theme-choice="light"]{
  background:transparent;
}

/* Compact state mark inside the appearance utility. */

/* =========================================================
   Appearance selector — Magic v4.7 language-selector geometry
   ========================================================= */

.tq-margin__themeSwitch{
  display:inline-flex;
  align-items:center;
  flex:0 0 auto;
  gap:4px;
  padding:4px;
  border:1px solid var(--tqm-line);
  border-radius:999px;
  background:transparent;
  isolation:isolate;
}

.tq-margin__themeOption{
  appearance:none;
  display:grid;
  place-items:center;
  flex:0 0 44px;
  width:44px;
  min-width:44px;
  height:44px;
  min-height:44px;
  margin:0;
  padding:0;
  border:0;
  border-radius:999px;
  background:transparent;
  color:var(--tqm-muted);
  font:inherit;
  font-size:12px;
  line-height:1;
  cursor:pointer;
  -webkit-tap-highlight-color:transparent;
  touch-action:manipulation;
  transition:
    background 160ms ease,
    color 160ms ease,
    transform 160ms ease,
    box-shadow 160ms ease;
}

.tq-margin__themeOption[aria-pressed="true"]{
  background:color-mix(in srgb,var(--tqm-fg) 9%,transparent);
  color:var(--tqm-fg);
  box-shadow:
    0 1px 0 color-mix(in srgb,var(--tqm-bg) 82%,transparent),
    0 .25em .875em color-mix(in srgb,var(--tqm-fg) 8%,transparent);
}

.tq-margin__themeOption:active{
  transform:scale(.97);
}

.tq-margin__themeOption:focus-visible{
  outline:2px solid currentColor;
  outline-offset:3px;
}

.tq-margin__themeMark{
  display:block;
  min-width:1em;
  font-family:
    -apple-system,
    BlinkMacSystemFont,
    "Hiragino Sans",
    "Yu Gothic",
    sans-serif;
  font-size:.875rem;
  line-height:1;
  letter-spacing:0;
  text-align:center;
  pointer-events:none;
}

.tq-margin__themeOption[data-theme-value="light"] .tq-margin__themeMark,
.tq-margin__themeOption[data-theme-value="dark"] .tq-margin__themeMark{
  font-size:1.125rem;
}

@supports not (background:color-mix(in srgb,black 10%,transparent)){
  .tq-margin__themeOption[aria-pressed="true"]{
    background:rgba(127,127,127,.12);
    box-shadow:none;
  }
}

.tq-margin__circle{
  --tqm-center-shift:calc(var(--tqm-history) * .35px);
  transform:translate(var(--tqm-center-shift),0);
  touch-action:inherit;
  -webkit-touch-callout:none;
  transition:transform 850ms cubic-bezier(.2,.8,.2,1),border-color 850ms ease;
}
.tq-margin__circle.is-active{
  transform:translate(var(--tqm-center-shift),0) scale(1.08);
}
.tq-margin__circle::before{
  background:var(--tqm-wash);
  translate:var(--tqm-touch-x) var(--tqm-touch-y);
  opacity:calc(var(--tqm-idle) * .45);
  transform:scale(calc(.1 + var(--tqm-idle) * .9));
}
.tq-margin__circle.is-active::before{
  opacity:calc(.55 + var(--tqm-idle) * .3);
  transform:scale(1);
}
.tq-margin__circle::after{
  inset:calc(10% + var(--tqm-return-depth) * 3%);
  opacity:calc(var(--tqm-history) * .11);
}
.tq-margin__circle.is-returned::after{opacity:.65;}
.tq-margin__circle.is-holding::before{opacity:.7;transform:scale(1);}
.tq-margin__circle.is-paused{border-color:var(--tqm-fg);}
.tq-margin__circle.is-returning::after{opacity:.85;}
.tq-margin__word{transition:opacity 350ms ease,transform 350ms ease;}
.tq-margin__circle.is-word-lag::after{transition-delay:var(--tqm-delay);}
.tq-margin__utility{
  appearance:none;
  display:grid;
  place-items:center;
  flex:0 0 44px;
  width:44px;
  min-width:44px;
  height:44px;
  min-height:44px;
  margin:0;
  padding:0;
  border:0;
  color:var(--tqm-muted);
  background:transparent;
  font:inherit;
  font-size:12px;
  line-height:1;
  cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
.tq-margin__utility[aria-pressed="true"]{color:var(--tqm-fg);}
.tq-margin__utility:focus-visible{outline:2px solid currentColor;outline-offset:3px;}
.tq-margin__utility:disabled{opacity:.35;cursor:default;}
.tq-margin__utility svg{
  display:block;
  width:1.375rem;
  height:1.375rem;
  fill:none;
  stroke:currentColor;
  stroke-width:1.5;
  stroke-linecap:round;
  stroke-linejoin:round;
  pointer-events:none;
}
.tq-margin__sr-only{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important;}
.tq-margin.is-immersive{overscroll-behavior:contain;}
@media (max-width:600px){
  .tq-margin__tools{gap:4px;}
  .tq-margin__fullscreen{margin-right:-8px;}
  .tq-margin__header{gap:6px;}
  .tq-margin__themeSwitch{gap:2px;padding:2px;}
  .tq-margin__themeOption{
    flex-basis:44px;
    width:44px;
    min-width:44px;
    height:44px;
    min-height:44px;
  }
}

@media (max-width:430px){
  .tq-margin__header{
    align-items:flex-start;
    flex-wrap:wrap;
  }

  .tq-margin__tools{
    width:100%;
    justify-content:flex-end;
  }
}

@media (max-width:350px){
}
/* Independent, non-instructional 24-second breathing. No motion when reduced motion is requested. */
@keyframes tqm-breathe{
  0%,100%{box-shadow:0 0 0 0 transparent;}
  50%{box-shadow:0 0 0 3px var(--tqm-line);}
}
.tq-margin.is-immersive .tq-margin__circle{
  animation:tqm-breathe 24s ease-in-out infinite;
}
@media (prefers-contrast:more){
 .tq-margin{--tqm-line:currentColor;}
 .tq-margin__circle,.tq-margin__utility:focus-visible{border-width:2px;}
}
@media (forced-colors:active){
  /*
   * Respect the user's forced color palette. Do not opt out with
   * forced-color-adjust:none; only guarantee that structure remains visible.
   */
  .tq-margin{
    --tqm-fg:CanvasText;
    --tqm-muted:CanvasText;
    --tqm-line:CanvasText;
    --tqm-wash:transparent;
  }

  .tq-margin__circle,
  .tq-margin__circle::after{
    border-color:CanvasText;
  }

  .tq-margin__circle::before{
    background:transparent;
    border:1px solid CanvasText;
  }

  .tq-margin__word,
  .tq-margin__footer{
    color:CanvasText;
  }

  .tq-margin__utility,
  .tq-margin__themeOption,
  .tq-margin__reset{
    color:ButtonText;
  }

  .tq-margin__themeSwitch{
    border-color:ButtonText;
  }

  .tq-margin__themeOption[aria-pressed="true"]{
    background:Highlight;
    color:HighlightText;
    box-shadow:none;
  }

  .tq-margin__reset{
    border-bottom-color:ButtonText;
  }

  .tq-margin__circle:focus-visible,
  .tq-margin__utility:focus-visible,
  .tq-margin__reset:focus-visible{
    outline:2px solid Highlight;
    outline-offset:3px;
  }

  .tq-margin__utility svg{
    stroke:currentColor;
  }
}

/* Pointer-capability differences: hover remains optional and never required. */
@media (hover:none){
  .tq-margin__circle:hover{
    border-color:var(--tqm-line);
  }

  .tq-margin__reset:hover{
    border-bottom-color:var(--tqm-line);
  }
}

@media (pointer:coarse){
  .tq-margin__circle,
  .tq-margin__utility,
  .tq-margin__theme,
  .tq-margin__fullscreen,
  .tq-margin__reset{
    -webkit-tap-highlight-color:transparent;
  }
}

@media (prefers-reduced-motion:reduce){
 .tq-margin{transition:none!important;}
 .tq-margin.is-immersive .tq-margin__circle{animation:none!important;}
}

</style>


<div class="tq-margin" id="tq-margin"
  data-responsive-contract="single-dom-container-aware"
  data-input-contract="single-primary-mouse-touch-pen-keyboard"
  data-viewport-contract="safe-area-dvh-visual-viewport"
  data-storage-contract="appearance-local-only"
  data-motion-contract="reduced-motion-respected"
  data-color-contract="forced-colors-prefers-contrast"
  data-persistence-contract="experience-ephemeral-appearance-persistent">

  <div class="tq-margin__header">

    <div class="tq-margin__tools">

      <div class="tq-margin__themeSwitch" id="tq-margin-theme" role="group" aria-label="表示モード">
        <button class="tq-margin__themeOption" type="button"
          data-theme-choice="auto" data-theme-value="auto"
          aria-label="表示: 自動" aria-pressed="true" title="自動">
          <span class="tq-margin__themeMark" aria-hidden="true">A</span>
        </button>
        <button class="tq-margin__themeOption" type="button"
          data-theme-choice="light" data-theme-value="light"
          aria-label="表示: ライト" aria-pressed="false" title="ライト">
          <span class="tq-margin__themeMark" aria-hidden="true"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2600.png" alt="☀" class="wp-smiley" style="height: 1em; max-height: 1em;" /></span>
        </button>
        <button class="tq-margin__themeOption" type="button"
          data-theme-choice="dark" data-theme-value="dark"
          aria-label="表示: ダーク" aria-pressed="false" title="ダーク">
          <span class="tq-margin__themeMark" aria-hidden="true"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f319.png" alt="🌙" class="wp-smiley" style="height: 1em; max-height: 1em;" /></span>
        </button>
      </div>

      <button class="tq-margin__utility" id="tq-margin-audio" type="button" aria-label="音を有効にする" aria-pressed="false" title="音を有効にする">
        <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 9v6h4l5 4V5L8 9H4z"/><path d="M17 9c2 1.5 2 4.5 0 6"/></svg>
      </button>
      <button class="tq-margin__utility" id="tq-margin-wake" type="button" aria-label="画面点灯を維持する" aria-pressed="false" title="画面点灯を維持する">
        <svg viewBox="0 0 24 24" aria-hidden="true"><rect x="5" y="3" width="14" height="18" rx="2"/><path d="M10 17h4"/></svg>
      </button>
      <button class="tq-margin__fullscreen" id="tq-margin-fullscreen" type="button" aria-label="ブラウザ内全画面で表示" aria-pressed="false" title="全画面表示">

        <!-- ===============================================
             EXPAND
             <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2199.png" alt="↙" class="wp-smiley" style="height: 1em; max-height: 1em;" />      <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2197.png" alt="↗" class="wp-smiley" style="height: 1em; max-height: 1em;" />
             =============================================== -->

        <svg class="
            tq-margin__fullscreenIcon
            tq-margin__icon-expand
          " viewBox="0 0 24 24" aria-hidden="true">

          <!-- &#x2199; -->

          <path d="
              M10 14
              L5 19
            "></path>

          <path d="
              M10.5 19
              H5
              V13.5
            "></path>


          <!-- &#x2197; -->

          <path d="
              M14 10
              L19 5
            "></path>

          <path d="
              M13.5 5
              H19
              V10.5
            "></path>

        </svg>


        <!-- ===============================================
             CONTRACT
             中央へ向かう2矢印
             =============================================== -->

        <svg class="
            tq-margin__fullscreenIcon
            tq-margin__icon-contract
          " viewBox="0 0 24 24" aria-hidden="true">

          <!-- 右上 → 中央 -->

          <path d="
              M19 5
              L14 10
            "></path>

          <path d="
              M14 5
              V10
              H19
            "></path>


          <!-- 左下 → 中央 -->

          <path d="
              M5 19
              L10 14
            "></path>

          <path d="
              M5 14
              H10
              V19
            "></path>

        </svg>

      </button>

    </div>

  </div>


  <section class="tq-margin__stage" aria-label="今日の余白">

    <button class="tq-margin__circle" id="tq-margin-circle" type="button" aria-label="作品を開く。開いた後はことばを変える">

      <span class="tq-margin__word" id="tq-margin-word" aria-live="polite">
        そのまま
      </span>

    </button>


    <p class="tq-margin__hint">
      触れると、少しだけ変わります。
    </p>

    <span class="tq-margin__sr-only" id="tq-margin-status" role="status" aria-live="polite"></span>
  </section>


  <div class="tq-margin__footer">

    <time class="tq-margin__dateTime" id="tq-margin-datetime" aria-label="現在の日付と時刻">&#8212;</time>


    <button class="tq-margin__reset" id="tq-margin-reset" type="button">
      reset
    </button>

  </div>

</div>


<script>
(() => {
  'use strict';
  // This instance uses localStorage only for the user's appearance preference; no analytics or network access.
  const root = document.getElementById('tq-margin');
  if (!root || root.dataset.initialized === 'true') return;
  const get = id => root.querySelector('#' + id);
  const circle = get('tq-margin-circle');
  const word = get('tq-margin-word');
  const dateTime = get('tq-margin-datetime');
  const reset = get('tq-margin-reset');
  const fullscreen = get('tq-margin-fullscreen');
  const themeGroup = get('tq-margin-theme');
  const themeButtons = themeGroup ? Array.from(themeGroup.querySelectorAll('[data-theme-choice]')) : [];
  const audioButton = get('tq-margin-audio');
  const wakeButton = get('tq-margin-wake');
  const status = get('tq-margin-status');
  if ([circle,word,dateTime,reset,fullscreen,themeGroup,audioButton,wakeButton,status].some(el=>!el)) return;
  if (themeButtons.length!==3) return;
  root.dataset.initialized = 'true';
  const words = ['そのまま','まだ決めない','ここにいる','少し離れる','窓を見る','戻ってくる','今日はここまで'];
  const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
  const themeStorageKey = 'tq-margin-theme-v1';
  const themeOrder = ['auto','light','dark'];
  const state = {
    index:0, rounds:0, history:0, immersive:false, changing:false,
    changeTimer:null, lagTimer:null, returnTimer:null,
    visible:!document.hidden, inView:false, idleSeconds:0, lastTick:Date.now(),
    hiddenAt:null, lockedScrollY:0, bodyStyles:null, focusBefore:null,
    inertElements:[], pointer:null, holdTimer:null, holdActive:false,
    suppressClick:false, themeChoice:'auto', inputMode:'unknown',
    audioEnabled:false, audioContext:null,
    wakeWanted:false, wakeLock:null, wakeRequestPending:false
  };
  const placeholder = document.createComment('tq-margin-origin');
  const originalParent = root.parentNode;
  const originalNextSibling = root.nextSibling;
  const lockProps = ['position','top','left','right','width'];
  const announce = message => {status.textContent = message;};
  const clearTimer = key => {if (state[key] !== null) {clearTimeout(state[key]);state[key]=null;}};
  const isReduced = () => reduceMotion.matches;

  function clearPointerState({clearSuppression=false}={}) {
    clearTimer('holdTimer');
    state.pointer=null;
    state.holdActive=false;
    circle.classList.remove('is-holding');
    circle.removeAttribute('data-contact-state');
    if (clearSuppression) state.suppressClick=false;
  }

  function setInputMode(mode){
    state.inputMode=mode;
    root.dataset.inputMode=mode;
  }

  function clearTransientInteractionState(){
    clearPointerState({clearSuppression:true});
    ['changeTimer','lagTimer','returnTimer'].forEach(clearTimer);
    state.changing=false;
    word.classList.remove('is-fading');
    circle.classList.remove(
      'is-holding',
      'is-word-lag',
      'is-returned',
      'is-returning',
      'is-paused'
    );
    circle.removeAttribute('data-contact-state');
  }

  function readThemeChoice() {
    try {
      const value=window.localStorage.getItem(themeStorageKey);
      return themeOrder.includes(value)?value:'auto';
    } catch (_) {
      return 'auto';
    }
  }

  function persistThemeChoice(value) {
    try {
      window.localStorage.setItem(themeStorageKey,value);
    } catch (_) {
      // Storage can be unavailable (private mode, policy, blocked storage).
      // The choice still applies for the current page session.
    }
  }

  function syncThemeUI({announceChange=false}={}) {
    const value=state.themeChoice;
    root.dataset.themeChoice=value;

    const labels={
      auto:'自動',
      light:'ライト',
      dark:'ダーク'
    };

    themeButtons.forEach(button=>{
      const selected=button.dataset.themeChoice===value;
      button.setAttribute('aria-pressed',selected?'true':'false');
    });

    if (announceChange) {
      announce(`表示を${labels[value] || labels.auto}に変更しました`);
    }
  }

  function setThemeChoice(value,{persist=true,announceChange=false}={}) {
    state.themeChoice=themeOrder.includes(value)?value:'auto';
    syncThemeUI({announceChange});
    if (persist) persistThemeChoice(state.themeChoice);
  }

  state.themeChoice=readThemeChoice();
  syncThemeUI();

  themeButtons.forEach(button=>{
    button.addEventListener('click',()=>{
      setThemeChoice(button.dataset.themeChoice,{
        persist:true,
        announceChange:true
      });
    });
  });

  function moveToBody() {
    if (root.parentNode === document.body) return;
    root.parentNode.insertBefore(placeholder,root);
    document.body.appendChild(root);
  }
  function restoreToOrigin() {
    if (placeholder.parentNode) {
      placeholder.parentNode.insertBefore(root,placeholder);
      placeholder.remove();
    } else if (originalParent) {
      if (originalNextSibling && originalNextSibling.parentNode === originalParent) originalParent.insertBefore(root,originalNextSibling);
      else originalParent.appendChild(root);
    }
  }
  function lockPage() {
    state.lockedScrollY=window.scrollY || window.pageYOffset || 0;
    state.bodyStyles=lockProps.map(property=>({property,value:document.body.style.getPropertyValue(property),priority:document.body.style.getPropertyPriority(property)}));
    const body=document.body.style;
    body.setProperty('position','fixed');body.setProperty('top',`-${state.lockedScrollY}px`);
    body.setProperty('left','0');body.setProperty('right','0');body.setProperty('width','100%');
  }
  function unlockPage() {
    if (!state.bodyStyles) return;
    state.bodyStyles.forEach(({property,value,priority})=>{
      if (value) document.body.style.setProperty(property,value,priority);
      else document.body.style.removeProperty(property);
    });
    state.bodyStyles=null;
    window.scrollTo(0,state.lockedScrollY);
  }
  function isolateBackground() {
    // Only body siblings; preserve pre-existing inert state, never inert the work itself.
    state.inertElements=[];
    for (const el of document.body.children) {
      if (el === root || ['SCRIPT','STYLE'].includes(el.tagName)) continue;
      state.inertElements.push({el,wasInert:el.inert});
      el.inert=true;
    }
  }
  function restoreBackground() {
    state.inertElements.forEach(({el,wasInert})=>{el.inert=wasInert;});
    state.inertElements=[];
  }
  function syncImmersiveUI() {
    root.classList.toggle('is-immersive',state.immersive);
    fullscreen.setAttribute('aria-pressed',String(state.immersive));
    fullscreen.setAttribute('aria-label',state.immersive?'ブラウザ内全画面を終了':'ブラウザ内全画面で表示');
    fullscreen.title=state.immersive?'全画面表示を終了':'全画面表示';
    circle.setAttribute('aria-label',state.immersive?'ことばを変える':'作品を開く。開いた後はことばを変える');
  }
  function enterImmersive() {
    if (state.immersive) return;
    state.focusBefore=document.activeElement;
    lockPage();moveToBody();state.immersive=true;syncImmersiveUI();isolateBackground();
    circle.focus({preventScroll:true});
    requestWake();
  }
  function exitImmersive({focus=true}={}) {
    if (!state.immersive) return;
    clearPointerState({clearSuppression:true});
    state.immersive=false;syncImmersiveUI();restoreBackground();restoreToOrigin();unlockPage();releaseWake();
    if (focus) {
      const target=state.focusBefore && state.focusBefore.isConnected ? state.focusBefore : fullscreen;
      if (target && typeof target.focus === 'function') target.focus({preventScroll:true});
    }
  }
  function toggleImmersive() {state.immersive?exitImmersive():enterImmersive();}
  fullscreen.addEventListener('click',toggleImmersive);
  document.addEventListener('keydown',event=>{
    setInputMode('keyboard');
    if (!state.immersive) return;
    if (event.key==='Escape') {event.preventDefault();exitImmersive();return;}
    if (event.key!=='Tab') return;
    const items=[...root.querySelectorAll('button:not(:disabled),a[href],input:not(:disabled),[tabindex]:not([tabindex="-1"])')].filter(el=>el.getClientRects().length);
    if (!items.length) return;
    const first=items[0],last=items[items.length-1];
    if (event.shiftKey && (document.activeElement===first || !root.contains(document.activeElement))) {event.preventDefault();last.focus();}
    else if (!event.shiftKey && (document.activeElement===last || !root.contains(document.activeElement))) {event.preventDefault();first.focus();}
  });

  function applyTrace() {
    root.style.setProperty('--tqm-history',String(Math.min(state.history,3)));
    root.style.setProperty('--tqm-return-depth',String(Math.min(state.rounds,3)));
  }
  function markReturn() {
    clearTimer('returnTimer');circle.classList.add('is-returned','is-returning');
    state.returnTimer=setTimeout(()=>{circle.classList.remove('is-returned','is-returning');state.returnTimer=null;},isReduced()?0:2200);
  }
  function playTouch() {
    if (!state.audioEnabled || !state.audioContext || document.hidden) return;
    const ctx=state.audioContext;
    if (ctx.state!=='running') ctx.resume().catch(()=>{});
    try {
      const oscillator=ctx.createOscillator(),gain=ctx.createGain();
      oscillator.type='sine';oscillator.frequency.setValueAtTime(190 + state.index*11,ctx.currentTime);
      gain.gain.setValueAtTime(.0001,ctx.currentTime);
      gain.gain.exponentialRampToValueAtTime(.013,ctx.currentTime+.04);
      gain.gain.exponentialRampToValueAtTime(.0001,ctx.currentTime+.55);
      oscillator.connect(gain);gain.connect(ctx.destination);
      oscillator.start();oscillator.stop(ctx.currentTime+.6);
      oscillator.onended=()=>{oscillator.disconnect();gain.disconnect();};
    } catch (_) { /* Audio is optional and never blocks the core interaction. */ }
  }
  function changeWord() {
    if (state.changing) return;
    state.changing=true;state.idleSeconds=0;applyIdle();
    circle.classList.remove('is-returned','is-returning','is-paused');
    circle.classList.toggle('is-active');
    const delay=isReduced()?0:280;
    if (delay) word.classList.add('is-fading');
    state.changeTimer=setTimeout(()=>{
      state.changeTimer=null;state.index=(state.index+1)%words.length;
      if (state.index===0) {state.rounds++;state.history=Math.min(state.history+1,3);applyTrace();markReturn();}
      word.textContent=words[state.index];word.classList.remove('is-fading');
      circle.classList.add('is-word-lag');root.style.setProperty('--tqm-delay',isReduced()?'0ms':'800ms');
      clearTimer('lagTimer');state.lagTimer=setTimeout(()=>{circle.classList.remove('is-word-lag');state.lagTimer=null;},isReduced()?0:900);
      state.changing=false;playTouch();
    },delay);
  }
  function mainAction() {
    if (!state.immersive) {enterImmersive();return;}
    changeWord();
  }
  circle.addEventListener('click',event=>{
    if (state.suppressClick) {event.preventDefault();state.suppressClick=false;return;}
    mainAction();
  });

  // Pointer position changes only the subtle visual response. Keyboard input stays equivalent.
  document.addEventListener('pointerdown',event=>{
    if (event.pointerType==='touch') setInputMode('touch');
    else if (event.pointerType==='pen') setInputMode('pen');
    else setInputMode('mouse');
  },{passive:true});

  circle.addEventListener('pointerdown',event=>{
    if (event.button!==0 || !event.isPrimary) return;

    const rect=circle.getBoundingClientRect();
    const dx=((event.clientX-rect.left)/rect.width-.5)*10;
    const dy=((event.clientY-rect.top)/rect.height-.5)*10;
    root.style.setProperty('--tqm-touch-x',dx.toFixed(2)+'px');
    root.style.setProperty('--tqm-touch-y',dy.toFixed(2)+'px');

    clearTimer('holdTimer');
    state.holdActive=false;
    state.pointer=null;

    /*
     * Long-press is supplementary, never required.
     * Restrict the custom hold gesture to direct touch only:
     * - pen/stylus long-press is commonly reserved for right-click
     * - mouse press-and-hold should remain ordinary pointer behavior
     * - multi-touch/system gestures are not used as artwork input
     */
    if (event.pointerType!=='touch') return;

    circle.dataset.contactState='contact';

    state.pointer={
      id:event.pointerId,
      x:event.clientX,
      y:event.clientY,
      type:event.pointerType
    };

    state.holdTimer=setTimeout(()=>{
      if (!state.pointer || state.pointer.type!=='touch') return;
      state.holdActive=true;
      state.suppressClick=true;
      circle.dataset.contactState='holding';
      circle.classList.add('is-holding');
      if (!state.immersive) enterImmersive();
      state.history=Math.min(3,state.history+.25);
      applyTrace();
      announce('円の輪郭が変わりました');
      playTouch();
    },650);
  });
  circle.addEventListener('pointermove',event=>{
    if (!state.pointer || state.pointer.id!==event.pointerId) return;
    if (Math.hypot(event.clientX-state.pointer.x,event.clientY-state.pointer.y)>12) {clearTimer('holdTimer');}
  });
  function endPointer() {
    const wasHold=state.holdActive;
    clearPointerState();
    if (wasHold) {
      // Some engines emit click after a long press while others suppress it.
      // Keep suppression briefly, then release it so a missing click cannot
      // block the user's next intentional tap.
      setTimeout(()=>{state.suppressClick=false;},500);
    }
  }

  function cancelPointer() {
    clearPointerState({clearSuppression:true});
  }

  circle.addEventListener('pointerup',endPointer);
  circle.addEventListener('pointercancel',cancelPointer);
  circle.addEventListener('lostpointercapture',cancelPointer);
  circle.addEventListener('pointerleave',event=>{
    if (state.pointer && state.pointer.id===event.pointerId) cancelPointer();
  });

  // Some touch engines dispatch touchcancel independently of Pointer Events.
  circle.addEventListener('touchcancel',cancelPointer,{passive:true});

  // Prevent Safari long-press callouts inside the artwork.
  circle.addEventListener('contextmenu',event=>{
    /*
     * Suppress browser/OS context menus only on the artwork control.
     * This covers touch press-and-hold and Windows touch/pen right-click
     * without globally disabling context menus on the page.
     */
    if (state.immersive || state.holdActive) event.preventDefault();
  });

  function applyIdle() {
    root.style.setProperty('--tqm-idle',String(Math.min(state.idleSeconds/90,1).toFixed(3)));
  }
  const observer=('IntersectionObserver' in window)?new IntersectionObserver(entries=>{
    state.inView=entries.some(entry=>entry.isIntersecting && entry.intersectionRatio>=.5);
    state.lastTick=Date.now();
  },{threshold:[0,.5,1]}):null;
  if (observer) observer.observe(root);
  else state.inView=true;
  const idleInterval=window.setInterval(()=>{
    const now=Date.now(),delta=Math.max(0,Math.min(2,(now-state.lastTick)/1000));state.lastTick=now;
    if (state.visible && state.inView && !state.changing) {
      state.idleSeconds=Math.min(90,state.idleSeconds+delta);
      applyIdle();
    }
  },1000);

  function resetExperience() {
    ['changeTimer','lagTimer','returnTimer'].forEach(clearTimer);
    clearPointerState({clearSuppression:true});
    state.index=0;state.rounds=0;state.changing=false;state.idleSeconds=0;
    word.textContent=words[0];word.classList.remove('is-fading');
    circle.classList.remove('is-active','is-returned','is-returning','is-paused','is-word-lag','is-holding');
    // A subtle in-session trace remains. Reset does not change the saved appearance choice.
    state.history=Math.min(3,state.history+.25);applyTrace();applyIdle();
    announce('最初のことばに戻りました');
  }
  reset.addEventListener('click',resetExperience);

  function updateDateTime() {
    const now=new Date();

    const dateText=now.toLocaleDateString(
      'ja-JP',
      {year:'numeric',month:'2-digit',day:'2-digit',weekday:'short'}
    );

    const timeText=now.toLocaleTimeString(
      'ja-JP',
      {hour:'2-digit',minute:'2-digit'}
    );

    dateTime.textContent=`${dateText}  ${timeText}`;
    dateTime.dateTime=now.toISOString();

    // Auto appearance follows local device time. Explicit Light/Dark remains authoritative in CSS.
    root.dataset.period=(now.getHours()>=18 || now.getHours()<6)?'night':'day';
  }
  updateDateTime();
  const clockInterval=window.setInterval(()=>{
    if (!document.hidden) updateDateTime();
  },30000);

  async function enableAudio() {
    const Ctx=window.AudioContext || window.webkitAudioContext;
    if (!Ctx) {audioButton.disabled=true;announce('このブラウザでは音を利用できません');return;}
    try {
      if (!state.audioContext) state.audioContext=new Ctx();
      await state.audioContext.resume();
      state.audioEnabled=true;audioButton.setAttribute('aria-pressed','true');
      audioButton.setAttribute('aria-label','音を無効にする');audioButton.title='音を無効にする';
      announce('音を有効にしました');
    } catch (_) {announce('音を有効にできませんでした');}
  }
  function disableAudio() {
    state.audioEnabled=false;audioButton.setAttribute('aria-pressed','false');
    audioButton.setAttribute('aria-label','音を有効にする');audioButton.title='音を有効にする';
    if (state.audioContext && state.audioContext.state==='running') state.audioContext.suspend().catch(()=>{});
    announce('音を無効にしました');
  }

  function suspendAudioForLifecycle() {
    if (state.audioContext && state.audioContext.state==='running') {
      state.audioContext.suspend().catch(()=>{});
    }
  }
  audioButton.addEventListener('click',()=>state.audioEnabled?disableAudio():enableAudio());
  if (!(window.AudioContext || window.webkitAudioContext)) audioButton.disabled=true;

  function syncWakeButton() {
    wakeButton.setAttribute('aria-pressed',String(state.wakeWanted));
    wakeButton.setAttribute('aria-label',state.wakeWanted?'画面点灯の維持を終了':'画面点灯を維持する');
    wakeButton.title=state.wakeWanted?'画面点灯の維持を終了':'画面点灯を維持する';
  }
  async function requestWake() {
    if (!state.wakeWanted || !state.immersive || document.hidden || state.wakeLock || state.wakeRequestPending || !navigator.wakeLock) return;
    state.wakeRequestPending=true;
    try {
      const sentinel=await navigator.wakeLock.request('screen');
      if (!state.wakeWanted || !state.immersive || document.hidden) {await sentinel.release();return;}
      state.wakeLock=sentinel;
      sentinel.addEventListener('release',()=>{if (state.wakeLock===sentinel) state.wakeLock=null;});
    } catch (_) {announce('画面点灯の維持は利用できませんでした');state.wakeWanted=false;syncWakeButton();}
    finally {state.wakeRequestPending=false;}
  }
  function releaseWake() {const lock=state.wakeLock;state.wakeLock=null;if(lock)lock.release().catch(()=>{});}
  wakeButton.addEventListener('click',()=>{
    state.wakeWanted=!state.wakeWanted;syncWakeButton();
    if (state.wakeWanted) {announce('没入表示中の画面点灯維持を有効にしました');requestWake();}
    else {releaseWake();announce('画面点灯の維持を終了しました');}
  });
  if (!navigator.wakeLock || !window.isSecureContext) {wakeButton.disabled=true;wakeButton.title='HTTPSと対応ブラウザが必要です';}
  syncWakeButton();

  document.addEventListener('visibilitychange',()=>{
    state.visible=!document.hidden;state.lastTick=Date.now();
    if (!state.visible) {
      state.hiddenAt=Date.now();
      clearPointerState({clearSuppression:true});
      suspendAudioForLifecycle();
      releaseWake();
      return;
    }
    updateDateTime();requestWake();
    if (state.hiddenAt!==null && state.immersive) {
      state.history=Math.min(3,state.history+.25);applyTrace();markReturn();
    }
    state.hiddenAt=null;
  });

  window.addEventListener('pageshow',event=>{
    clearTransientInteractionState();
    updateDateTime();
    resyncViewport();
    syncImmersiveUI();

    if (event.persisted) {
      applyIdle();
      applyTrace();
      if (state.immersive) requestWake();
    }
  });

  // Safari toolbars, rotation and Dynamic Island/safe-area changes can resize the
  // visual viewport without a conventional page resize. Re-sync non-persistent
  // visual state; CSS dvh/safe-area values do the actual layout work.
  let viewportTimer=null;
  function resyncViewport(){
    if (viewportTimer!==null) clearTimeout(viewportTimer);
    viewportTimer=setTimeout(()=>{
      viewportTimer=null;
      applyIdle();
      applyTrace();
    },100);
  }

  function resyncImmersiveViewport(){
    if (state.immersive) resyncViewport();
  }

  window.addEventListener('resize',resyncViewport,{passive:true});
  if (window.visualViewport) {
    window.visualViewport.addEventListener('resize',resyncImmersiveViewport,{passive:true});
    window.visualViewport.addEventListener('scroll',resyncImmersiveViewport,{passive:true});
  }
  if (screen.orientation && screen.orientation.addEventListener) {
    screen.orientation.addEventListener('change',resyncViewport);
  }
  window.addEventListener('pagehide',()=>{
    clearTransientInteractionState();
    suspendAudioForLifecycle();
    releaseWake();
    exitImmersive({focus:false});

    if (viewportTimer!==null) {
      clearTimeout(viewportTimer);
      viewportTimer=null;
    }
  });
  try {
    setInputMode('unknown');
    applyTrace();
    applyIdle();
    syncImmersiveUI();
  } catch (error) {
    console.error('[TODAY / MARGIN] initialization failed.',error);
  }
})();
</script>
]]></content:encoded>
					
					<wfw:commentRss>https://tranquilguides.com/today-margin/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2792</post-id>	</item>
		<item>
		<title>あける</title>
		<link>https://tranquilguides.com/akeru/</link>
					<comments>https://tranquilguides.com/akeru/#respond</comments>
		
		<dc:creator><![CDATA[案内人のアシカ]]></dc:creator>
		<pubDate>Fri, 04 Sep 2026 15:20:00 +0000</pubDate>
				<category><![CDATA[生存ログ]]></category>
		<category><![CDATA[Web Game]]></category>
		<category><![CDATA[体験]]></category>
		<category><![CDATA[扉]]></category>
		<category><![CDATA[開ける]]></category>
		<guid isPermaLink="false">https://tranquilguides.com/?p=2722</guid>

					<description><![CDATA[<p><img src="https://i0.wp.com/tranquilguides.com/wp-content/uploads/2026/09/IMG_20260904_093215.png?fit=1024%2C683&ssl=1" class="webfeedsFeaturedVisual" /></p>戸を開ける。閉じる。また開ける。そのたび、向こう側に違うものが現れる、小さなWEBゲーム。]]></description>
										<content:encoded><![CDATA[<p><img src="https://i0.wp.com/tranquilguides.com/wp-content/uploads/2026/09/IMG_20260904_093215.png?fit=1024%2C683&ssl=1" class="webfeedsFeaturedVisual" /></p>
<!-- =========================================================
  Tranquil Guides / WEB GAME No.1 v3.1

  REBUILT FROM v3.0 CORE + v2.9 FEATURE SET

  CORE
  - v2.3由来 / v3.0で正常動作確認済みの4状態構造を固定
  - closed / opening / revealed / closing
  - 通常表示はコンテンツ高のみ
  - ページ背景 / scene背景の色指定なし
  - シーンは絵文字
  - 発見数「Nつ みつけた」 / 総数非表示
  - 固定Storageキー tranquil-akeru-save
  - 「まだあります」は一度のみ
  - 初回のみ小さな戸の誘導
  - 同一シーン連続回避 / 同一カテゴリ連続を可能な限り回避
  - 外部ライブラリ / 外部画像 / 外部音声なし

  v2.9までから再導入
  - 保存データ正規化
  - presence → reveal → opened の時間分離
  - 未発見sceneを25%だけ弱く優先
  - scene別のpan / delay / noise / lowpass / decay
  - AudioContext非対応時の安全なUI無効化
  - transient timer一括管理
  - visibilitychange / pagehide / pageshow / BFCache対応
  - dvw / dvh / visualViewport / safe-area対応
  - 画面回転 / Mobile Safari viewport再同期
  - prefers-reduced-motion / prefers-contrast / forced-colors対応
  - pointer種別記録
  - Fullscreen APIによる没入表示 / Escape復帰 / focus trap
  - JS内 && を使用しない（WordPress/SWELLのHTMLエンティティ変換対策）
  - 補助UIが欠けてもコアゲームは初期化

  v3.1 FIX
  - tap時の外部微動を抑える layout / paint containment
  - overflow: clip / isolation: isolate
  - SWELL由来 button:active transform / translate / scale / filter を完全リセット
  - hintの高さを常時予約し、表示時のlayout shiftをゼロ化
  - 没入表示でDOM移動 / body固定 / inert / visibility操作を行わない
  ========================================================= -->

<div id="akeru-game-v31" class="akeru-game"
  data-state="closed"
  data-presence-visible="false"
  data-scene-visible="false"
  data-first-cue="false"
  data-input-mode="unknown"
  data-immersive="false"
  data-hint-visible="false">

  <div class="akeru-layout">

    <div class="akeru-tools" aria-label="表示操作">
      <button id="akeru-focus-v31" class="akeru-focus" type="button"
        aria-label="全画面で表示" aria-pressed="false" title="全画面表示">⛶</button>
    </div>

    <button id="akeru-stage-v31" class="akeru-stage" type="button"
      aria-label="戸を開ける" aria-expanded="false">

      <span id="akeru-presence-v31" class="akeru-presence" aria-hidden="true"></span>

      <span id="akeru-scene-v31" class="akeru-scene" aria-hidden="true">
        <span id="akeru-scene-visual-v31" class="akeru-scene-visual" aria-hidden="true"></span>
      </span>

      <span class="akeru-door" aria-hidden="true">
        <span class="akeru-door-face">
          <span class="akeru-door-panel akeru-door-panel-top"></span>
          <span class="akeru-door-panel akeru-door-panel-bottom"></span>
          <span class="akeru-knob"></span>
        </span>
      </span>

    </button>

    <div class="akeru-meta">
      <div class="akeru-progress" aria-live="polite">
        <span id="akeru-progress-count-v31" class="akeru-progress-count">0</span>
        <span>つ みつけた</span>
      </div>

      <button id="akeru-sound-v31" class="akeru-sound" type="button"
        aria-label="音を消す" aria-pressed="true">♪</button>
    </div>

    <p id="akeru-hint-v31" class="akeru-hint" aria-hidden="true">まだあります</p>

  </div>

  <p id="akeru-status-v31" class="akeru-visually-hidden" aria-live="polite"></p>
</div>

<style>
/* =========================================================
   ROOT / EXTERNAL MOVEMENT CONTAINMENT
   ========================================================= */

#akeru-game-v31,
#akeru-game-v31 * {
  box-sizing: border-box;
}

#akeru-game-v31 {
  --akeru-visual-height: 100dvh;

  width: 100%;
  min-width: 0;
  min-height: 0;
  margin: 0;
  padding: 0;
  position: relative;
  display: block;

  /* 戸の3D再描画やtap状態を記事本文の外へ波及させない */
  overflow: clip;
  contain: layout paint;
  isolation: isolate;

  font-family: inherit;
  -webkit-tap-highlight-color: transparent;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

@supports not (overflow: clip) {
  #akeru-game-v31 { overflow: hidden; }
}

/* =========================================================
   LAYOUT
   通常表示はviewport高を予約しない
   ========================================================= */

#akeru-game-v31 .akeru-layout {
  width: 100%;
  min-width: 0;
  min-height: 0;
  margin: 0;
  padding:
    clamp(8px, 1.5vw, 14px)
    max(10px, env(safe-area-inset-right))
    clamp(7px, 1.3vw, 12px)
    max(10px, env(safe-area-inset-left));
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* =========================================================
   TOOLS
   ========================================================= */

#akeru-game-v31 .akeru-tools {
  width: min(68vw, 288px);
  min-height: 32px;
  margin: 0 0 4px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
}

#akeru-game-v31 .akeru-focus {
  width: 36px;
  height: 36px;
  flex: 0 0 36px;
  display: grid;
  place-items: center;
  font-size: 16px;
  opacity: .5;
  cursor: pointer;
  touch-action: manipulation;
}

#akeru-game-v31 .akeru-focus:hover,
#akeru-game-v31 .akeru-focus:focus-visible {
  opacity: 1;
}

/* =========================================================
   BUTTON RESET / SWELL LOCAL RESET
   stage自身は一切動かさない
   ========================================================= */

#akeru-game-v31 button,
#akeru-game-v31 button:hover,
#akeru-game-v31 button:active,
#akeru-game-v31 button:focus {
  margin: 0 !important;
  padding: 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  background: transparent !important;
  color: inherit;
  font: inherit;
  line-height: 1;
  text-transform: none;
  appearance: none;
  -webkit-appearance: none;

  /* SWELL / browserのactive変形を遮断 */
  transform: none !important;
  translate: none !important;
  scale: 1 !important;
  filter: none !important;
  text-shadow: none !important;
}

#akeru-game-v31 button:disabled {
  cursor: default;
  opacity: .24;
}

/* =========================================================
   STAGE
   ========================================================= */

#akeru-game-v31 .akeru-stage {
  width: min(68vw, 288px);
  aspect-ratio: 3 / 4;
  flex: 0 0 auto;
  position: relative;
  display: block;
  margin: 0 auto !important;
  perspective: 1100px;
  cursor: pointer;
  touch-action: manipulation;
  isolation: isolate;
  contain: layout paint style;
  overflow: visible;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

/* =========================================================
   PRESENCE
   sceneの前に、同じ絵文字を距離のあるぼけとして見せる
   ========================================================= */

#akeru-game-v31 .akeru-presence {
  position: absolute;
  inset: 2%;
  display: grid;
  place-items: center;
  font-size: clamp(4rem, 16vw, 7.25rem);
  line-height: 1;
  opacity: 0;
  filter: blur(12px);
  transform: scale(.82);
  transition:
    opacity .18s ease,
    filter .30s ease,
    transform .34s ease;
  pointer-events: none;
}

#akeru-game-v31[data-presence-visible="true"] .akeru-presence {
  opacity: .16;
  filter: blur(8px);
  transform: scale(.9);
}

#akeru-game-v31[data-scene-visible="true"] .akeru-presence {
  opacity: 0;
  filter: blur(14px);
  transform: scale(.96);
}

/* =========================================================
   SCENE
   背景色指定なし
   ========================================================= */

#akeru-game-v31 .akeru-scene {
  position: absolute;
  inset: 2%;
  display: grid;
  place-items: center;
  overflow: hidden;
  opacity: 1;
  pointer-events: none;
}

#akeru-game-v31 .akeru-scene-visual {
  display: block;
  font-size: clamp(4.25rem, 17vw, 7.5rem);
  line-height: 1;
  opacity: 0;
  transform: scale(.88);
  transform-origin: center;
  transition:
    opacity .22s ease,
    transform .34s cubic-bezier(.23,.72,.23,1);
}

#akeru-game-v31[data-scene-visible="true"] .akeru-scene-visual {
  opacity: 1;
  transform: scale(1);
}

/* =========================================================
   DOOR
   ========================================================= */

#akeru-game-v31 .akeru-door {
  position: absolute;
  inset: 0;
  display: block;
  transform-origin: left center;
  transform-style: preserve-3d;
  transform: rotateY(0deg);
  transition:
    transform .62s cubic-bezier(.23,.72,.23,1);
  pointer-events: none;
  will-change: transform;
}

#akeru-game-v31[data-state="opening"] .akeru-door,
#akeru-game-v31[data-state="revealed"] .akeru-door {
  transform: rotateY(-79deg);
}

#akeru-game-v31[data-state="closing"] .akeru-door {
  transform: rotateY(0deg);
}

#akeru-game-v31 .akeru-door-face {
  position: absolute;
  inset: 0;
  display: block;
  background:
    linear-gradient(
      90deg,
      #b4875d 0%,
      #c99b6b 45%,
      #b77f4d 100%
    );
  border: 10px solid #76583e;
  box-shadow: inset -10px 0 18px rgba(0,0,0,.08);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

#akeru-game-v31 .akeru-door-panel {
  position: absolute;
  left: 14%;
  right: 14%;
  border: 2px solid rgba(91,61,36,.28);
}

#akeru-game-v31 .akeru-door-panel-top {
  top: 12%;
  height: 30%;
}

#akeru-game-v31 .akeru-door-panel-bottom {
  bottom: 12%;
  height: 37%;
}

#akeru-game-v31 .akeru-knob {
  position: absolute;
  width: 17px;
  height: 17px;
  right: 9%;
  top: 50%;
  transform: translateY(-50%);
  border-radius: 50%;
  background: #332a22;
  box-shadow: 0 1px 2px rgba(0,0,0,.35);
}

/* =========================================================
   FIRST VISIT CUE
   ========================================================= */

#akeru-game-v31[data-first-cue="true"][data-state="closed"] .akeru-door {
  animation: akeru-v31-first-cue 1.7s ease-in-out 1;
}

@keyframes akeru-v31-first-cue {
  0%, 55%, 100% { transform: rotateY(0deg); }
  70% { transform: rotateY(-3deg); }
  82% { transform: rotateY(0deg); }
}

/* =========================================================
   META
   ========================================================= */

#akeru-game-v31 .akeru-meta {
  width: min(68vw, 288px);
  flex: 0 0 auto;
  margin-top: clamp(10px, 2vw, 16px);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

#akeru-game-v31 .akeru-progress {
  display: flex;
  align-items: baseline;
  gap: .24em;
  font-size: 13px;
  line-height: 1;
  white-space: nowrap;
  opacity: .62;
  pointer-events: none;
}

#akeru-game-v31 .akeru-progress-count {
  font-size: 15px;
  font-variant-numeric: tabular-nums;
}

#akeru-game-v31 .akeru-sound {
  width: 44px;
  height: 44px;
  flex: 0 0 44px;
  display: grid;
  place-items: center;
  font-size: 17px;
  cursor: pointer;
  opacity: .62;
  touch-action: manipulation;
}

#akeru-game-v31 .akeru-sound:hover,
#akeru-game-v31 .akeru-sound:focus-visible {
  opacity: 1;
}

/* =========================================================
   HINT
   常時高さを確保してlayout shiftを出さない
   ========================================================= */

#akeru-game-v31 .akeru-hint {
  flex: 0 0 auto;
  height: 17px;
  min-height: 17px;
  margin: 4px 0 0;
  padding: 0;
  font-size: 12px;
  line-height: 17px;
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .18s ease;
}

#akeru-game-v31[data-hint-visible="true"] .akeru-hint {
  opacity: .6;
  visibility: visible;
}

/* =========================================================
   ACCESSIBILITY
   ========================================================= */

#akeru-game-v31 .akeru-stage:focus-visible,
#akeru-game-v31 .akeru-sound:focus-visible,
#akeru-game-v31 .akeru-focus:focus-visible {
  outline: 2px solid currentColor !important;
  outline-offset: 4px !important;
}

#akeru-game-v31 .akeru-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0,0,0,0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* =========================================================
   RESPONSIVE
   ========================================================= */

@media (max-width: 767px) {
  #akeru-game-v31 .akeru-stage,
  #akeru-game-v31 .akeru-meta,
  #akeru-game-v31 .akeru-tools {
    width: min(68vw, 272px);
  }
}

@media (max-width: 767px) and (max-height: 720px) {
  #akeru-game-v31 .akeru-layout {
    padding-top: 6px;
    padding-bottom: 6px;
  }

  #akeru-game-v31 .akeru-stage,
  #akeru-game-v31 .akeru-meta,
  #akeru-game-v31 .akeru-tools {
    width: min(58vw, 230px);
  }

  #akeru-game-v31 .akeru-meta { margin-top: 8px; }
}

@media (min-width: 768px) {
  #akeru-game-v31 .akeru-stage,
  #akeru-game-v31 .akeru-meta,
  #akeru-game-v31 .akeru-tools {
    width: min(38vw, 288px);
  }
}

@media (min-width: 1100px) {
  #akeru-game-v31 .akeru-stage,
  #akeru-game-v31 .akeru-meta,
  #akeru-game-v31 .akeru-tools {
    width: 288px;
  }
}

/* =========================================================
   FULLSCREEN / IMMERSIVE
   DOM移動・body固定・背景要素操作はしない
   ========================================================= */

#akeru-game-v31:fullscreen,
#akeru-game-v31:-webkit-full-screen {
  width: 100dvw;
  height: var(--akeru-visual-height, 100dvh);
  min-height: var(--akeru-visual-height, 100dvh);
  overflow: clip;
}

#akeru-game-v31:fullscreen .akeru-layout,
#akeru-game-v31:-webkit-full-screen .akeru-layout {
  width: 100%;
  min-height: var(--akeru-visual-height, 100dvh);
  justify-content: center;
  padding:
    max(56px, env(safe-area-inset-top))
    max(18px, env(safe-area-inset-right))
    max(18px, env(safe-area-inset-bottom))
    max(18px, env(safe-area-inset-left));
}

#akeru-game-v31:fullscreen .akeru-tools,
#akeru-game-v31:-webkit-full-screen .akeru-tools {
  position: absolute;
  top: max(12px, env(safe-area-inset-top));
  right: max(12px, env(safe-area-inset-right));
  width: auto;
  margin: 0;
  z-index: 5;
}

#akeru-game-v31:fullscreen .akeru-stage,
#akeru-game-v31:fullscreen .akeru-meta,
#akeru-game-v31:-webkit-full-screen .akeru-stage,
#akeru-game-v31:-webkit-full-screen .akeru-meta {
  width: min(68dvw, 48dvh, 23rem);
}

#akeru-game-v31:fullscreen,
#akeru-game-v31:fullscreen *,
#akeru-game-v31:-webkit-full-screen,
#akeru-game-v31:-webkit-full-screen * {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

@media (orientation: landscape) and (max-height: 520px) {
  #akeru-game-v31:fullscreen .akeru-layout,
  #akeru-game-v31:-webkit-full-screen .akeru-layout {
    padding-left: max(24px, env(safe-area-inset-left));
    padding-right: max(24px, env(safe-area-inset-right));
  }
}

/* =========================================================
   CONTRAST / FORCED COLORS
   ========================================================= */

@media (prefers-contrast: more) {
  #akeru-game-v31 .akeru-progress,
  #akeru-game-v31 .akeru-sound,
  #akeru-game-v31 .akeru-focus {
    opacity: .86;
  }

  #akeru-game-v31 .akeru-door-face {
    border-width: 12px;
  }
}

@media (forced-colors: active) {
  #akeru-game-v31 .akeru-door-face,
  #akeru-game-v31 .akeru-knob,
  #akeru-game-v31 .akeru-door-panel {
    forced-color-adjust: auto;
  }

  #akeru-game-v31 .akeru-door-face {
    background: Canvas;
    border-color: CanvasText;
  }

  #akeru-game-v31 .akeru-door-panel {
    border-color: CanvasText;
  }

  #akeru-game-v31 .akeru-knob {
    background: CanvasText;
  }
}

/* =========================================================
   REDUCED MOTION
   ========================================================= */

@media (prefers-reduced-motion: reduce) {
  #akeru-game-v31 .akeru-door,
  #akeru-game-v31 .akeru-presence,
  #akeru-game-v31 .akeru-scene-visual,
  #akeru-game-v31 .akeru-hint {
    transition-duration: .01ms;
  }

  #akeru-game-v31[data-first-cue="true"] .akeru-door {
    animation: none;
  }
}
</style>

<script>
(function () {
  "use strict";

  /* =========================================================
     DOM / FAIL-SAFE INIT
     ========================================================= */

  const game = document.getElementById("akeru-game-v31");
  const stage = document.getElementById("akeru-stage-v31");
  const presence = document.getElementById("akeru-presence-v31");
  const scene = document.getElementById("akeru-scene-v31");
  const sceneVisual = document.getElementById("akeru-scene-visual-v31");
  const progressCount = document.getElementById("akeru-progress-count-v31");
  const hint = document.getElementById("akeru-hint-v31");
  const soundButton = document.getElementById("akeru-sound-v31");
  const focusButton = document.getElementById("akeru-focus-v31");
  const status = document.getElementById("akeru-status-v31");

  if (!game) return;
  if (!stage) return;
  if (!presence) return;
  if (!scene) return;
  if (!sceneVisual) return;
  if (!progressCount) return;
  if (!status) return;

  if (game.dataset.initialized === "true") return;
  game.dataset.initialized = "true";

  /* =========================================================
     STATE
     ========================================================= */

  const GAME_STATES = {
    CLOSED: "closed",
    OPENING: "opening",
    REVEALED: "revealed",
    CLOSING: "closing"
  };

  const TIMING = {
    presenceStart: 85,
    revealStart: 330,
    opening: 620,
    closing: 500,
    hintVisible: 1800
  };

  const scenes = [
    { id: "cat", category: "animal", visual: "&#x1f408;", label: "猫がいます", sound: { presence: [520,.20,.009,"sine",-.18,.02,.004,1200], reveal: [440,.42,.014,"sine",.12,.02,.003,1500] } },
    { id: "bird", category: "animal", visual: "&#x1f426;", label: "鳥がいます", sound: { presence: [710,.16,.008,"sine",.28,.04,.003,2200], reveal: [659,.30,.012,"triangle",.36,.03,.002,2500] } },
    { id: "fish", category: "animal", visual: "&#x1f41f;", label: "魚がいます", sound: { presence: [420,.28,.008,"sine",-.28,.06,.006,900], reveal: [349,.46,.012,"sine",-.12,.04,.006,1100] } },
    { id: "whale", category: "animal", visual: "&#x1f40b;", label: "大きなクジラがいます", sound: { presence: [140,.70,.008,"sine",-.35,.10,.012,420], reveal: [120,.95,.012,"sine",.18,.08,.014,360] } },
    { id: "sea", category: "water", visual: "&#x1f30a;", label: "海が見えます", sound: { presence: [280,.50,.006,"sine",-.22,.04,.018,700], reveal: [392,.60,.009,"sine",.20,.06,.022,850] } },
    { id: "moon", category: "sky", visual: "&#x1f315;", label: "月が見えます", sound: { presence: [240,.64,.006,"sine",-.10,.12,.002,700], reveal: [262,.85,.010,"sine",.06,.12,.001,900] } },
    { id: "stars", category: "sky", visual: "&#x2728;", label: "星が見えます", sound: { presence: [610,.18,.006,"sine",-.36,.08,.001,2600], reveal: [523,.52,.009,"sine",.34,.10,.001,3000] } },
    { id: "rainbow", category: "sky", visual: "&#x1f308;", label: "虹が見えます", sound: { presence: [620,.22,.007,"triangle",-.25,.02,.002,2200], reveal: [554,.44,.010,"sine",.28,.04,.002,2600] } },
    { id: "snow", category: "weather", visual: "&#x2744;", label: "雪が降っています", sound: { presence: [650,.12,.005,"sine",-.34,.10,.006,3200], reveal: [587,.34,.008,"sine",.24,.12,.010,3600] } },
    { id: "train", category: "transport", visual: "&#x1f683;", label: "電車が通ります", sound: { presence: [150,.34,.008,"triangle",-.44,.02,.018,520], reveal: [330,.26,.011,"triangle",.42,.08,.015,900] } },
    { id: "balloon", category: "object", visual: "&#x1f388;", label: "風船があります", sound: { presence: [550,.24,.006,"sine",-.06,.06,.001,1800], reveal: [494,.52,.009,"sine",.16,.08,.001,2100] } },
    { id: "flower", category: "object", visual: "&#x1f33b;", label: "大きな花があります", sound: { presence: [490,.28,.007,"sine",-.22,.04,.002,1400], reveal: [440,.50,.010,"sine",.22,.06,.002,1700] } },
    { id: "egg", category: "object", visual: "&#x1f95a;", label: "卵があります", sound: { presence: [290,.34,.006,"sine",-.04,.12,.001,1000], reveal: [540,.32,.009,"sine",.08,.14,.001,1500] } },
    { id: "another-door", category: "place", visual: "&#x1f6aa;", label: "向こうにも戸があります", sound: { presence: [185,.18,.007,"triangle",-.12,.04,.010,620], reveal: [285,.52,.010,"triangle",.12,.08,.008,780] } }
  ];

  const state = {
    phase: GAME_STATES.CLOSED,
    currentScene: null,
    previousSceneId: null,
    previousCategory: null,
    muted: false,
    visible: !document.hidden,
    immersive: false,
    inputMode: "unknown"
  };

  const transientTimers = new Set();
  let audioContext = null;
  let viewportTimer = null;

  /* =========================================================
     TIMER MANAGEMENT
     ========================================================= */

  function scheduleTransient(callback, delay) {
    const id = window.setTimeout(function () {
      transientTimers.delete(id);
      callback();
    }, delay);
    transientTimers.add(id);
    return id;
  }

  function clearTransientTimers() {
    transientTimers.forEach(function (id) {
      window.clearTimeout(id);
    });
    transientTimers.clear();
  }

  /* =========================================================
     STORAGE
     ========================================================= */

  const STORAGE_KEY = "tranquil-akeru-save";

  let saveData = {
    opens: 0,
    discovered: [],
    hintShown: false,
    muted: false,
    hasPlayed: false
  };

  function normalizeSaveData() {
    const validIds = new Set(
      scenes.map(function (item) {
        return item.id;
      })
    );

    const unique = [];

    if (!Array.isArray(saveData.discovered)) {
      saveData.discovered = [];
    }

    saveData.discovered.forEach(function (id) {
      if (!validIds.has(id)) return;
      if (unique.includes(id)) return;
      unique.push(id);
    });

    saveData.discovered = unique;

    if (!Number.isFinite(saveData.opens)) saveData.opens = 0;
    if (saveData.opens < 0) saveData.opens = 0;
    saveData.opens = Math.floor(saveData.opens);
    saveData.hintShown = Boolean(saveData.hintShown);
    saveData.muted = Boolean(saveData.muted);
    saveData.hasPlayed = Boolean(saveData.hasPlayed);

    if (saveData.opens > 0) saveData.hasPlayed = true;
    if (saveData.discovered.length > 0) saveData.hasPlayed = true;
  }

  function loadSave() {
    try {
      const raw = localStorage.getItem(STORAGE_KEY);
      if (!raw) {
        normalizeSaveData();
        return;
      }

      const saved = JSON.parse(raw);

      if (typeof saved.opens === "number") saveData.opens = saved.opens;
      if (Array.isArray(saved.discovered)) saveData.discovered = saved.discovered;
      if (typeof saved.hintShown === "boolean") saveData.hintShown = saved.hintShown;
      if (typeof saved.muted === "boolean") saveData.muted = saved.muted;
      if (typeof saved.hasPlayed === "boolean") saveData.hasPlayed = saved.hasPlayed;
    } catch (error) {
      saveData = {
        opens: 0,
        discovered: [],
        hintShown: false,
        muted: false,
        hasPlayed: false
      };
    }

    normalizeSaveData();
  }

  function saveGame() {
    try {
      localStorage.setItem(STORAGE_KEY, JSON.stringify(saveData));
    } catch (error) {
      /* 保存不可でもコア操作を継続 */
    }
  }

  /* =========================================================
     PHASE / RANDOM
     ========================================================= */

  function setPhase(nextPhase) {
    state.phase = nextPhase;
    game.setAttribute("data-state", nextPhase);
  }

  function randomItem(items) {
    if (!items.length) return null;
    const index = Math.floor(Math.random() * items.length);
    return items[index];
  }

  function getNextScene() {
    let candidates = scenes.filter(function (item) {
      return item.id !== state.previousSceneId;
    });

    const differentCategory = candidates.filter(function (item) {
      return item.category !== state.previousCategory;
    });

    if (differentCategory.length > 0) {
      candidates = differentCategory;
    }

    const undiscovered = candidates.filter(function (item) {
      return !saveData.discovered.includes(item.id);
    });

    if (undiscovered.length > 0) {
      if (Math.random() < .25) {
        return randomItem(undiscovered);
      }
    }

    return randomItem(candidates);
  }

  /* =========================================================
     PROGRESS / HINT
     ========================================================= */

  function updateProgress() {
    progressCount.textContent = saveData.discovered.length;
  }

  function setHintVisible(visible) {
    game.setAttribute("data-hint-visible", visible ? "true" : "false");
    if (!hint) return;
    hint.setAttribute("aria-hidden", visible ? "false" : "true");
  }

  function registerDiscovery(selectedScene) {
    saveData.opens += 1;
    saveData.hasPlayed = true;

    if (!saveData.discovered.includes(selectedScene.id)) {
      saveData.discovered.push(selectedScene.id);
    }

    normalizeSaveData();
    saveGame();
    updateProgress();
    checkHint();
  }

  function checkHint() {
    if (!hint) return;
    if (saveData.hintShown) return;
    if (saveData.opens < 4) return;
    if (saveData.discovered.length >= scenes.length) return;

    saveData.hintShown = true;
    saveGame();
    setHintVisible(true);

    scheduleTransient(function () {
      setHintVisible(false);
    }, TIMING.hintVisible);
  }

  /* =========================================================
     AUDIO / SPATIAL CHARACTER
     ========================================================= */

  function getAudioContext() {
    if (audioContext) return audioContext;

    const AudioContextClass = window.AudioContext || window.webkitAudioContext;
    if (!AudioContextClass) return null;

    try {
      audioContext = new AudioContextClass();
    } catch (error) {
      return null;
    }

    return audioContext;
  }

  function resumeAudioContext() {
    const context = getAudioContext();
    if (!context) return null;

    if (context.state === "suspended") {
      try {
        const resumed = context.resume();
        if (resumed) {
          if (typeof resumed.catch === "function") {
            resumed.catch(function () {});
          }
        }
      } catch (error) {
        /* 音声失敗でもゲーム継続 */
      }
    }

    return context;
  }

  function suspendAudioForLifecycle() {
    if (!audioContext) return;
    if (audioContext.state !== "running") return;
    if (typeof audioContext.suspend !== "function") return;

    try {
      const suspended = audioContext.suspend();
      if (suspended) {
        if (typeof suspended.catch === "function") {
          suspended.catch(function () {});
        }
      }
    } catch (error) {
      /* 無視 */
    }
  }

  function connectPan(context, sourceNode, panValue) {
    if (typeof context.createStereoPanner !== "function") return sourceNode;

    const panner = context.createStereoPanner();
    const safePan = Math.max(-1, Math.min(1, panValue || 0));
    panner.pan.value = safePan;
    sourceNode.connect(panner);
    return panner;
  }

  function createSpatialNoise(context, duration, volume, lowpass, pan, delay) {
    if (!context) return;

    const frameCount = Math.max(1, Math.floor(context.sampleRate * duration));
    const buffer = context.createBuffer(1, frameCount, context.sampleRate);
    const data = buffer.getChannelData(0);

    for (let i = 0; i < frameCount; i += 1) {
      data[i] = Math.random() * 2 - 1;
    }

    const source = context.createBufferSource();
    const filter = context.createBiquadFilter();
    const gain = context.createGain();
    const startAt = context.currentTime + (delay || 0);

    source.buffer = buffer;
    filter.type = "lowpass";
    filter.frequency.value = lowpass || 1800;

    gain.gain.setValueAtTime(Math.max(.0001, volume), startAt);
    gain.gain.exponentialRampToValueAtTime(.0001, startAt + duration);

    source.connect(filter);
    filter.connect(gain);

    const output = connectPan(context, gain, pan || 0);
    output.connect(context.destination);
    source.start(startAt);
  }

  function createSpatialTone(config) {
    if (state.muted) return;
    if (!config) return;

    const context = resumeAudioContext();
    if (!context) return;

    const frequency = config[0];
    const duration = config[1];
    const volume = config[2];
    const type = config[3] || "sine";
    const pan = config[4] || 0;
    const delay = config[5] || 0;
    const noiseAmount = config[6] || 0;
    const lowpass = config[7] || 1800;
    const startAt = context.currentTime + delay;

    const oscillator = context.createOscillator();
    const gain = context.createGain();

    oscillator.type = type;
    oscillator.frequency.setValueAtTime(frequency, startAt);

    gain.gain.setValueAtTime(.0001, context.currentTime);
    gain.gain.setValueAtTime(Math.max(.0001, volume), startAt);
    gain.gain.exponentialRampToValueAtTime(.0001, startAt + duration);

    oscillator.connect(gain);
    const output = connectPan(context, gain, pan);
    output.connect(context.destination);

    oscillator.start(startAt);
    oscillator.stop(startAt + duration + .02);

    if (noiseAmount > 0) {
      createSpatialNoise(context, duration, noiseAmount, lowpass, pan * .7, delay);
    }
  }

  function playLatchSound() {
    createSpatialTone([185,.055,.024,"triangle",-.03,0,.002,800]);
    scheduleTransient(function () {
      createSpatialTone([135,.055,.017,"triangle",.02,0,.0015,700]);
    }, 38);
  }

  function playDoorOpeningSound() {
    if (state.muted) return;
    const context = resumeAudioContext();
    if (!context) return;
    createSpatialNoise(context,.34,.009,720,-.16,.01);
    createSpatialTone([92,.28,.007,"triangle",-.10,.02,.003,600]);
  }

  function playDoorClosingSound() {
    if (state.muted) return;
    const context = resumeAudioContext();
    if (!context) return;
    createSpatialNoise(context,.22,.010,650,.08,.01);
    scheduleTransient(function () {
      createSpatialTone([108,.08,.025,"triangle",.02,0,.002,720]);
    }, 330);
  }

  function playPresenceSound(selectedScene) {
    createSpatialTone(selectedScene.sound.presence);
  }

  function playSceneSound(selectedScene) {
    createSpatialTone(selectedScene.sound.reveal);
  }

  /* =========================================================
     SCENE / OPEN / CLOSE
     ========================================================= */

  function prepareScene(selectedScene) {
    presence.textContent = selectedScene.visual;
    sceneVisual.textContent = "";
    game.setAttribute("data-presence-visible", "false");
    game.setAttribute("data-scene-visible", "false");
    scene.setAttribute("aria-hidden", "true");
  }

  function showPresence(selectedScene) {
    if (state.phase !== GAME_STATES.OPENING) return;
    if (state.currentScene !== selectedScene) return;

    game.setAttribute("data-presence-visible", "true");
    playPresenceSound(selectedScene);
  }

  function showSceneVisual(selectedScene) {
    if (state.phase !== GAME_STATES.OPENING) return;
    if (state.currentScene !== selectedScene) return;

    sceneVisual.textContent = selectedScene.visual;
    scene.setAttribute("aria-hidden", "false");
    game.setAttribute("data-scene-visible", "true");
    playSceneSound(selectedScene);
  }

  function startOpening() {
    if (state.phase !== GAME_STATES.CLOSED) return;

    const selectedScene = getNextScene();
    if (!selectedScene) return;

    state.currentScene = selectedScene;
    prepareScene(selectedScene);
    game.setAttribute("data-first-cue", "false");
    setPhase(GAME_STATES.OPENING);
    stage.setAttribute("aria-label", "戸を開いています");

    playLatchSound();
    playDoorOpeningSound();

    scheduleTransient(function () {
      showPresence(selectedScene);
    }, TIMING.presenceStart);

    scheduleTransient(function () {
      showSceneVisual(selectedScene);
    }, TIMING.revealStart);

    scheduleTransient(function () {
      finishOpening(selectedScene);
    }, TIMING.opening);
  }

  function finishOpening(selectedScene) {
    if (state.phase !== GAME_STATES.OPENING) return;
    if (state.currentScene !== selectedScene) return;

    setPhase(GAME_STATES.REVEALED);
    stage.setAttribute("aria-expanded", "true");
    stage.setAttribute("aria-label", "戸を閉じる");
    status.textContent = selectedScene.label;
    registerDiscovery(selectedScene);
  }

  function startClosing() {
    if (state.phase !== GAME_STATES.REVEALED) return;

    setPhase(GAME_STATES.CLOSING);
    stage.setAttribute("aria-label", "戸を閉じています");
    playDoorClosingSound();
    game.setAttribute("data-scene-visible", "false");

    scheduleTransient(function () {
      game.setAttribute("data-presence-visible", "false");
    }, 120);

    scheduleTransient(finishClosing, TIMING.closing);
  }

  function finishClosing() {
    if (state.currentScene) {
      state.previousSceneId = state.currentScene.id;
      state.previousCategory = state.currentScene.category;
    }

    state.currentScene = null;
    presence.textContent = "";
    sceneVisual.textContent = "";
    game.setAttribute("data-presence-visible", "false");
    game.setAttribute("data-scene-visible", "false");
    scene.setAttribute("aria-hidden", "true");
    setPhase(GAME_STATES.CLOSED);
    stage.setAttribute("aria-expanded", "false");
    stage.setAttribute("aria-label", "戸を開ける");
    status.textContent = "戸が閉じました";
  }

  function resetTransientView() {
    if (state.phase === GAME_STATES.CLOSED) return;

    if (state.currentScene) {
      state.previousSceneId = state.currentScene.id;
      state.previousCategory = state.currentScene.category;
    }

    state.currentScene = null;
    presence.textContent = "";
    sceneVisual.textContent = "";
    game.setAttribute("data-presence-visible", "false");
    game.setAttribute("data-scene-visible", "false");
    scene.setAttribute("aria-hidden", "true");
    setPhase(GAME_STATES.CLOSED);
    stage.setAttribute("aria-expanded", "false");
    stage.setAttribute("aria-label", "戸を開ける");
  }

  function handleStageTap() {
    if (state.phase === GAME_STATES.CLOSED) {
      startOpening();
      return;
    }

    if (state.phase === GAME_STATES.REVEALED) {
      startClosing();
    }
  }

  /* =========================================================
     SOUND SETTING
     ========================================================= */

  function updateSoundUI() {
    if (!soundButton) return;

    if (soundButton.disabled) {
      soundButton.textContent = "×";
      soundButton.setAttribute("aria-pressed", "false");
      return;
    }

    if (state.muted) {
      soundButton.textContent = "×";
      soundButton.setAttribute("aria-pressed", "false");
      soundButton.setAttribute("aria-label", "音を出す");
      return;
    }

    soundButton.textContent = "♪";
    soundButton.setAttribute("aria-pressed", "true");
    soundButton.setAttribute("aria-label", "音を消す");
  }

  function toggleSound() {
    if (!soundButton) return;
    if (soundButton.disabled) return;

    state.muted = !state.muted;
    saveData.muted = state.muted;
    saveGame();
    updateSoundUI();

    if (!state.muted) {
      createSpatialTone([440,.10,.010,"sine",0,0,.001,1800]);
    }
  }

  /* =========================================================
     INPUT MODE
     ========================================================= */

  function setInputMode(mode) {
    state.inputMode = mode || "unknown";
    game.setAttribute("data-input-mode", state.inputMode);
  }

  function recordPointerMode(event) {
    if (!event) {
      setInputMode("pointer");
      return;
    }

    if (event.pointerType === "touch") {
      setInputMode("touch");
      return;
    }

    if (event.pointerType === "pen") {
      setInputMode("pen");
      return;
    }

    if (event.pointerType === "mouse") {
      setInputMode("mouse");
      return;
    }

    setInputMode("pointer");
  }

  /* =========================================================
     VIEWPORT / FULLSCREEN
     Fullscreen APIのみ。ページDOMは一切組み替えない。
     ========================================================= */

  function getFullscreenElement() {
    if (document.fullscreenElement) return document.fullscreenElement;
    if (document.webkitFullscreenElement) return document.webkitFullscreenElement;
    return null;
  }

  function syncVisualViewport() {
    try {
      let height = window.innerHeight;
      if (window.visualViewport) {
        if (window.visualViewport.height) {
          height = window.visualViewport.height;
        }
      }

      if (!Number.isFinite(height)) return;
      if (height <= 0) return;
      game.style.setProperty("--akeru-visual-height", height + "px");
    } catch (error) {
      /* viewport同期失敗でもコア操作を継続 */
    }
  }

  function scheduleViewportSync() {
    if (viewportTimer !== null) {
      window.clearTimeout(viewportTimer);
    }

    viewportTimer = window.setTimeout(function () {
      viewportTimer = null;
      syncVisualViewport();
    }, 80);
  }

  function syncFullscreenUI() {
    const current = getFullscreenElement();
    state.immersive = current === game;
    game.setAttribute("data-immersive", state.immersive ? "true" : "false");

    if (!focusButton) return;

    focusButton.textContent = state.immersive ? "&#x2199;" : "⛶";
    focusButton.setAttribute("aria-pressed", state.immersive ? "true" : "false");
    focusButton.setAttribute("aria-label", state.immersive ? "全画面表示を終了" : "全画面で表示");
    focusButton.title = state.immersive ? "全画面表示を終了" : "全画面表示";
  }

  function enterFullscreen() {
    if (!focusButton) return;
    if (state.immersive) return;

    syncVisualViewport();

    try {
      let request = null;

      if (typeof game.requestFullscreen === "function") {
        request = game.requestFullscreen();
      } else if (typeof game.webkitRequestFullscreen === "function") {
        request = game.webkitRequestFullscreen();
      } else {
        focusButton.disabled = true;
        focusButton.setAttribute("aria-disabled", "true");
        focusButton.setAttribute("aria-label", "このブラウザでは全画面表示を利用できません");
        return;
      }

      if (request) {
        if (typeof request.catch === "function") {
          request.catch(function () {
            syncFullscreenUI();
          });
        }
      }
    } catch (error) {
      syncFullscreenUI();
    }
  }

  function exitFullscreen() {
    if (!state.immersive) return;

    try {
      let request = null;

      if (typeof document.exitFullscreen === "function") {
        request = document.exitFullscreen();
      } else if (typeof document.webkitExitFullscreen === "function") {
        request = document.webkitExitFullscreen();
      }

      if (request) {
        if (typeof request.catch === "function") {
          request.catch(function () {});
        }
      }
    } catch (error) {
      /* browser側Escapeでも復帰可能 */
    }
  }

  function toggleFullscreen() {
    if (state.immersive) {
      exitFullscreen();
      return;
    }

    enterFullscreen();
  }

  function trapFullscreenTab(event) {
    if (!state.immersive) return;
    if (event.key !== "Tab") return;

    const selector = 'button:not(:disabled),a[href],[tabindex]:not([tabindex="-1"])';
    const nodes = Array.from(game.querySelectorAll(selector));
    const items = nodes.filter(function (element) {
      return element.getClientRects().length > 0;
    });

    if (!items.length) return;

    const first = items[0];
    const last = items[items.length - 1];

    if (event.shiftKey) {
      if (document.activeElement === first) {
        event.preventDefault();
        last.focus();
      }
      return;
    }

    if (document.activeElement === last) {
      event.preventDefault();
      first.focus();
    }
  }

  /* =========================================================
     LIFECYCLE
     ========================================================= */

  function syncAfterLifecycleResume() {
    state.visible = !document.hidden;
    clearTransientTimers();
    resetTransientView();
    syncVisualViewport();
    syncFullscreenUI();
  }

  function prepareForLifecyclePause() {
    clearTransientTimers();
    resetTransientView();
    suspendAudioForLifecycle();
  }

  /* =========================================================
     EVENTS
     ========================================================= */

  stage.addEventListener("click", handleStageTap);
  stage.addEventListener("pointerdown", recordPointerMode, { passive: true });

  if (soundButton) {
    soundButton.addEventListener("click", toggleSound);
    soundButton.addEventListener("pointerdown", recordPointerMode, { passive: true });
  }

  if (focusButton) {
    focusButton.addEventListener("click", toggleFullscreen);
    focusButton.addEventListener("pointerdown", recordPointerMode, { passive: true });
  }

  document.addEventListener("keydown", function (event) {
    setInputMode("keyboard");

    if (state.immersive) {
      if (event.key === "Escape") {
        /* Fullscreen API側にもEscape処理を任せる。preventDefaultしない */
        return;
      }

      trapFullscreenTab(event);
    }
  });

  document.addEventListener("fullscreenchange", syncFullscreenUI);
  document.addEventListener("webkitfullscreenchange", syncFullscreenUI);

  window.addEventListener("resize", scheduleViewportSync, { passive: true });

  if (window.visualViewport) {
    window.visualViewport.addEventListener("resize", scheduleViewportSync, { passive: true });
    window.visualViewport.addEventListener("scroll", scheduleViewportSync, { passive: true });
  }

  if (screen.orientation) {
    if (typeof screen.orientation.addEventListener === "function") {
      screen.orientation.addEventListener("change", scheduleViewportSync);
    }
  }

  document.addEventListener("visibilitychange", function () {
    state.visible = !document.hidden;

    if (!state.visible) {
      prepareForLifecyclePause();
      return;
    }

    syncAfterLifecycleResume();
  });

  window.addEventListener("pageshow", function () {
    syncAfterLifecycleResume();
  });

  window.addEventListener("pagehide", function () {
    prepareForLifecyclePause();

    if (viewportTimer !== null) {
      window.clearTimeout(viewportTimer);
      viewportTimer = null;
    }
  });

  /* =========================================================
     INIT
     ========================================================= */

  loadSave();
  state.muted = saveData.muted;

  if (soundButton) {
    const supportsAudio = Boolean(window.AudioContext || window.webkitAudioContext);

    if (!supportsAudio) {
      soundButton.disabled = true;
      soundButton.setAttribute("aria-disabled", "true");
      soundButton.setAttribute("aria-label", "このブラウザでは音を利用できません");
      soundButton.title = "このブラウザでは音を利用できません";
    }
  }

  if (focusButton) {
    const supportsFullscreen = Boolean(
      typeof game.requestFullscreen === "function" ||
      typeof game.webkitRequestFullscreen === "function"
    );

    if (!supportsFullscreen) {
      focusButton.disabled = true;
      focusButton.setAttribute("aria-disabled", "true");
      focusButton.setAttribute("aria-label", "このブラウザでは全画面表示を利用できません");
      focusButton.title = "このブラウザでは全画面表示を利用できません";
    }
  }

  updateSoundUI();
  updateProgress();
  setHintVisible(false);
  syncVisualViewport();
  syncFullscreenUI();

  setPhase(GAME_STATES.CLOSED);
  game.setAttribute("data-presence-visible", "false");
  game.setAttribute("data-scene-visible", "false");
  stage.setAttribute("aria-expanded", "false");
  scene.setAttribute("aria-hidden", "true");

  saveGame();

  if (!saveData.hasPlayed) {
    scheduleTransient(function () {
      if (state.phase !== GAME_STATES.CLOSED) return;
      if (!state.visible) return;
      game.setAttribute("data-first-cue", "true");
    }, 800);
  }
})();
</script>
]]></content:encoded>
					
					<wfw:commentRss>https://tranquilguides.com/akeru/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2722</post-id>	</item>
		<item>
		<title>夜の待合室 mini</title>
		<link>https://tranquilguides.com/midnight-waiting-room-mini/</link>
					<comments>https://tranquilguides.com/midnight-waiting-room-mini/#respond</comments>
		
		<dc:creator><![CDATA[案内人のアシカ]]></dc:creator>
		<pubDate>Sun, 19 Jul 2026 13:58:19 +0000</pubDate>
				<category><![CDATA[生存ログ]]></category>
		<category><![CDATA[休息]]></category>
		<category><![CDATA[体験]]></category>
		<category><![CDATA[夜]]></category>
		<category><![CDATA[部屋]]></category>
		<guid isPermaLink="false">https://tranquilguides.com/?p=1575</guid>

					<description><![CDATA[<p><img src="https://i0.wp.com/tranquilguides.com/wp-content/uploads/2026/07/img_4438.jpg?fit=1024%2C576&ssl=1" class="webfeedsFeaturedVisual" /></p>今日を終える前に、ほんの1分だけ。画面の光を落とし、ゆっくり呼吸しながら、何もしない時間を過ごせる小さな夜の待合室です。]]></description>
										<content:encoded><![CDATA[<p><img src="https://i0.wp.com/tranquilguides.com/wp-content/uploads/2026/07/img_4438.jpg?fit=1024%2C576&ssl=1" class="webfeedsFeaturedVisual" /></p>
<!-- ここから「夜の待合室 mini」 -->
<style>
.ywm-room{--night:#0b1020;--deep:#070b16;--paper:#f3efe4;--mist:#aeb7ca;--gold:#d7b777;box-sizing:border-box;min-height:min(760px,88svh);width:min(1180px,calc(100vw - 32px));margin:2rem 50%;padding:34px clamp(24px,5vw,76px) 30px;position:relative;transform:translateX(-50%);overflow:hidden;display:grid;grid-template-rows:auto 1fr auto;color:var(--paper);background:radial-gradient(circle at 78% 28%,rgba(96,119,167,.15),transparent 29%),linear-gradient(145deg,var(--night),var(--deep) 76%);border-radius:3px;font-family:"Yu Mincho","YuMincho","Hiragino Mincho ProN",serif;isolation:isolate}.ywm-room *{box-sizing:border-box}.ywm-room [hidden]{display:none!important}.ywm-stars{position:absolute;inset:0;opacity:.38;background-image:radial-gradient(circle at 18% 22%,#fff 0 1px,transparent 1.5px),radial-gradient(circle at 64% 12%,#fff 0 1px,transparent 1.5px),radial-gradient(circle at 92% 63%,#fff 0 1px,transparent 1.5px),radial-gradient(circle at 39% 78%,#fff 0 1px,transparent 1.5px),radial-gradient(circle at 71% 84%,#fff 0 1px,transparent 1.5px)}.ywm-header,.ywm-footer{position:relative;z-index:2;display:flex;justify-content:space-between;align-items:center}.ywm-wordmark{margin:0;color:var(--paper);letter-spacing:.14em;font-size:15px}.ywm-wordmark em{color:var(--gold);font:normal 10px "Helvetica Neue",Arial,sans-serif;letter-spacing:.18em;margin-left:6px}.ywm-open,.ywm-footer span,.ywm-eyebrow{margin:0;color:var(--mist);font:9px "Helvetica Neue",Arial,sans-serif;letter-spacing:.27em}.ywm-welcome{position:relative;z-index:2;width:min(720px,100%);align-self:center;margin:6vh 0 6vh clamp(0px,7vw,110px)}.ywm-eyebrow{color:var(--gold);margin-bottom:38px}.ywm-room h2{margin:0;padding:0;color:var(--paper);background:none;border:0;font-size:clamp(42px,6.2vw,84px);font-weight:400;line-height:1.42;letter-spacing:.045em}.ywm-room h2:before,.ywm-room h2:after{display:none}.ywm-intro{margin:35px 0 44px;color:var(--mist);font-size:clamp(14px,1.5vw,17px);line-height:2.15;letter-spacing:.09em}.ywm-button{width:min(280px,100%);margin:0;padding:18px 4px;border:0;border-bottom:1px solid rgba(215,183,119,.65);border-radius:0;background:transparent;box-shadow:none;color:var(--paper);display:flex;align-items:center;justify-content:space-between;cursor:pointer;font-size:14px;letter-spacing:.13em;transition:.3s}.ywm-button:hover,.ywm-button:focus-visible{color:var(--gold);border-color:var(--gold);background:transparent;padding-left:8px;outline:none}.ywm-arrow{font:18px "Helvetica Neue",Arial,sans-serif}.ywm-moon{position:absolute;z-index:1;top:17%;right:clamp(-75px,3vw,55px);width:clamp(190px,29vw,430px);aspect-ratio:1;border-radius:50%;background:#e6dec9;box-shadow:0 0 90px rgba(210,202,181,.13);opacity:.88;transition:transform 4s ease,box-shadow 2s ease}.ywm-moon span{position:absolute;inset:10% 0 0 29%;border-radius:50%;background:#0a0f1d}.ywm-room.is-resting .ywm-moon{transform:scale(1.035);box-shadow:0 0 140px rgba(210,202,181,.21)}.ywm-rest,.ywm-complete{min-height:286px;display:flex;flex-direction:column;justify-content:center}.ywm-breath{color:var(--gold);font-size:15px;letter-spacing:.28em;animation:ywm-breathe 8s ease-in-out infinite}.ywm-timer{margin:20px 0;color:var(--paper);font:200 clamp(76px,12vw,150px)/1 "Helvetica Neue",Arial,sans-serif;letter-spacing:-.04em;font-variant-numeric:tabular-nums}.ywm-note{color:var(--mist);font-size:13px;letter-spacing:.1em}.ywm-complete h2{font-size:clamp(40px,5.8vw,72px)}.ywm-footer{color:#858da0;font-size:10px;letter-spacing:.13em}.ywm-footer p{margin:0}@keyframes ywm-breathe{0%,100%{opacity:.42;letter-spacing:.28em}50%{opacity:1;letter-spacing:.42em}}@media(max-width:640px){.ywm-room{min-height:74svh;padding:26px 22px 24px}.ywm-open,.ywm-footer span{display:none}.ywm-welcome{margin:5vh 0}.ywm-eyebrow{margin-bottom:26px}.ywm-room h2{font-size:clamp(38px,12vw,58px);line-height:1.5}.ywm-moon{top:12%;right:-92px;opacity:.55}.ywm-intro{margin:28px 0 34px}.ywm-footer{justify-content:flex-start}}@media(prefers-reduced-motion:reduce){.ywm-room *{animation-duration:.01ms!important;transition-duration:.01ms!important}}
</style>

<section class="ywm-room" data-ywm-room aria-label="夜の待合室 mini">
  <div class="ywm-stars" aria-hidden="true"></div><div class="ywm-moon" aria-hidden="true"><span></span></div>
  <header class="ywm-header"><p class="ywm-wordmark">夜の待合室 <em>mini</em></p><p class="ywm-open">OPEN AFTER DARK</p></header>
  <div class="ywm-welcome" aria-live="polite">
    <p class="ywm-eyebrow">A SMALL PAUSE FOR TONIGHT</p>
    <div data-ywm-before><h2>ここでは、<br>急がなくて大丈夫。</h2><p class="ywm-intro">今日を終える前に、ほんの少しだけ。<br>画面の光を落として、ゆっくり息をしましょう。</p></div>
    <div class="ywm-rest" data-ywm-rest hidden><p class="ywm-breath">吸って　 · 　吐いて</p><p class="ywm-timer" data-ywm-timer aria-label="残り60秒">01:00</p><p class="ywm-note">何もしない時間も、ちゃんと時間です。</p></div>
    <div class="ywm-complete" data-ywm-complete hidden><h2>おつかれさまでした。</h2><p class="ywm-intro">今夜が、少しだけ静かになりますように。</p></div>
    <button class="ywm-button" type="button" data-ywm-button><span data-ywm-button-label>1分だけ、ひと休み</span><span class="ywm-arrow" aria-hidden="true">→</span></button>
  </div>
  <footer class="ywm-footer"><p>今夜も、ここは静かに開いています。</p><span>01 — 03 MINUTES</span></footer>
</section>

<script>
(function(){"use strict";var duration=60;function initialize(room){var before=room.querySelector("[data-ywm-before]");var rest=room.querySelector("[data-ywm-rest]");var complete=room.querySelector("[data-ywm-complete]");var timer=room.querySelector("[data-ywm-timer]");var button=room.querySelector("[data-ywm-button]");var label=room.querySelector("[data-ywm-button-label]");var intervalId=null;function show(element){element.hidden=false}function hide(element){element.hidden=true}function update(remaining){var minutes=String(Math.floor(remaining/60)).padStart(2,"0");var seconds=String(remaining%60).padStart(2,"0");timer.textContent=minutes+":"+seconds;timer.setAttribute("aria-label","残り"+remaining+"秒")}function finish(){window.clearInterval(intervalId);room.classList.remove("is-resting");hide(rest);show(complete);show(button);label.textContent="もう一度、ひと休み"}function start(){var remaining=duration;window.clearInterval(intervalId);hide(before);hide(complete);hide(button);show(rest);room.classList.add("is-resting");update(remaining);intervalId=window.setInterval(function(){remaining-=1;update(remaining);if(remaining<=0){finish()}},1000)}button.addEventListener("click",start)}function boot(){document.querySelectorAll("[data-ywm-room]").forEach(initialize)}if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",boot)}else{boot()}})();
</script>
<!-- ここまで「夜の待合室 mini」 -->




<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://tranquilguides.com/midnight-waiting-room-mini/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1575</post-id>	</item>
		<item>
		<title>夜の茶室</title>
		<link>https://tranquilguides.com/night-room/</link>
					<comments>https://tranquilguides.com/night-room/#respond</comments>
		
		<dc:creator><![CDATA[案内人のアシカ]]></dc:creator>
		<pubDate>Wed, 01 Jul 2026 08:46:54 +0000</pubDate>
				<category><![CDATA[生存ログ]]></category>
		<category><![CDATA[体験]]></category>
		<category><![CDATA[夜]]></category>
		<category><![CDATA[居場所]]></category>
		<category><![CDATA[部屋]]></category>
		<guid isPermaLink="false">https://tranquilguides.com/?p=1229</guid>

					<description><![CDATA[<p><img src="https://i0.wp.com/tranquilguides.com/wp-content/uploads/2026/07/IMG_20260702_001350.jpg?fit=1024%2C683&ssl=1" class="webfeedsFeaturedVisual" /></p>日没から夜明けまで開く、小さな夜の部屋。何かを話さなくても、ただ席につくだけで、その夜を誰かと静かに共有できます。]]></description>
										<content:encoded><![CDATA[<p><img src="https://i0.wp.com/tranquilguides.com/wp-content/uploads/2026/07/IMG_20260702_001350.jpg?fit=1024%2C683&ssl=1" class="webfeedsFeaturedVisual" /></p>	  
<div id="NightRoom" class="night-room">


<div id="NightClosed" class="night-closed">
	
  <p class="small">
    太陽のいない「あいだ」にのみ開きます。
  </p>

  <div class="night-wait">
    <p class="night-wait-label">本日の日没</p>
    <p class="night-wait-time">17:05</p>

    <p id="NightCountdownLabel" class="night-wait-label">開室まで</p>
<p
  id="NightCountdown"
  class="night-countdown"
  data-sunset-ts="1793433957">
  00:27:57</p>
  </div>
</div>
	
	
</div>

  <script>
console.log('NightRoom version: 2026-07-09-01');
	
    document.addEventListener('DOMContentLoaded', function () {
		
      const ajaxUrl = 'https://tranquilguides.com/wp-admin/admin-ajax.php';

      const openEl = document.getElementById('NightOpen');
      const closedEl = document.getElementById('NightClosed');
      const cupShelfEl = document.getElementById('CupShelf');
const btn = document.getElementById('TakeSeatBtn');
const btnText = document.getElementById('TakeSeatText');
const msg = document.getElementById('SeatMessage');

function isNightTime() {
  return false;
}

function todayKey() {
  const parts = new Intl.DateTimeFormat('ja-JP', {
    timeZone: 'Asia/Tokyo',
    year: 'numeric',
    month: '2-digit',
    day: '2-digit'
  }).formatToParts(new Date());

  const y = parts.find(p => p.type === 'year').value;
  const m = parts.find(p => p.type === 'month').value;
  const d = parts.find(p => p.type === 'day').value;

  return `${y}-${m}-${d}`;
}

function seededNumber(str) {
  let hash = 0;

  for (let i = 0; i < str.length; i++) {
    hash = (hash * 31 + str.charCodeAt(i)) >>> 0;
  }

  return hash / 4294967295;
}

function seededRange(str, min, max) {
  return min + seededNumber(str) * (max - min);
}
		
      function hasTakenSeatToday() {
        return localStorage.getItem('night_room_seat_' + todayKey()) === '1';
      }

      function markTakenSeatToday() {
        localStorage.setItem('night_room_seat_' + todayKey(), '1');
      }

      function loadCupCount() {
        fetch(ajaxUrl + '?action=night_room_get_cup_count')
          .then(res => res.json())
          .then(data => {
            renderCups(data.count || 0);
          });
      }
		
let currentCupCount = 0;

function syncCupCount() {
  fetch(ajaxUrl + '?action=night_room_get_cup_count' + '&ts=' + Date.now())
    .then(res => res.json())
    .then(data => {
      const newCount = data.count || 0;

      if (newCount > currentCupCount) {
        for (let i = currentCupCount + 1; i <= newCount; i++) {
          addCup(i);
        }
      }

      currentCupCount = newCount;
    });
}

function takeSeat() {
  if (hasTakenSeatToday()) {
    btn.disabled = true;
    btn.classList.add('is-leaving');
    btnText.textContent = '素敵な夜を';
    btn.classList.add('is-seated');
    msg.textContent = '';
    return;
  }

btn.disabled = true;

setTimeout(() => {
  btn.classList.add('is-leaving');
}, 700);

fetch(ajaxUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: 'action=night_room_take_seat'
  })
    .then(res => res.json())
    .then(data => {
      markTakenSeatToday();
      msg.textContent = '';

      // 1. 「席につく」を消す
      btnText.classList.add('is-fading-out');

      setTimeout(() => {
        // 2. 何も書いていないボタン
        btnText.textContent = '';
        btnText.classList.remove('is-fading-out');

        setTimeout(() => {
          // 3. 「お席を整えています」を表示
          btnText.classList.add('is-fading-out');

          setTimeout(() => {
            btnText.textContent = 'お席を整えています...';
            btnText.classList.remove('is-fading-out');
            btn.classList.add('is-preparing');

            setTimeout(() => {
              // 4. 「お席を整えています」を消す
              btnText.classList.add('is-fading-out');

              setTimeout(() => {
                // 5. 空白のまま、カップを出す
                btnText.textContent = '';
                btn.classList.remove('is-preparing');
                btnText.classList.remove('is-fading-out');

                addCup(data.count);
				currentCupCount = data.count || currentCupCount;

                setTimeout(() => {
                  // 6. 最終文言を表示
                  btnText.classList.add('is-fading-out');

                  setTimeout(() => {
                    btnText.textContent = '素敵な夜を';
                    btnText.classList.remove('is-fading-out');
                    btn.classList.add('is-seated');
                  }, 1200);

                }, 2200);

              }, 1200);

            }, 2200);

          }, 1200);

        }, 800);

      }, 1200);
    });
}

function renderCups(count) {
  cupShelfEl.innerHTML = '';

  if (!count || count < 1) {
    const empty = document.createElement('div');
    empty.className = 'cup-empty';
    empty.textContent = 'お席は、まだ空いています。';
    cupShelfEl.appendChild(empty);
    return;
  }

  for (let i = 0; i < count; i++) {
    const cup = createCupElement(i, false);
    cupShelfEl.appendChild(cup);
  }
	
currentCupCount = count || 0;
	
}

function addCup(count) {
  const empty = cupShelfEl.querySelector('.cup-empty');

  if (empty) {
    empty.classList.add('is-fading-out');

    setTimeout(() => {
      empty.remove();
      showNewCup(count);
    }, 1000);

    return;
  }

  showNewCup(count);
}

function showNewCup(count) {
  const cup = createCupElement(count - 1, true);

  cupShelfEl.appendChild(cup);

  requestAnimationFrame(() => {
    cup.classList.add('is-visible');
  });
}

function createCupElement(index, animate) {
  const cup = document.createElement('span');

  cup.innerHTML = `
    <svg class="cup-icon" viewBox="0 0 64 48" aria-hidden="true">
      <ellipse cx="32" cy="12" rx="18" ry="6"></ellipse>
      <path d="M14 12 C16 34, 22 40, 32 40 C42 40, 48 34, 50 12"></path>
      <ellipse cx="32" cy="40" rx="9" ry="3"></ellipse>
    </svg>
  `;

const basePositions = [
  [-28, -6, -3],
  [-10,  4,  2],
  [ 18, -3, -1],
  [ 34,  7,  3],
  [ -2, -10,  1],
  [ 12,  12, -4],
  [-35,  9,  2],
  [ 30, -11, -2],
  [ -18, 15,  4],
  [ 0,   18, -1],
  [ 40,  15,  2],
  [-42, -14, -2],
];

const base = basePositions[index % basePositions.length];
const seed = todayKey() + '-' + index;

const changeType = seededNumber(seed + '-change');

let x = base[0];
let y = base[1];
let r = base[2];

if (changeType < 0.3) {
  // 30%：ほぼ同じ
  x += seededRange(seed + '-x-small', -3, 3);
  y += seededRange(seed + '-y-small', -3, 3);
  r += seededRange(seed + '-r-small', -1, 1);
} else if (changeType < 0.7) {
  // 40%：少し変わる
  x += seededRange(seed + '-x-mid', -12, 12);
  y += seededRange(seed + '-y-mid', -10, 10);
  r += seededRange(seed + '-r-mid', -3, 3);
} else {
  // 30%：大きめに変わる
  x += seededRange(seed + '-x-large', -28, 28);
  y += seededRange(seed + '-y-large', -18, 18);
  r += seededRange(seed + '-r-large', -6, 6);
}

cup.style.transform = `translate(${x}px, ${y}px) rotate(${r}deg)`;
	
  cup.setAttribute('aria-hidden', 'true');

  if (animate) {
    cup.classList.add('cup-new');
  }

  return cup;
}
	
function startNightCountdown() {
	
  const countdownEl = document.getElementById('NightCountdown');
  const labelEl = document.getElementById('NightCountdownLabel');
  const roomEl = document.getElementById('NightRoom');

  if (!countdownEl || !labelEl) return;

  const sunset = Number(countdownEl.dataset.sunsetTs) * 1000;
	
  let reloadStarted = false;

  function pad(num) {
    return String(num).padStart(2, '0');
  }

  function updateCountdown() {
    const now = Date.now();
    const diff = sunset - now;

if (diff <= 0) {
  countdownEl.textContent = '00:00:00';

  if (!reloadStarted) {
    reloadStarted = true;
    window.location.href = window.location.pathname + '?nr=' + Date.now();
  }

  return;
}
	  
	/**
    if (!hasTakenSeatToday()) {
      btn.disabled = false;
      btn.addEventListener('click', takeSeat);
    } else {
      btn.disabled = true;
      btnText.textContent = '素敵な夜を';
      btn.classList.add('is-leaving');
      btn.classList.add('is-seated');
      msg.textContent = '';
    }
  }

  return;
}
	 */
	  
    const totalSeconds = Math.floor(diff / 1000);
    const hours = Math.floor(totalSeconds / 3600);
    const minutes = Math.floor((totalSeconds % 3600) / 60);
    const seconds = totalSeconds % 60;

    countdownEl.textContent =
      pad(hours) + ':' + pad(minutes) + ':' + pad(seconds);

    if (totalSeconds <= 10) {
      labelEl.textContent = 'こんばんは';
    } else if (totalSeconds <= 60) {
      labelEl.textContent = 'まもなく開室します';
    } else {
      labelEl.textContent = '開室まで';
    }
  }

  updateCountdown();
  setInterval(updateCountdown, 1000);
}
	
function startMorningMessage() {
  const greeting = document.getElementById('Greeting');

  if (!greeting) return;
  if (!openEl) return;

  const sunrise = new Date(openEl.dataset.sunrise).getTime();
  
  const morningUntil = new Date(openEl.dataset.morningUntil).getTime();

  function updateMorningMessage() {
    const now = Date.now();

if (now >= sunrise) {
    greeting.classList.add('is-morning');
    greeting.textContent = 'おはようございます';

    if (!btn.classList.contains('is-hidden')) {
        btn.classList.add('is-hidden');
        cupShelfEl.classList.add('is-hidden');
        msg.textContent = '';

        setTimeout(() => {
            btn.hidden = true;
            cupShelfEl.hidden = true;
        }, 800);
    }

if (now >= morningUntil) {
    window.location.href =
        window.location.pathname + '?nr=' + Date.now();
    return;
}

    return;
}

    if (now >= sunrise - 3600 * 1000) {
      greeting.textContent = 'まもなく夜が明けます';
    } else {
      greeting.textContent = 'こんばんは';
    }
  }

  updateMorningMessage();
  setInterval(updateMorningMessage, 1000);
}

function startMorningGrace() {
  if (!openEl) return;

  const morningUntil = new Date(openEl.dataset.morningUntil).getTime();

  function updateMorningGrace() {

if (Date.now() >= morningUntil) {
  window.location.href = window.location.pathname + '?nr=' + Date.now();
  return;
}
  }

  updateMorningGrace();
  setInterval(updateMorningGrace, 1000);
}
		
if (isNightTime()) {
  if (openEl) {
    openEl.hidden = false;
  }

  if (closedEl) {
    closedEl.hidden = true;
  }
	
loadCupCount();
setInterval(syncCupCount, 20000);
startMorningMessage();

  if (hasTakenSeatToday()) {
    btn.disabled = true;
    btnText.textContent = '素敵な夜を';
    btn.classList.add('is-leaving');
    btn.classList.add('is-seated');
    msg.textContent = '';
  }

  btn.addEventListener('click', takeSeat);

} else if (false) {
  if (openEl) {
    openEl.hidden = false;
  }

  if (closedEl) {
    closedEl.hidden = true;
  }

const morningGreeting = document.getElementById('Greeting');
morningGreeting.classList.add('is-morning');
morningGreeting.textContent = 'おはようございます';

btn.classList.add('is-hidden');
cupShelfEl.classList.add('is-hidden');
msg.textContent = '';

setTimeout(() => {
  btn.hidden = true;
  cupShelfEl.hidden = true;
}, 800);

startMorningGrace();

} else {
  if (openEl) {
    openEl.hidden = true;
  }

  if (closedEl) {
    closedEl.hidden = false;
    startNightCountdown();
  }
}
    });
  </script>
			  
			  
  



<style data-wp-block-html="css">
.night-room {
      min-height: 70vh;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      text-align: center;
      padding: 48px 20px;
      background: #f7f6f3;
      color: #111;
      filter: grayscale(1);
      font-family: inherit;
      transition: opacity 1.2s ease, filter 1.2s ease;
    }

    .night-room h1 {
      font-size: 1.8rem;
      font-weight: 400;
      letter-spacing: 0.08em;
      margin-bottom: 32px;
    }

    .small {
      font-size: 0.8rem;
      opacity: 0.55;
      margin-bottom: 40px;
    }

    .status {
      font-size: 1rem;
      margin-bottom: 32px;
    }

#TakeSeatBtn {
  appearance: none !important;
  -webkit-appearance: none !important;

  position: relative;
  min-width: 260px !important;
  height: 44px !important;
  padding: 0 24px !important;

  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  box-sizing: border-box !important;

  border: none !important;
  background: transparent !important;
  background-color: transparent !important;
  box-shadow: none !important;

  color: inherit !important;
  border-radius: 999px !important;
  font-size: 0.95rem !important;
  line-height: 1 !important;
  white-space: nowrap !important;
  text-decoration: none !important;

  cursor: pointer;
}

#TakeSeatBtn::before {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px solid currentColor;
  border-radius: 999px;
  opacity: 1;
  transition: opacity 3.8s ease;
  pointer-events: none;
}

#TakeSeatBtn.is-leaving::before,
#TakeSeatBtn.is-seated::before {
  opacity: 0;
}

#TakeSeatBtn:disabled {
  cursor: default;
}

.btn-text {
  position: relative;
  z-index: 1;
  opacity: 1;
  transition: opacity 1.2s ease;
}

.btn-text.is-fading-out {
  opacity: 0;
}

#TakeSeatBtn.is-preparing .btn-text {
  opacity: 0.55;
}

#TakeSeatBtn.is-seated .btn-text {
  opacity: 0.62;
}
			  
.message {
      margin-top: 24px;
      font-size: 0.85rem;
      opacity: 0.65;
    }
	
.greeting {
  margin-bottom: 36px;
  font-size: 0.85rem;
  opacity: 0;
  pointer-events: none;
  animation: Greeting 8s ease-in-out forwards;
}

@keyframes Greeting {

  /* 最初は見えない */
  0% {
    opacity: 0;
  }

  /* ゆっくり現れる・5秒地点 */
  62.5% {
    opacity: 0.6;
  }

  /* 少し滞在・7秒地点 */
  87.5% {
    opacity: 0.6;
  }

  /* ゆっくり消える */
  100% {
    opacity: 0;
  }

}
			  
.cup-shelf {
  min-height: 72px;
  margin: 28px 0 34px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.cup-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 14px;
  max-width: 260px;
  font-size: 1.45rem;
  line-height: 1.8;
  opacity: 0.72;
}

.cup-empty {
  font-size: 0.8rem;
  opacity: 0.45;
  transition: opacity 1s ease;
}

.cup-row span {
  display: inline-flex;
  width: 28px;
  height: 22px;
  align-items: center;
  justify-content: center;
}

.cup-icon {
  width: 28px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.72;
}
			  	  
.cup-new {
  opacity: 0;
  transition: opacity 2s ease;
}

.cup-new.is-visible {
  opacity: 1;
}	
			  
.cup-empty.is-fading-out {
  opacity: 0;
}

.night-wait {
  text-align: center;
  margin-top: 2.5rem;
  letter-spacing: 0.08em;
}

.night-wait-label {
  font-size: 0.75rem;
  opacity: 0.55;
  margin: 1.5rem 0 0.4rem;
}

.night-wait-time,
.night-countdown {
  font-size: clamp(1.8rem, 6vw, 3.8rem);
  line-height: 1;
  margin: 0;
  font-weight: 300;
}

.night-room.is-opening {
  opacity: 0;
  filter: blur(6px);
}

.cup-shelf,
#TakeSeatBtn {
    transition: opacity .8s ease;
}

.cup-shelf.is-hidden,
#TakeSeatBtn.is-hidden{
    opacity:0;
    pointer-events:none;
}

.greeting.is-morning {
  animation: none !important;
  opacity: 0.62 !important;
}

</style>



<style data-wp-block-html="css">
.cl-copyright{
  margin:80px auto 24px;
  text-align:center;
  font-size:13px;
  letter-spacing:.08em;
  opacity:.55;
}

.cl-copyright a{
  color:inherit;
  text-decoration:none;
  transition:opacity .2s ease;
}

.cl-copyright a:hover{
  opacity:1;
}
</style>

<div class="cl-copyright">
  <a href="https://tranquilguides.com/">
Tranquilvæj
  </a>
</div>



<style data-wp-block-html="css">
/* 診断ページ専用：外側UI削除 */
#header,
.l-header,
.l-fixHeader,
#fix_header,
#sp_menu,
.p-spMenu,
.p-spMenu__inner,
.p-spMenu__body,
.p-spMenu__overlay,
#breadcrumb,
.c-postTitle,
.p-articleMetas,
.p-postTax,
.p-articleFoot,
.l-articleBottom,
.l-contentBottom,
.w-beforeFooter,
.l-footerWidgets,
.l-footer {
  display: none !important;
}

/* 余白リセット */
:root {
  --swl-headerH: 0px !important;
  --swl-fix_headerH: 0px !important;
  --swl-offset_y: 0px !important;
}

html,
body,
#body_wrap,
#content,
.l-content,
.l-mainContent,
.l-mainContent__inner,
#main_content {
  margin-top: 0 !important;
  padding-top: 0 !important;
}

/* 夜の茶室：表示領域全体をモノクロ */
html,
body,
#body_wrap,
#content,
.l-content,
.l-mainContent,
.l-mainContent__inner,
#main_content,
.post_content {
  filter: grayscale(1) !important;
}

.p-fixBtnWrap {
  border-radius: 999px !important;
  overflow: hidden !important;
  border: 0 !important;

  background:
    radial-gradient(
      circle at 50% 50%,
      rgba(255,255,255,.00) 0%,
      rgba(255,255,255,.02) 58%,
      rgba(255,255,255,.12) 100%
    ) !important;

  backdrop-filter: blur(.3px) saturate(135%) contrast(108%) brightness(106%);
  -webkit-backdrop-filter: blur(.3px) saturate(135%) contrast(108%) brightness(106%);

  box-shadow:
    inset 2px 2px 2px rgba(255,255,255,.55),
    inset 0 0 14px rgba(255,255,255,.28),
    0 3px 8px rgba(0,0,0,.03) !important;
}

.p-fixBtnWrap::before {
  content: "";
  position: absolute;
  inset: 1px;
  border-radius: 999px;
  pointer-events: none;
  background:
    linear-gradient(
      145deg,
      rgba(255,255,255,.75) 0%,
      rgba(255,255,255,.28) 18%,
      rgba(255,255,255,0) 42%
    );
  mix-blend-mode: screen;
  opacity: .65;
}

.p-fixBtnWrap:hover {
  background: #2f4f4f !important;
  box-shadow: none !important;
}

.c-fixBtn__icon {
  color: #2f2f2f !important;
  text-shadow: none !important;
  -webkit-text-stroke: 0 !important;
}

.p-fixBtnWrap:hover .c-fixBtn__icon {
  color: #fff !important;
}

.p-fixBtnWrap a,
.p-fixBtnWrap button,
.p-fixBtnWrap [class*="fixBtn"],
.p-fixBtnWrap [class*="icon"] {
  border: 0 !important;
  outline: 0 !important;
  box-shadow: none !important;
  background: transparent !important;
}

.p-fixBtnWrap [class*="fixBtn"],
.p-fixBtnWrap [class*="icon"],
.p-fixBtnWrap a,
.p-fixBtnWrap button {
  border: 0 !important;
  outline: 0 !important;
  box-shadow: none !important;
  background: transparent !important;
}

.p-fixBtnWrap {
  width: 52px !important;
  height: 52px !important;
  position: fixed !important;
  display: block !important;

  transition:
    width .22s ease,
    background-color .18s ease,
    box-shadow .18s ease !important;
}

.p-fixBtnWrap .c-fixBtn__icon {
  position: absolute !important;
  top: 50% !important;
  left: 50% !important;
  transform: translate(-50%, -50%) !important;
  z-index: 2;
}

.p-fixBtnWrap::after {
  content: "Page top";
  position: absolute;
  top: 50%;
  left: 54px;
  transform: translateY(-55%);

  z-index: 2;
  opacity: 0;
  max-width: 0;
  overflow: hidden;
  white-space: nowrap;

  height: 24px;
  line-height: 24px;

  font-size: 14px;
  letter-spacing: .03em;
  color: #fff;

  transition:
    opacity .15s ease,
    max-width .22s ease;
}

.p-fixBtnWrap:hover {
  width: 132px !important;
}

.p-fixBtnWrap:hover .c-fixBtn__icon {
  left: 28px !important;
}

.p-fixBtnWrap:hover::after {
  opacity: 1;
  max-width: 80px;
}

#breadcrumb {
  display: none !important;
}
</style>

<script data-wp-block-html="js">
document.addEventListener("DOMContentLoaded", () => {
  [
    "#header",
    ".l-header",
    ".l-fixHeader",
    "#fix_header",
    "#sp_menu",
    ".p-spMenu",
    "#breadcrumb",
    ".c-postTitle",
    ".p-articleMetas",
    ".p-postTax",
    ".p-articleFoot",
    ".l-articleBottom",
    ".l-contentBottom",
    ".w-beforeFooter",
    ".l-footerWidgets",
    ".l-footer"
  ].forEach(selector => {
    document.querySelectorAll(selector).forEach(el => el.remove());
  });
});
</script>
]]></content:encoded>
					
					<wfw:commentRss>https://tranquilguides.com/night-room/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1229</post-id>	</item>
		<item>
		<title>Guide Map</title>
		<link>https://tranquilguides.com/map/</link>
					<comments>https://tranquilguides.com/map/#respond</comments>
		
		<dc:creator><![CDATA[案内人のアシカ]]></dc:creator>
		<pubDate>Wed, 01 Jul 2026 03:03:54 +0000</pubDate>
				<category><![CDATA[生存ログ]]></category>
		<category><![CDATA[体験]]></category>
		<category><![CDATA[案内]]></category>
		<category><![CDATA[道具]]></category>
		<guid isPermaLink="false">https://tranquilguides.com/?p=1353</guid>

					<description><![CDATA[探すためではなく、引っかかるための地図。気になる言葉や景色に触れると、Tranquilvæjに点在するひとつの世界へつながります。]]></description>
										<content:encoded><![CDATA[
<!-- =========================================================
Tranquilvæj / Tranquil Guides
TRANQUIL GUIDE MAP
Independent Block v1.3

WordPress / SWELL

v1.3:
- Fixed semantic map nodes
- Dynamic article nodes from WordPress REST API
- Excerpt-first article presentation
- Title reveal on hover / focus
- Article shuffle
- Predefined article slots by ENTRY
- DRIFT can refresh article selection
- Subtle pointer response
- Trackpad / wheel zoom around pointer (Google Maps-like)
- One-finger pan on touch devices
- Two-finger pinch zoom around pinch midpoint
- Dynamic article collision avoidance
- Universal Spatial Map
- Mobile: same Map UI as desktop
- INDEX mode
- READ / REST / SEE / CHECK filters
- SVG relationships
- Drag to move
- prefers-reduced-motion
- WebGL / Canvas unused

IMPORTANT:
This JavaScript intentionally avoids the double-ampersand operator
to reduce the risk of WordPress/SWELL entity conversion.
========================================================= -->

<div class="tgm" data-tgm>
  <div class="tgm__shell">

    <header class="tgm__intro">


      <div class="tgm__intro-row">
        <div>

          <p class="tgm__lead">探すためではなく、引っかかるための索引。</p>
        </div>

        <button
          class="tgm__mode"
          type="button"
          data-tgm-mode
          aria-pressed="false"
        >
          INDEX
        </button>
      </div>

      <p class="tgm__description">
        読む場所、休む場所、眺める場所、確かめる場所。
        気になる断片に近づいてください。
      </p>
    </header>


    <div class="tgm__controls" aria-label="Guide Map filters">
      <div class="tgm__filters" role="group" aria-label="Filter map">
        <button class="tgm__filter is-active" type="button" data-tgm-filter="all">ALL</button>
        <button class="tgm__filter" type="button" data-tgm-filter="read">READ</button>
        <button class="tgm__filter" type="button" data-tgm-filter="rest">REST</button>
        <button class="tgm__filter" type="button" data-tgm-filter="see">SEE</button>
        <button class="tgm__filter" type="button" data-tgm-filter="check">CHECK</button>
      </div>

      <button class="tgm__drift" type="button" data-tgm-drift>
        DRIFT
      </button>
    </div>


    <div class="tgm__map-wrap" data-tgm-map-wrap>
      <div
        class="tgm__viewport"
        data-tgm-viewport
        tabindex="0"
        aria-label="Tranquil Guide Map. Drag to move."
      >
        <div class="tgm__canvas" data-tgm-canvas>

          <svg
            class="tgm__connections"
            data-tgm-svg
            viewBox="0 0 1600 1050"
            preserveAspectRatio="none"
            aria-hidden="true"
          ></svg>

          <div class="tgm__nodes" data-tgm-nodes></div>

        </div>
      </div>

      <div class="tgm__map-hint" aria-hidden="true">
        DRAG / PINCH TO MOVE
      </div>
    </div>


    <div class="tgm__index" data-tgm-index hidden></div>

  </div>
</div>


<style>
/* =========================================================
   ROOT
========================================================= */

.tgm,
.tgm *,
.tgm *::before,
.tgm *::after{
  box-sizing:border-box;
}

.tgm{
  --tgm-ink:#10141c;
  --tgm-muted:rgba(16,20,28,.56);
  --tgm-faint:rgba(16,20,28,.33);
  --tgm-line:rgba(16,20,28,.09);
  --tgm-line-active:rgba(16,20,28,.30);
  --tgm-panel:rgba(255,255,255,.94);
  --tgm-focus:rgba(16,20,28,.86);

  width:100%;
  color:var(--tgm-ink);

  font-family:
    ui-sans-serif,
    system-ui,
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Roboto,
    Helvetica,
    Arial,
    sans-serif;
}

.tgm button,
.tgm a{
  font:inherit;
}

.tgm button{
  color:inherit;
}


/* =========================================================
   SHELL
========================================================= */

.tgm__shell{
  width:min(100%,1600px);
  margin-inline:auto;

  padding:
    clamp(76px,8vw,126px)
    clamp(18px,4vw,56px);
}


/* =========================================================
   INTRO
========================================================= */

.tgm__intro{
  max-width:1080px;
  margin:0 auto clamp(34px,5vw,68px);
}

.tgm__eyebrow{
  margin:0 0 14px;

  color:var(--tgm-faint);

  font-size:11px;
  line-height:1;
  font-weight:600;
  letter-spacing:.16em;
  text-transform:uppercase;
}

.tgm__intro-row{
  display:flex;
  align-items:flex-end;
  justify-content:space-between;
  gap:24px;
}

.tgm__title{
  margin:0;

  font-size:clamp(34px,5.6vw,78px);
  line-height:.92;
  font-weight:500;
  letter-spacing:-.045em;
}

.tgm__lead{
  margin:16px 0 0;

  color:var(--tgm-muted);

  font-size:clamp(15px,1.6vw,20px);
  line-height:1.7;
}

.tgm__description{
  max-width:620px;
  margin:26px 0 0;

  color:var(--tgm-muted);

  font-size:13px;
  line-height:1.9;
}

.tgm__mode{
  flex:none;

  border:0;
  padding:10px 0;

  background:transparent;

  color:var(--tgm-muted);

  font-size:11px;
  font-weight:600;
  letter-spacing:.14em;

  cursor:pointer;
}


/* =========================================================
   CONTROLS
========================================================= */

.tgm__controls{
  width:min(100%,1080px);
  margin:0 auto 18px;

  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:20px;
}

.tgm__filters{
  display:flex;
  flex-wrap:wrap;
  gap:18px;
}

.tgm__filter,
.tgm__drift{
  border:0;
  padding:8px 0;

  background:transparent;

  color:var(--tgm-faint);

  font-size:10px;
  font-weight:600;
  line-height:1;
  letter-spacing:.14em;

  cursor:pointer;

  transition:
    color .35s ease,
    opacity .35s ease;
}

.tgm__filter:hover,
.tgm__filter:focus-visible,
.tgm__drift:hover,
.tgm__drift:focus-visible,
.tgm__filter.is-active{
  color:var(--tgm-ink);
}

.tgm__filter:focus-visible,
.tgm__drift:focus-visible,
.tgm__mode:focus-visible,
.tgm__node:focus-visible,
.tgm__index-link:focus-visible{
  outline:1px solid var(--tgm-focus);
  outline-offset:5px;
}


/* =========================================================
   MAP
========================================================= */

.tgm__map-wrap{
  position:relative;

  width:min(100%,1180px);
  margin-inline:auto;

  border-top:1px solid var(--tgm-line);
  border-bottom:1px solid var(--tgm-line);

  overflow:hidden;
}

.tgm__viewport{
  position:relative;

  height:clamp(570px,68vw,760px);

  overflow:hidden;
  cursor:grab;
  touch-action:none;
  outline:none;
}

.tgm__viewport.is-dragging{
  cursor:grabbing;
}

.tgm__canvas{
  position:absolute;
  inset:50% auto auto 50%;

  width:1600px;
  height:1050px;

  transform:translate3d(-800px,-525px,0) scale(1);
  transform-origin:0 0;
  will-change:transform;
}

.tgm__connections,
.tgm__nodes{
  position:absolute;
  inset:0;

  width:100%;
  height:100%;
}

.tgm__connections{
  overflow:visible;
  pointer-events:none;
}

.tgm__nodes{
  pointer-events:none;
}

.tgm__map-hint{
  position:absolute;
  right:0;
  bottom:15px;

  color:var(--tgm-faint);

  font-size:9px;
  font-weight:600;
  letter-spacing:.14em;

  pointer-events:none;
}


/* =========================================================
   CONNECTIONS
========================================================= */

.tgm__edge{
  stroke:var(--tgm-line);
  stroke-width:1;
  vector-effect:non-scaling-stroke;

  opacity:.52;

  transition:
    opacity .42s ease,
    stroke .42s ease;
}

.tgm__edge.is-muted{
  opacity:.08;
}

.tgm__edge.is-active{
  stroke:var(--tgm-line-active);
  opacity:1;
}


/* =========================================================
   NODES
========================================================= */

.tgm__node{
  position:absolute;

  transform:
    translate(-50%,-50%)
    translate3d(var(--push-x,0),var(--push-y,0),0);

  border:0;
  padding:0;

  background:transparent;

  color:var(--tgm-ink);
  text-decoration:none;

  pointer-events:auto;
  cursor:pointer;

  transition:
    opacity .42s ease,
    transform .42s cubic-bezier(.2,.7,.2,1);
}

.tgm__node:hover{
  transform:
    translate(-50%,-50%)
    translate3d(var(--push-x,0),var(--push-y,0),0)
    scale(1.025);
}

.tgm__node.is-muted{
  opacity:.11;
}

.tgm__node.is-related{
  opacity:1;
}

.tgm__node.is-active{
  z-index:8;
}

.tgm__node-inner{
  position:relative;

  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:8px;

  min-width:56px;
  min-height:56px;
}

.tgm__node-mark{
  display:block;

  width:8px;
  height:8px;

  border:1px solid currentColor;
  border-radius:50%;

  background:transparent;
  opacity:.72;

  transition:
    width .36s ease,
    height .36s ease,
    opacity .36s ease,
    background .36s ease;
}

.tgm__node:hover .tgm__node-mark,
.tgm__node:focus-visible .tgm__node-mark,
.tgm__node.is-active .tgm__node-mark{
  opacity:1;
}

.tgm__node--current .tgm__node-mark{
  width:12px;
  height:12px;

  border:0;
  border-radius:0;

  background:
    linear-gradient(currentColor,currentColor) center / 12px 1px no-repeat,
    linear-gradient(currentColor,currentColor) center / 1px 12px no-repeat;
}

.tgm__node--entry .tgm__node-mark{
  width:34px;
  height:34px;

  border-width:1px;
}

.tgm__node--theme .tgm__node-mark{
  width:5px;
  height:5px;

  background:currentColor;
  border:0;
}

.tgm__node--series .tgm__node-mark{
  width:20px;
  height:1px;

  border:0;
  border-radius:0;

  background:currentColor;
}

.tgm__node--place .tgm__node-mark{
  width:10px;
  height:10px;
  border-radius:0;
}

.tgm__node--visual .tgm__node-mark{
  width:18px;
  height:12px;
  border-radius:0;
}


/* =========================================================
   LABELS
========================================================= */

.tgm__node-label{
  display:block;

  max-width:200px;

  color:var(--tgm-muted);

  font-size:10px;
  font-weight:600;
  line-height:1.4;
  letter-spacing:.11em;

  text-align:center;
  text-transform:uppercase;
  white-space:nowrap;
}

.tgm__node--entry .tgm__node-label{
  color:var(--tgm-ink);

  font-size:13px;
  letter-spacing:.13em;
}

.tgm__node--current .tgm__node-label{
  font-size:9px;
  letter-spacing:.15em;
}


/* =========================================================
   DYNAMIC ARTICLE
========================================================= */

.tgm__node--article{
  width:220px;
  max-width:220px;
}

.tgm__node--article .tgm__node-inner{
  min-width:120px;
  max-width:230px;

  align-items:flex-start;
  gap:7px;
}

.tgm__node--article .tgm__node-mark{
  width:4px;
  height:4px;

  border:0;
  background:currentColor;
}

.tgm__article-phrase{
  display:block;

  width:220px;
  max-width:220px;

  color:var(--tgm-muted);

  font-size:11px;
  line-height:1.65;
  letter-spacing:.015em;
  text-align:left;
}

.tgm__node--article .tgm__node-label{
  max-width:220px;

  color:var(--tgm-faint);

  font-size:8px;
  line-height:1.4;
  letter-spacing:.10em;
  text-align:left;

  opacity:0;
  transform:translateY(4px);

  transition:
    opacity .3s ease,
    transform .3s ease;
}

.tgm__node--article:hover .tgm__node-label,
.tgm__node--article:focus-visible .tgm__node-label,
.tgm__node--article.is-active .tgm__node-label{
  opacity:1;
  transform:translateY(0);
}


/* =========================================================
   DETAIL
========================================================= */

.tgm__node-detail{
  position:absolute;
  top:calc(100% + 11px);
  left:50%;

  width:max-content;
  max-width:250px;

  transform:translateX(-50%) translateY(4px);

  padding:9px 11px;

  background:var(--tgm-panel);

  color:var(--tgm-ink);

  box-shadow:
    0 14px 38px rgba(16,20,28,.08);

  opacity:0;
  visibility:hidden;
  pointer-events:none;

  transition:
    opacity .28s ease,
    transform .28s ease,
    visibility .28s ease;
}

.tgm__node:hover .tgm__node-detail,
.tgm__node:focus-visible .tgm__node-detail,
.tgm__node.is-active .tgm__node-detail{
  opacity:1;
  visibility:visible;

  transform:translateX(-50%) translateY(0);
}

.tgm__node-detail-title{
  display:block;

  font-size:11px;
  font-weight:500;
  line-height:1.55;
}

.tgm__node-detail-meta{
  display:block;
  margin-top:5px;

  color:var(--tgm-faint);

  font-size:8px;
  font-weight:600;
  letter-spacing:.11em;
  text-transform:uppercase;
}


/* =========================================================
   INDEX
========================================================= */

.tgm__index{
  width:min(100%,1080px);
  margin:0 auto;

  border-top:1px solid var(--tgm-line);
}

.tgm__index-group{
  padding:30px 0;
  border-bottom:1px solid var(--tgm-line);
}

.tgm__index-head{
  display:grid;
  grid-template-columns:48px 1fr auto;
  gap:18px;
  align-items:baseline;
}

.tgm__index-number{
  color:var(--tgm-faint);

  font-size:10px;
  letter-spacing:.12em;
}

.tgm__index-title{
  font-size:clamp(18px,2vw,27px);
  font-weight:500;
  letter-spacing:-.02em;
}

.tgm__index-count{
  color:var(--tgm-faint);

  font-size:9px;
  letter-spacing:.12em;
}

.tgm__index-items{
  margin:20px 0 0 66px;

  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:10px 30px;
}

.tgm__index-link{
  color:var(--tgm-muted);
  text-decoration:none;

  font-size:12px;
  line-height:1.65;

  transition:color .28s ease;
}

.tgm__index-link:hover{
  color:var(--tgm-ink);
}


/* =========================================================
   MODE
========================================================= */

.tgm.is-index .tgm__map-wrap{
  display:none;
}

.tgm.is-index .tgm__index{
  display:block;
}

.tgm.is-index .tgm__mode{
  color:var(--tgm-ink);
}


/* =========================================================
   TOUCH
========================================================= */

@media (hover:none){

  .tgm__node--article .tgm__node-label{
    opacity:0;
    transform:translateY(4px);
  }

  .tgm__node--article:focus-visible .tgm__node-label,
  .tgm__node--article.is-active .tgm__node-label{
    opacity:1;
    transform:none;
  }

}


/* =========================================================
   MOBILE / TABLET
   Same Spatial Map UI
========================================================= */

@media (max-width:767px){

  .tgm__shell{
    width:100%;
    padding:
      46px
      12px
      56px;
  }

  .tgm__intro{
    margin-bottom:24px;
    padding-inline:6px;
  }

  .tgm__intro-row{
    align-items:flex-start;
    gap:14px;
  }

  .tgm__lead{
    margin-top:0;
    font-size:14px;
    line-height:1.65;
  }

  .tgm__description{
    margin-top:15px;
    max-width:290px;
    font-size:11px;
    line-height:1.75;
  }

  .tgm__mode{
    padding-top:2px;
    font-size:9px;
  }

  .tgm__controls{
    margin-bottom:10px;
    padding-inline:6px;
    align-items:center;
    gap:12px;
  }

  .tgm__filters{
    gap:12px;
  }

  .tgm__filter,
  .tgm__drift{
    padding:7px 0;
    font-size:8px;
    letter-spacing:.11em;
  }

  .tgm__map-wrap{
    display:block !important;
    width:100%;
  }

  .tgm__viewport{
    display:block !important;
    height:min(68svh,640px);
    min-height:500px;
    overscroll-behavior:contain;
    touch-action:none;
  }

  .tgm__canvas{
    width:1600px;
    height:1050px;
  }

  .tgm__map-hint{
    right:10px;
    bottom:10px;
    font-size:7px;
    opacity:.75;
  }

  .tgm__node--article{
    width:190px;
    max-width:190px;
  }

  .tgm__node--article .tgm__node-inner{
    min-width:100px;
    max-width:190px;
  }

  .tgm__article-phrase{
    width:190px;
    max-width:190px;
    font-size:10px;
    line-height:1.6;
  }

  .tgm__node--article .tgm__node-label{
    max-width:190px;
    font-size:7px;
  }

  .tgm__node-label{
    font-size:9px;
  }

  .tgm__node--entry .tgm__node-label{
    font-size:11px;
  }

  .tgm__node--entry .tgm__node-mark{
    width:28px;
    height:28px;
  }

  .tgm__node-detail{
    max-width:200px;
    padding:7px 9px;
  }

  .tgm__index{
    width:100%;
    padding-inline:6px;
  }

  .tgm__index-items{
    margin-left:42px;
    grid-template-columns:1fr;
  }

  .tgm.is-index .tgm__map-wrap{
    display:none !important;
  }

  .tgm.is-index .tgm__index{
    display:block !important;
  }

}

@media (min-width:768px) and (max-width:1024px){

  .tgm__viewport{
    height:min(72svh,720px);
    min-height:560px;
    overscroll-behavior:contain;
    touch-action:none;
  }

}

/* =========================================================
   REDUCED MOTION
========================================================= */

@media (prefers-reduced-motion:reduce){

  .tgm *,
  .tgm *::before,
  .tgm *::after{
    scroll-behavior:auto !important;
    animation:none !important;
    transition:none !important;
  }

}
</style>


<script>
(function(){

  "use strict";


  /* =======================================================
     CONFIG
  ======================================================== */

  var CONFIG = {

    endpoint:"/wp-json/wp/v2/posts?_embed=1&per_page=30",

    dynamicPostCount:8,

    excerptLength:64,

    pointerRadius:150,

    pointerStrength:4,

    driftRefreshesArticles:true,

    minScale:0.48,
    maxScale:2.15,
    zoomSensitivity:0.0018,

    desktopInitialScale:1,
    tabletInitialScale:0.78,
    mobileInitialScale:0.60,

    doubleTapZoomFactor:1.28,

    collisionPadding:18,
    collisionIterations:90,
    collisionStep:14,
    collisionBounds:{
      left:120,
      top:90,
      right:1480,
      bottom:970
    }

  };


  /* =======================================================
     FIXED MAP DATA

     entry:
     all / read / rest / see / check

     IMPORTANT:
     These semantic nodes stay fixed.
  ======================================================== */

  var fixedData = [

    {
      id:"current",
      type:"current",
      label:"CURRENT",
      title:"YOU ARE HERE",
      entry:"all",
      x:800,
      y:520,
      connections:["read","rest","see","check"]
    },

    {
      id:"read",
      type:"entry",
      label:"READ",
      title:"読む",
      entry:"read",
      x:790,
      y:790,
      connections:["current","memory","body","quiet-letter"]
    },

    {
      id:"rest",
      type:"entry",
      label:"REST",
      title:"休む",
      entry:"rest",
      x:390,
      y:510,
      connections:["current","night","plants","home"]
    },

    {
      id:"see",
      type:"entry",
      label:"SEE",
      title:"眺める",
      entry:"see",
      x:1210,
      y:510,
      connections:["current","visual-archive","places"]
    },

    {
      id:"check",
      type:"entry",
      label:"CHECK",
      title:"確かめる",
      entry:"check",
      x:815,
      y:245,
      connections:["current","weather","now"]
    },

    {
      id:"memory",
      type:"theme",
      label:"MEMORY",
      title:"記憶",
      entry:"read",
      x:560,
      y:650,
      connections:["read","body","quiet-letter"]
    },

    {
      id:"body",
      type:"theme",
      label:"BODY",
      title:"身体",
      entry:"read",
      x:610,
      y:760,
      connections:["read","rest","memory"]
    },

    {
      id:"night",
      type:"theme",
      label:"NIGHT",
      title:"夜",
      entry:"rest",
      x:470,
      y:390,
      connections:["rest","home"]
    },

    {
      id:"plants",
      type:"theme",
      label:"PLANTS",
      title:"植物",
      entry:"rest",
      x:300,
      y:690,
      connections:["rest","home"]
    },

    {
      id:"home",
      type:"theme",
      label:"HOME",
      title:"家",
      entry:"rest",
      x:430,
      y:770,
      connections:["rest","plants","night"]
    },

    {
      id:"weather",
      type:"theme",
      label:"WEATHER",
      title:"天気",
      entry:"check",
      x:1050,
      y:310,
      connections:["check","see","now"]
    },

    {
      id:"quiet-letter",
      type:"series",
      label:"QUIET LETTER",
      title:"Quiet Letter",
      entry:"read",
      x:945,
      y:700,
      connections:["read","memory"]
    },

    {
      id:"visual-archive",
      type:"visual",
      label:"VISUAL ARCHIVE",
      title:"Visual Archive",
      entry:"see",
      x:1180,
      y:680,
      connections:["see","places"]
    },

    {
      id:"places",
      type:"place",
      label:"PLACES",
      title:"Places",
      entry:"see",
      x:1330,
      y:360,
      connections:["see","check","visual-archive"]
    },

    {
      id:"now",
      type:"series",
      label:"NOW",
      title:"Current Board",
      entry:"check",
      x:1010,
      y:185,
      connections:["check","weather"]
    }

  ];


  /* =======================================================
     ARTICLE SLOTS

     Dynamic posts are inserted only into these positions.
     Structure remains stable while article selection changes.
  ======================================================== */

  var articleSlots = {

    read:[
      {x:430,y:865,connect:"body"},
      {x:760,y:930,connect:"read"},
      {x:1090,y:845,connect:"quiet-letter"}
    ],

    rest:[
      {x:205,y:300,connect:"night"},
      {x:185,y:815,connect:"plants"},
      {x:500,y:930,connect:"home"}
    ],

    see:[
      {x:1350,y:790,connect:"visual-archive"}
    ],

    check:[
      {x:1215,y:160,connect:"weather"}
    ]

  };


  /* =======================================================
     HELPERS
  ======================================================== */

  function q(root,selector){
    return root.querySelector(selector);
  }

  function qa(root,selector){
    return Array.prototype.slice.call(
      root.querySelectorAll(selector)
    );
  }

  function stripHTML(html){

    var div = document.createElement("div");

    div.innerHTML = html || "";

    return (
      div.textContent ||
      div.innerText ||
      ""
    )
    .replace(/\s+/g," ")
    .trim();

  }

  function trimText(text,max){

    if(!text){
      return "";
    }

    if(text.length <= max){
      return text;
    }

    return text.slice(0,max) + "…";

  }

  function shuffle(array){

    var copy = array.slice();

    for(var i = copy.length - 1; i > 0; i--){

      var j = Math.floor(
        Math.random() * (i + 1)
      );

      var temp = copy[i];

      copy[i] = copy[j];
      copy[j] = temp;

    }

    return copy;

  }

  function inferEntry(index){

    var sequence = [
      "read",
      "rest",
      "read",
      "see",
      "rest",
      "check",
      "read",
      "rest"
    ];

    return sequence[
      index % sequence.length
    ];

  }

  function makeDynamicPost(post,index){

    var title = stripHTML(
      post.title ?
      post.title.rendered :
      ""
    );

    var excerpt = stripHTML(
      post.excerpt ?
      post.excerpt.rendered :
      ""
    );

    var phrase = excerpt;

    if(!phrase){
      phrase = title;
    }

    if(!phrase){
      phrase = "名前のない断片";
    }

    var entry = inferEntry(index);

    return {
      id:"post-" + post.id,
      type:"article",
      label:title || "ARTICLE",
      title:title || phrase,
      phrase:trimText(
        phrase,
        CONFIG.excerptLength
      ),
      url:post.link || "#",
      entry:entry,
      postId:post.id,
      x:0,
      y:0,
      connections:[]
    };

  }

  function assignSlots(posts){

    var counters = {
      read:0,
      rest:0,
      see:0,
      check:0
    };

    var result = [];

    posts.forEach(function(item){

      var slots =
        articleSlots[item.entry];

      if(!slots){
        return;
      }

      var count =
        counters[item.entry];

      if(count >= slots.length){
        return;
      }

      var slot = slots[count];

      counters[item.entry] =
        count + 1;

      item.x = slot.x;
      item.y = slot.y;
      item.connections = [
        item.entry,
        slot.connect
      ];

      result.push(item);

    });

    return result;

  }


  /* =======================================================
     ARTICLE COLLISION AVOIDANCE

     Only dynamic article nodes are moved.
     Fixed semantic nodes remain anchored.
  ======================================================== */

  function estimateArticleRect(item){

    var width = 220;

    var phraseLength =
      item.phrase ?
      item.phrase.length :
      0;

    var lines =
      Math.max(
        1,
        Math.ceil(
          phraseLength / 18
        )
      );

    lines =
      Math.min(
        lines,
        4
      );

    var height =
      34 +
      lines * 19;

    return {
      left:item.x - width / 2,
      right:item.x + width / 2,
      top:item.y - height / 2,
      bottom:item.y + height / 2,
      width:width,
      height:height
    };

  }

  function rectsOverlap(a,b,padding){

    if(
      a.right + padding <= b.left
    ){
      return false;
    }

    if(
      b.right + padding <= a.left
    ){
      return false;
    }

    if(
      a.bottom + padding <= b.top
    ){
      return false;
    }

    if(
      b.bottom + padding <= a.top
    ){
      return false;
    }

    return true;

  }

  function clampArticleToBounds(item){

    var bounds =
      CONFIG.collisionBounds;

    item.x =
      Math.max(
        bounds.left,
        Math.min(
          bounds.right,
          item.x
        )
      );

    item.y =
      Math.max(
        bounds.top,
        Math.min(
          bounds.bottom,
          item.y
        )
      );

  }

  function estimateFixedRect(item){

    var width = 90;
    var height = 54;

    if(item.type === "entry"){
      width = 110;
      height = 86;
    }

    if(item.type === "theme"){
      width = 92;
      height = 44;
    }

    if(item.type === "series"){
      width = 130;
      height = 48;
    }

    if(item.type === "visual"){
      width = 150;
      height = 58;
    }

    if(item.type === "place"){
      width = 100;
      height = 54;
    }

    if(item.type === "current"){
      width = 92;
      height = 62;
    }

    return {
      left:item.x - width / 2,
      right:item.x + width / 2,
      top:item.y - height / 2,
      bottom:item.y + height / 2,
      width:width,
      height:height
    };

  }

  function pushArticleAwayFromRect(
    article,
    obstacleRect
  ){

    var articleRect =
      estimateArticleRect(article);

    if(
      !rectsOverlap(
        articleRect,
        obstacleRect,
        CONFIG.collisionPadding
      )
    ){
      return false;
    }

    var obstacleCenterX =
      (
        obstacleRect.left +
        obstacleRect.right
      ) / 2;

    var obstacleCenterY =
      (
        obstacleRect.top +
        obstacleRect.bottom
      ) / 2;

    var dx =
      article.x -
      obstacleCenterX;

    var dy =
      article.y -
      obstacleCenterY;

    if(dx === 0){
      dx = 1;
    }

    if(dy === 0){
      dy = 1;
    }

    var step =
      CONFIG.collisionStep;

    if(
      Math.abs(dx) >=
      Math.abs(dy)
    ){

      article.x +=
        dx > 0 ?
        step :
        -step;

    }else{

      article.y +=
        dy > 0 ?
        step :
        -step;

    }

    clampArticleToBounds(
      article
    );

    return true;

  }

  function separateArticleNodes(items){

    var articles =
      items.filter(function(item){
        return item.type === "article";
      });

    if(!articles.length){
      return;
    }

    var fixedObstacles =
      fixedData.map(function(item){
        return estimateFixedRect(item);
      });

    for(
      var iteration = 0;
      iteration < CONFIG.collisionIterations;
      iteration++
    ){

      var moved =
        false;

      for(
        var f = 0;
        f < articles.length;
        f++
      ){

        for(
          var o = 0;
          o < fixedObstacles.length;
          o++
        ){

          if(
            pushArticleAwayFromRect(
              articles[f],
              fixedObstacles[o]
            )
          ){
            moved = true;
          }

        }

      }

      for(
        var i = 0;
        i < articles.length;
        i++
      ){

        for(
          var j = i + 1;
          j < articles.length;
          j++
        ){

          var a =
            articles[i];

          var b =
            articles[j];

          var rectA =
            estimateArticleRect(a);

          var rectB =
            estimateArticleRect(b);

          if(
            !rectsOverlap(
              rectA,
              rectB,
              CONFIG.collisionPadding
            )
          ){
            continue;
          }

          var dx =
            b.x - a.x;

          var dy =
            b.y - a.y;

          if(dx === 0){
            dx = 1;
          }

          if(dy === 0){
            dy = 1;
          }

          var absX =
            Math.abs(dx);

          var absY =
            Math.abs(dy);

          var step =
            CONFIG.collisionStep;

          if(absX >= absY){

            var sx =
              dx > 0 ?
              1 :
              -1;

            a.x -=
              step * sx;

            b.x +=
              step * sx;

          }else{

            var sy =
              dy > 0 ?
              1 :
              -1;

            a.y -=
              step * sy;

            b.y +=
              step * sy;

          }

          clampArticleToBounds(a);
          clampArticleToBounds(b);

          moved = true;

        }

      }

      if(!moved){
        break;
      }

    }

  }


  /* =======================================================
     INIT
  ======================================================== */

  qa(document,"[data-tgm]").forEach(function(root){

    var viewport =
      q(root,"[data-tgm-viewport]");

    var canvas =
      q(root,"[data-tgm-canvas]");

    var nodesLayer =
      q(root,"[data-tgm-nodes]");

    var svg =
      q(root,"[data-tgm-svg]");

    var index =
      q(root,"[data-tgm-index]");

    var modeButton =
      q(root,"[data-tgm-mode]");

    var driftButton =
      q(root,"[data-tgm-drift]");

    var filterButtons =
      qa(root,"[data-tgm-filter]");

    var sourcePosts = [];

    var dynamicPosts = [];

    var mapData = fixedData.slice();

    var activeNodeId = null;

    var activeFilter = "all";

    var indexMode = false;

    var baseX = -800;
    var baseY = -525;

    var offsetX = 0;
    var offsetY = 0;

    var viewportWidth =
      window.innerWidth;

    var scale =
      CONFIG.desktopInitialScale;

    if(viewportWidth < 768){
      scale =
        CONFIG.mobileInitialScale;
    }else if(viewportWidth <= 1024){
      scale =
        CONFIG.tabletInitialScale;
    }

    var dragging = false;

    var dragStartX = 0;
    var dragStartY = 0;

    var dragOriginX = 0;
    var dragOriginY = 0;

    var reduceMotion = false;

    if(window.matchMedia){

      reduceMotion =
        window.matchMedia(
          "(prefers-reduced-motion: reduce)"
        ).matches;

    }


    /* =====================================================
       DATA ACCESS
    ====================================================== */

    function byId(id){

      var found = null;

      mapData.forEach(function(item){

        if(item.id === id){
          found = item;
        }

      });

      return found;

    }

    function hasConnection(a,b){

      if(!a){
        return false;
      }

      if(!a.connections){
        return false;
      }

      return (
        a.connections.indexOf(b) !== -1
      );

    }

    function uniqueEdges(){

      var used = {};
      var edges = [];

      mapData.forEach(function(item){

        if(!item.connections){
          return;
        }

        item.connections.forEach(function(targetId){

          var keyA =
            item.id + "::" + targetId;

          var keyB =
            targetId + "::" + item.id;

          if(used[keyA]){
            return;
          }

          if(used[keyB]){
            return;
          }

          used[keyA] = true;

          edges.push({
            from:item.id,
            to:targetId
          });

        });

      });

      return edges;

    }


    /* =====================================================
       DYNAMIC POSTS
    ====================================================== */

    function buildDynamicPosts(){

      if(!sourcePosts.length){

        dynamicPosts = [];

        mapData =
          fixedData.slice();

        return;

      }

      var shuffled =
        shuffle(sourcePosts);

      var selected =
        shuffled.slice(
          0,
          CONFIG.dynamicPostCount
        );

      var converted =
        selected.map(function(post,index){

          return makeDynamicPost(
            post,
            index
          );

        });

      dynamicPosts =
        assignSlots(converted);

      separateArticleNodes(
        dynamicPosts
      );

      mapData =
        fixedData
          .slice()
          .concat(dynamicPosts);

    }


    /* =====================================================
       RENDER NODES
    ====================================================== */

    function renderNodes(){

      nodesLayer.innerHTML = "";

      mapData.forEach(function(item){

        var element;

        if(item.url){

          element =
            document.createElement("a");

          element.href =
            item.url;

        }else{

          element =
            document.createElement("button");

          element.type =
            "button";

        }

        element.className =
          "tgm__node tgm__node--" +
          item.type;

        element.dataset.nodeId =
          item.id;

        element.dataset.entry =
          item.entry;

        element.style.left =
          item.x + "px";

        element.style.top =
          item.y + "px";

        var inner =
          document.createElement("span");

        inner.className =
          "tgm__node-inner";

        var mark =
          document.createElement("span");

        mark.className =
          "tgm__node-mark";

        mark.setAttribute(
          "aria-hidden",
          "true"
        );

        inner.appendChild(mark);

        if(item.type === "article"){

          var phrase =
            document.createElement("span");

          phrase.className =
            "tgm__article-phrase";

          phrase.textContent =
            item.phrase;

          inner.appendChild(phrase);

        }

        var label =
          document.createElement("span");

        label.className =
          "tgm__node-label";

        label.textContent =
          item.label;

        inner.appendChild(label);

        if(item.type !== "article"){

          if(item.title){

            var detail =
              document.createElement("span");

            detail.className =
              "tgm__node-detail";

            var detailTitle =
              document.createElement("span");

            detailTitle.className =
              "tgm__node-detail-title";

            detailTitle.textContent =
              item.title;

            detail.appendChild(
              detailTitle
            );

            inner.appendChild(
              detail
            );

          }

        }

        element.appendChild(inner);

        element.setAttribute(
          "aria-label",
          item.title ?
          item.title :
          item.label
        );

        element.addEventListener(
          "mouseenter",
          function(){

            activateNode(
              item.id
            );

          }
        );

        element.addEventListener(
          "focus",
          function(){

            activateNode(
              item.id
            );

          }
        );

        element.addEventListener(
          "mouseleave",
          function(){

            if(activeNodeId === item.id){
              return;
            }

            clearVisualRelations();

          }
        );

        element.addEventListener(
          "blur",
          function(){

            if(activeNodeId === item.id){
              return;
            }

            clearVisualRelations();

          }
        );

        if(!item.url){

          element.addEventListener(
            "click",
            function(){

              toggleNode(
                item.id
              );

            }
          );

        }

        nodesLayer.appendChild(
          element
        );

      });

    }


    /* =====================================================
       EDGES
    ====================================================== */

    function renderEdges(){

      svg.innerHTML = "";

      uniqueEdges().forEach(function(edge){

        var from =
          byId(edge.from);

        var to =
          byId(edge.to);

        if(!from){
          return;
        }

        if(!to){
          return;
        }

        var line =
          document.createElementNS(
            "http://www.w3.org/2000/svg",
            "line"
          );

        line.setAttribute(
          "x1",
          from.x
        );

        line.setAttribute(
          "y1",
          from.y
        );

        line.setAttribute(
          "x2",
          to.x
        );

        line.setAttribute(
          "y2",
          to.y
        );

        line.setAttribute(
          "class",
          "tgm__edge"
        );

        line.dataset.from =
          edge.from;

        line.dataset.to =
          edge.to;

        svg.appendChild(line);

      });

    }


    /* =====================================================
       RELATIONS
    ====================================================== */

    function activateNode(id){

      var active =
        byId(id);

      qa(root,".tgm__node")
      .forEach(function(node){

        var nodeId =
          node.dataset.nodeId;

        var related =
          false;

        if(nodeId === id){

          node.classList.add(
            "is-active"
          );

          node.classList.remove(
            "is-muted"
          );

          return;
        }

        if(active){

          related =
            hasConnection(
              active,
              nodeId
            );

          if(!related){

            var other =
              byId(nodeId);

            if(other){

              related =
                hasConnection(
                  other,
                  id
                );

            }

          }

        }

        node.classList.toggle(
          "is-related",
          related
        );

        node.classList.toggle(
          "is-muted",
          !related
        );

      });

      qa(root,".tgm__edge")
      .forEach(function(edge){

        var connected =
          false;

        if(edge.dataset.from === id){
          connected = true;
        }

        if(edge.dataset.to === id){
          connected = true;
        }

        edge.classList.toggle(
          "is-active",
          connected
        );

        edge.classList.toggle(
          "is-muted",
          !connected
        );

      });

    }

    function clearVisualRelations(){

      qa(root,".tgm__node")
      .forEach(function(node){

        node.classList.remove(
          "is-active"
        );

        node.classList.remove(
          "is-related"
        );

        node.classList.remove(
          "is-muted"
        );

      });

      qa(root,".tgm__edge")
      .forEach(function(edge){

        edge.classList.remove(
          "is-active"
        );

        edge.classList.remove(
          "is-muted"
        );

      });

      applyFilterVisual();

    }

    function toggleNode(id){

      if(activeNodeId === id){

        activeNodeId = null;

        clearVisualRelations();

        return;
      }

      activeNodeId = id;

      activateNode(id);

    }


    /* =====================================================
       FILTER
    ====================================================== */

    function setFilter(filter){

      activeFilter =
        filter;

      filterButtons
      .forEach(function(button){

        button.classList.toggle(
          "is-active",
          button.dataset.tgmFilter === filter
        );

      });

      activeNodeId = null;

      applyFilterVisual();

    }

    function applyFilterVisual(){

      qa(root,".tgm__node")
      .forEach(function(node){

        var nodeEntry =
          node.dataset.entry;

        var visible =
          true;

        if(activeFilter !== "all"){

          if(nodeEntry !== activeFilter){

            if(nodeEntry !== "all"){
              visible = false;
            }

          }

        }

        node.classList.toggle(
          "is-muted",
          !visible
        );

        node.classList.remove(
          "is-active"
        );

        node.classList.remove(
          "is-related"
        );

      });

      qa(root,".tgm__edge")
      .forEach(function(edge){

        if(activeFilter === "all"){

          edge.classList.remove(
            "is-muted"
          );

          edge.classList.remove(
            "is-active"
          );

          return;
        }

        var from =
          byId(edge.dataset.from);

        var to =
          byId(edge.dataset.to);

        var visible =
          false;

        if(from){

          if(from.entry === activeFilter){
            visible = true;
          }

          if(from.entry === "all"){
            visible = true;
          }

        }

        if(to){

          if(to.entry === activeFilter){
            visible = true;
          }

          if(to.entry === "all"){
            visible = true;
          }

        }

        edge.classList.toggle(
          "is-muted",
          !visible
        );

        edge.classList.remove(
          "is-active"
        );

      });

    }

    filterButtons
    .forEach(function(button){

      button.addEventListener(
        "click",
        function(){

          setFilter(
            button.dataset.tgmFilter
          );

        }
      );

    });


    /* =====================================================
       PAN / TOUCH STATE
    ====================================================== */

    function clamp(value,min,max){

      return Math.max(
        min,
        Math.min(
          max,
          value
        )
      );

    }

    function applyTransform(animated){

      if(animated){

        if(!reduceMotion){

          canvas.style.transition =
            "transform 900ms cubic-bezier(.2,.7,.2,1)";

        }

      }else{

        canvas.style.transition =
          "none";

      }

      canvas.style.transform =
        "translate3d(" +
        (baseX + offsetX) +
        "px," +
        (baseY + offsetY) +
        "px,0) scale(" +
        scale +
        ")";

      if(animated){

        window.setTimeout(
          function(){

            canvas.style.transition =
              "none";

          },
          950
        );

      }

    }

    var activePointers = {};
    var panPointerId = null;

    var panStartX = 0;
    var panStartY = 0;

    var panOriginX = 0;
    var panOriginY = 0;

    var pinchStartDistance = 0;
    var pinchStartScale = scale;

    var pinchWorldX = 0;
    var pinchWorldY = 0;

    function pointerCount(){

      return Object.keys(
        activePointers
      ).length;

    }

    function pointerValues(){

      return Object.keys(
        activePointers
      ).map(function(key){

        return activePointers[key];

      });

    }

    function beginPan(pointer){

      panPointerId =
        pointer.id;

      panStartX =
        pointer.x;

      panStartY =
        pointer.y;

      panOriginX =
        offsetX;

      panOriginY =
        offsetY;

      viewport.classList.add(
        "is-dragging"
      );

      activeNodeId = null;

    }

    function updatePan(pointer){

      if(
        panPointerId !==
        pointer.id
      ){
        return;
      }

      var dx =
        pointer.x -
        panStartX;

      var dy =
        pointer.y -
        panStartY;

      offsetX =
        clamp(
          panOriginX + dx,
          -1100,
          1100
        );

      offsetY =
        clamp(
          panOriginY + dy,
          -800,
          800
        );

      applyTransform(false);

    }

    function endPan(){

      panPointerId = null;

      viewport.classList.remove(
        "is-dragging"
      );

    }

    function distanceBetween(a,b){

      var dx =
        a.x - b.x;

      var dy =
        a.y - b.y;

      return Math.sqrt(
        dx * dx +
        dy * dy
      );

    }

    function midpointBetween(a,b){

      return {
        x:(a.x + b.x) / 2,
        y:(a.y + b.y) / 2
      };

    }

    function beginPinch(){

      var points =
        pointerValues();

      if(points.length < 2){
        return;
      }

      endPan();

      pinchStartDistance =
        distanceBetween(
          points[0],
          points[1]
        );

      pinchStartScale =
        scale;

      var midpoint =
        midpointBetween(
          points[0],
          points[1]
        );

      var rect =
        viewport.getBoundingClientRect();

      var pointerX =
        midpoint.x -
        rect.left;

      var pointerY =
        midpoint.y -
        rect.top;

      var currentTranslateX =
        baseX + offsetX;

      var currentTranslateY =
        baseY + offsetY;

      pinchWorldX =
        (
          pointerX -
          currentTranslateX
        ) /
        scale;

      pinchWorldY =
        (
          pointerY -
          currentTranslateY
        ) /
        scale;

    }

    function updatePinch(){

      var points =
        pointerValues();

      if(points.length < 2){
        return;
      }

      if(
        pinchStartDistance <= 0
      ){

        beginPinch();
        return;

      }

      var distance =
        distanceBetween(
          points[0],
          points[1]
        );

      var ratio =
        distance /
        pinchStartDistance;

      var nextScale =
        clamp(
          pinchStartScale * ratio,
          CONFIG.minScale,
          CONFIG.maxScale
        );

      var midpoint =
        midpointBetween(
          points[0],
          points[1]
        );

      var rect =
        viewport.getBoundingClientRect();

      var pointerX =
        midpoint.x -
        rect.left;

      var pointerY =
        midpoint.y -
        rect.top;

      var nextTranslateX =
        pointerX -
        pinchWorldX *
        nextScale;

      var nextTranslateY =
        pointerY -
        pinchWorldY *
        nextScale;

      offsetX =
        clamp(
          nextTranslateX -
          baseX,
          -1100,
          1100
        );

      offsetY =
        clamp(
          nextTranslateY -
          baseY,
          -800,
          800
        );

      scale =
        nextScale;

      applyTransform(false);

    }

    viewport.addEventListener(
      "pointerdown",
      function(event){

        activePointers[
          event.pointerId
        ] = {
          id:event.pointerId,
          x:event.clientX,
          y:event.clientY,
          type:event.pointerType
        };

        try{

          viewport.setPointerCapture(
            event.pointerId
          );

        }catch(error){}

        if(
          pointerCount() === 2
        ){

          beginPinch();
          return;

        }

        if(
          pointerCount() === 1
        ){

          if(
            event.target.closest(
              ".tgm__node"
            )
          ){
            return;
          }

          beginPan(
            activePointers[
              event.pointerId
            ]
          );

        }

      }
    );

    viewport.addEventListener(
      "pointermove",
      function(event){

        if(
          !activePointers[
            event.pointerId
          ]
        ){
          return;
        }

        activePointers[
          event.pointerId
        ].x =
          event.clientX;

        activePointers[
          event.pointerId
        ].y =
          event.clientY;

        if(
          pointerCount() >= 2
        ){

          updatePinch();
          return;

        }

        updatePan(
          activePointers[
            event.pointerId
          ]
        );

      }
    );

    function releasePointer(event){

      delete activePointers[
        event.pointerId
      ];

      if(
        pointerCount() < 2
      ){

        pinchStartDistance = 0;

      }

      if(
        pointerCount() === 1
      ){

        var remaining =
          pointerValues()[0];

        beginPan(
          remaining
        );

      }else if(
        pointerCount() === 0
      ){

        endPan();

      }

    }

    viewport.addEventListener(
      "pointerup",
      releasePointer
    );

    viewport.addEventListener(
      "pointercancel",
      releasePointer
    );


    /* =====================================================
       TRACKPAD / WHEEL ZOOM

       Zoom is anchored to the pointer position,
       similar to Google Maps.
    ====================================================== */

    function setScaleAtPoint(
      nextScale,
      clientX,
      clientY
    ){

      nextScale =
        clamp(
          nextScale,
          CONFIG.minScale,
          CONFIG.maxScale
        );

      if(nextScale === scale){
        return;
      }

      var rect =
        viewport.getBoundingClientRect();

      var pointerX =
        clientX - rect.left;

      var pointerY =
        clientY - rect.top;

      var currentTranslateX =
        baseX + offsetX;

      var currentTranslateY =
        baseY + offsetY;

      var worldX =
        (
          pointerX -
          currentTranslateX
        ) /
        scale;

      var worldY =
        (
          pointerY -
          currentTranslateY
        ) /
        scale;

      var nextTranslateX =
        pointerX -
        worldX *
        nextScale;

      var nextTranslateY =
        pointerY -
        worldY *
        nextScale;

      offsetX =
        nextTranslateX -
        baseX;

      offsetY =
        nextTranslateY -
        baseY;

      offsetX =
        clamp(
          offsetX,
          -1100,
          1100
        );

      offsetY =
        clamp(
          offsetY,
          -800,
          800
        );

      scale =
        nextScale;

      applyTransform(false);

    }

    viewport.addEventListener(
      "wheel",
      function(event){

        if(indexMode){
          return;
        }

        event.preventDefault();

        var delta =
          event.deltaY;

        var factor =
          Math.exp(
            -delta *
            CONFIG.zoomSensitivity
          );

        var nextScale =
          scale *
          factor;

        setScaleAtPoint(
          nextScale,
          event.clientX,
          event.clientY
        );

      },
      {
        passive:false
      }
    );


    /* =====================================================
       SUBTLE POINTER RESPONSE
    ====================================================== */

    function activatePointer(){

      if(reduceMotion){
        return;
      }

      if(
        window.matchMedia(
          "(hover:none)"
        ).matches
      ){
        return;
      }

      viewport.addEventListener(
        "mousemove",
        function(event){

          var rect =
            viewport.getBoundingClientRect();

          var mx =
            event.clientX - rect.left;

          var my =
            event.clientY - rect.top;

          qa(root,".tgm__node")
          .forEach(function(node){

            var item =
              byId(
                node.dataset.nodeId
              );

            if(!item){
              return;
            }

            var canvasX =
              item.x *
              scale +
              baseX +
              offsetX;

            var canvasY =
              item.y *
              scale +
              baseY +
              offsetY;

            var dx =
              canvasX - mx;

            var dy =
              canvasY - my;

            var dist =
              Math.sqrt(
                dx * dx +
                dy * dy
              );

            if(
              dist <
              CONFIG.pointerRadius
            ){

              var safeDist =
                Math.max(
                  dist,
                  1
                );

              var force =
                (
                  CONFIG.pointerRadius -
                  dist
                ) /
                CONFIG.pointerRadius;

              var moveX =
                (
                  dx /
                  safeDist
                ) *
                force *
                CONFIG.pointerStrength;

              var moveY =
                (
                  dy /
                  safeDist
                ) *
                force *
                CONFIG.pointerStrength;

              node.style.setProperty(
                "--push-x",
                moveX.toFixed(2) + "px"
              );

              node.style.setProperty(
                "--push-y",
                moveY.toFixed(2) + "px"
              );

            }else{

              node.style.setProperty(
                "--push-x",
                "0px"
              );

              node.style.setProperty(
                "--push-y",
                "0px"
              );

            }

          });

        }
      );

      viewport.addEventListener(
        "mouseleave",
        function(){

          qa(root,".tgm__node")
          .forEach(function(node){

            node.style.setProperty(
              "--push-x",
              "0px"
            );

            node.style.setProperty(
              "--push-y",
              "0px"
            );

          });

        }
      );

    }


    /* =====================================================
       INDEX
    ====================================================== */

    var groups = [
      {id:"read",number:"01"},
      {id:"rest",number:"02"},
      {id:"see",number:"03"},
      {id:"check",number:"04"}
    ];

    function renderIndex(){

      index.innerHTML = "";

      groups.forEach(function(group){

        var entry =
          byId(group.id);

        if(!entry){
          return;
        }

        var related =
          mapData.filter(function(item){

            if(item.id === group.id){
              return false;
            }

            return (
              item.entry ===
              group.id
            );

          });

        var section =
          document.createElement("section");

        section.className =
          "tgm__index-group";

        var head =
          document.createElement("div");

        head.className =
          "tgm__index-head";

        var number =
          document.createElement("span");

        number.className =
          "tgm__index-number";

        number.textContent =
          group.number;

        var title =
          document.createElement("span");

        title.className =
          "tgm__index-title";

        title.textContent =
          entry.label;

        var count =
          document.createElement("span");

        count.className =
          "tgm__index-count";

        count.textContent =
          related.length +
          " ENTRIES";

        head.appendChild(number);
        head.appendChild(title);
        head.appendChild(count);

        section.appendChild(head);

        var items =
          document.createElement("div");

        items.className =
          "tgm__index-items";

        related.forEach(function(item){

          if(!item.url){
            return;
          }

          var link =
            document.createElement("a");

          link.className =
            "tgm__index-link";

          link.href =
            item.url;

          link.textContent =
            item.title;

          items.appendChild(link);

        });

        section.appendChild(items);
        index.appendChild(section);

      });

    }

    function setMode(nextIndexMode){

      indexMode =
        nextIndexMode;

      root.classList.toggle(
        "is-index",
        indexMode
      );

      index.hidden =
        !indexMode;

      modeButton.setAttribute(
        "aria-pressed",
        indexMode ?
        "true" :
        "false"
      );

      modeButton.textContent =
        indexMode ?
        "MAP" :
        "INDEX";

    }

    modeButton.addEventListener(
      "click",
      function(){

        setMode(
          !indexMode
        );

      }
    );


    /* =====================================================
       FULL RENDER
    ====================================================== */

    function renderAll(){

      renderNodes();
      renderEdges();
      renderIndex();

      applyFilterVisual();

    }


    /* =====================================================
       DRIFT
    ====================================================== */

    function drift(){

      if(
        CONFIG.driftRefreshesArticles
      ){

        buildDynamicPosts();

        renderAll();

      }

      var candidates =
        mapData.filter(function(item){

          if(item.type === "current"){
            return false;
          }

          if(item.type === "entry"){
            return false;
          }

          if(activeFilter === "all"){
            return true;
          }

          return (
            item.entry ===
            activeFilter
          );

        });

      if(!candidates.length){
        return;
      }

      var selected =
        candidates[
          Math.floor(
            Math.random() *
            candidates.length
          )
        ];

      var rect =
        viewport.getBoundingClientRect();

      var viewportCenterX =
        rect.width / 2;

      var viewportCenterY =
        rect.height / 2;

      offsetX =
        viewportCenterX -
        selected.x *
        scale -
        baseX;

      offsetY =
        viewportCenterY -
        selected.y *
        scale -
        baseY;

      offsetX =
        clamp(
          offsetX,
          -1100,
          1100
        );

      offsetY =
        clamp(
          offsetY,
          -800,
          800
        );

      applyTransform(true);

      activeNodeId =
        selected.id;

      window.setTimeout(
        function(){

          activateNode(
            selected.id
          );

        },
        reduceMotion ?
        0 :
        620
      );

    }

    driftButton.addEventListener(
      "click",
      drift
    );

    viewport.addEventListener(
      "dblclick",
      function(event){

        event.preventDefault();

        setScaleAtPoint(
          scale *
          CONFIG.doubleTapZoomFactor,
          event.clientX,
          event.clientY
        );

      }
    );

    var lastTouchTapTime = 0;
    var lastTouchTapX = 0;
    var lastTouchTapY = 0;

    viewport.addEventListener(
      "pointerup",
      function(event){

        if(
          event.pointerType !==
          "touch"
        ){
          return;
        }

        var now =
          Date.now();

        var elapsed =
          now -
          lastTouchTapTime;

        var dx =
          event.clientX -
          lastTouchTapX;

        var dy =
          event.clientY -
          lastTouchTapY;

        var moved =
          Math.sqrt(
            dx * dx +
            dy * dy
          );

        if(
          elapsed > 0
        ){

          if(
            elapsed < 320
          ){

            if(
              moved < 36
            ){

              setScaleAtPoint(
                scale *
                CONFIG.doubleTapZoomFactor,
                event.clientX,
                event.clientY
              );

              lastTouchTapTime = 0;

              return;

            }

          }

        }

        lastTouchTapTime =
          now;

        lastTouchTapX =
          event.clientX;

        lastTouchTapY =
          event.clientY;

      }
    );


    /* =====================================================
       LOAD POSTS
    ====================================================== */

    function loadPosts(){

      fetch(
        CONFIG.endpoint,
        {
          credentials:"same-origin",
          headers:{
            Accept:"application/json"
          }
        }
      )
      .then(function(response){

        if(!response.ok){

          throw new Error(
            "Posts request failed."
          );

        }

        return response.json();

      })
      .then(function(posts){

        if(!Array.isArray(posts)){
          return;
        }

        sourcePosts =
          posts.slice();

        buildDynamicPosts();

        renderAll();

      })
      .catch(function(){

        sourcePosts = [];

        buildDynamicPosts();

        renderAll();

      });

    }


    /* =====================================================
       ESC / START
    ====================================================== */

    root.addEventListener(
      "keydown",
      function(event){

        if(event.key === "Escape"){

          activeNodeId = null;

          clearVisualRelations();

        }

      }
    );

    renderAll();

    applyTransform(false);

    setFilter("all");

    activatePointer();

    loadPosts();

  });

})();
</script>

]]></content:encoded>
					
					<wfw:commentRss>https://tranquilguides.com/map/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1353</post-id>	</item>
		<item>
		<title>Guide Soundtrack</title>
		<link>https://tranquilguides.com/reading-with-sound/</link>
					<comments>https://tranquilguides.com/reading-with-sound/#respond</comments>
		
		<dc:creator><![CDATA[案内人のアシカ]]></dc:creator>
		<pubDate>Tue, 30 Jun 2026 21:08:14 +0000</pubDate>
				<category><![CDATA[生存ログ]]></category>
		<category><![CDATA[体験]]></category>
		<category><![CDATA[記憶]]></category>
		<category><![CDATA[道具]]></category>
		<category><![CDATA[音]]></category>
		<guid isPermaLink="false">https://tranquilguides.com/?p=1464</guid>

					<description><![CDATA[音楽は、読む時間にどこまで自然に寄り添えるのか。同じ文章と異なる音の組み合わせから、記憶の残り方を試す小さな読書実験です。]]></description>
										<content:encoded><![CDATA[
<p class="has-text-align-center wp-block-paragraph">静かな場所で、お試しください。</p>


	<section id="tq-gs-1464" class="tq-gs" data-provider="soundcloud" data-player-id="tq-gs-1464-master">
		<div class="tq-gs__entry">
			<p class="tq-gs__brand">GUIDE SOUNDTRACK</p>
			<div class="tq-gs__heading" role="heading" aria-level="2">Soundtrack for this guide</div>
			<p class="tq-gs__description">このガイドには、読む時間のための音楽があります。</p>
			<div class="tq-gs__actions">
				<button type="button" class="tq-gs__start" disabled>
					<span class="tq-gs__start-icon" aria-hidden="true">♪</span>
					<span class="tq-gs__start-label">音楽とともに読む</span>
				</button>
				<button type="button" class="tq-gs__silent">静かに読む</button>
			</div>
			<p class="tq-gs__status" aria-live="polite">プレイヤーを準備しています。</p>
		</div>

		<div class="tq-gs__article-start" tabindex="-1"></div>

		<div class="tq-gs__master-wrap" aria-hidden="true">
			<iframe id="tq-gs-1464-master" class="tq-gs__master-soundcloud" title="SoundCloud player" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https://soundcloud.com/blue-healer-usa/luminescent-eyes&#038;color=#111416&#038;auto_play=false&#038;hide_related=true&#038;show_comments=false&#038;show_user=false&#038;show_reposts=false&#038;show_teaser=false&#038;visual=false"></iframe>		</div>

		<div class="tq-gs__data" data-title="Luminescent Eyes" data-artist="Blue Healer" hidden></div>
	</section>
	



<p class="has-text-align-center wp-block-paragraph">アイキャッチ [静かな椅子や窓辺]</p>



<p class="has-text-align-center wp-block-paragraph">あなたが今いる場所は、今日だけの読書室です。</p>



<p class="has-text-align-center wp-block-paragraph">もしよければ、音楽とともに読み始めてください。</p>



<p class="has-text-align-center wp-block-paragraph">音がなくても、この文章は変わりません。</p>



<p class="has-text-align-center wp-block-paragraph">けれど、同じ文章でも、聞こえている音が違えば、残る記憶も少し変わります。</p>



<p class="has-text-align-center wp-block-paragraph">このページは、Guide Soundtrack のテストページです。</p>



<p class="has-text-align-center wp-block-paragraph">読書の入口として、音楽はどこまで自然に寄り添えるのか。</p>



<p class="has-text-align-center wp-block-paragraph">その小さな実験に、付き合っていただければ幸いです。</p>


	<section class="tq-gs-player" data-controller-for="tq-gs-1464">
		<p class="tq-gs-player__label">GUIDE SOUNDTRACK</p>

		<div class="tq-gs-player__card">
			<div class="tq-gs-player__artwork-wrap" aria-hidden="true">
				<img decoding="async" class="tq-gs-player__artwork" src="" alt="" hidden>
				<div class="tq-gs-player__placeholder"><span>♪</span></div>
			</div>

			<div class="tq-gs-player__copy">
				<p class="tq-gs-player__track">Luminescent Eyes</p>
				<p class="tq-gs-player__artist">Blue Healer</p>
				<p class="tq-gs-player__state" aria-live="polite">準備しています。</p>
			</div>

			<button type="button" class="tq-gs-player__toggle" disabled aria-label="再生">
				<span class="tq-gs-player__toggle-icon" aria-hidden="true"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/25b6.png" alt="▶" class="wp-smiley" style="height: 1em; max-height: 1em;" /></span>
			</button>
		</div>
	</section>
	
]]></content:encoded>
					
					<wfw:commentRss>https://tranquilguides.com/reading-with-sound/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1464</post-id>	</item>
		<item>
		<title>一時避難所｜いまをやり過ごすための小さな公共施設</title>
		<link>https://tranquilguides.com/temporary-shelter/</link>
					<comments>https://tranquilguides.com/temporary-shelter/#respond</comments>
		
		<dc:creator><![CDATA[案内人のアシカ]]></dc:creator>
		<pubDate>Thu, 25 Jun 2026 22:26:24 +0000</pubDate>
				<category><![CDATA[生存ログ]]></category>
		<category><![CDATA[休息]]></category>
		<category><![CDATA[体験]]></category>
		<category><![CDATA[回復]]></category>
		<category><![CDATA[居場所]]></category>
		<category><![CDATA[施設]]></category>
		<guid isPermaLink="false">https://tranquilguides.com/?p=1174</guid>

					<description><![CDATA[<p><img src="https://i0.wp.com/tranquilguides.com/wp-content/uploads/2026/06/IMG_20260626_072229.jpg?fit=1024%2C683&ssl=1" class="webfeedsFeaturedVisual" /></p>何もしたくない日や、少しだけ休みたい日に。暖炉や給水所、セーフルームなどを歩きながら、いまをやり過ごすための小さな避難所です。]]></description>
										<content:encoded><![CDATA[<p><img src="https://i0.wp.com/tranquilguides.com/wp-content/uploads/2026/06/IMG_20260626_072229.jpg?fit=1024%2C683&ssl=1" class="webfeedsFeaturedVisual" /></p>
<style data-wp-block-html="css">
.shelter-wrap {
  --shelter-text: #3f3a34;
  --shelter-muted: #8d8171;
  --shelter-border: rgba(80,70,55,.14);
  --shelter-surface: rgba(255,255,255,.58);
  --shelter-surface-hover: rgba(255,255,255,.82);
  --shelter-radius: 32px;
  --shelter-shadow: 0 18px 50px rgba(70,55,35,.08);
width: 100%;
max-width: 100%;
margin: 24px auto;
padding: 0 10px;
color: var(--shelter-text);
font-family: "Hiragino Mincho ProN", "Yu Mincho", serif;
}
/* 共通カード */
.shelter-home,
.shelter-room {
position: relative;
width: 100%;
box-sizing: border-box;
min-height: 520px;
padding: 56px 28px 86px;
border-radius: var(--shelter-radius);
background:
radial-gradient(circle at top, rgba(255,255,255,.86),
rgba(244,239,230,.76)),
linear-gradient(180deg, #f7f2e8, #ebe3d6);
border: 1px solid rgba(80,70,55,.12);
box-shadow: var(--shelter-shadow);
text-align: center;
box-sizing: border-box;
}
.shelter-kicker {
margin: 0 0 22px;
font-size: 12px;
letter-spacing: .12em;
color: var(--shelter-muted);
}
.shelter-home h1{
margin: 0 0 28px;
font-size: clamp(28px, 6vw, 42px);
font-weight: 400;
letter-spacing: .08em;
}
.shelter-lead,
.shelter-room p {
margin: 0 auto 34px;
max-width: 420px;
font-size: 16px;
line-height: 2.1;
}
.shelter-note,
.water-msg,
.lost-msg,
.small-msg {
font-size: 13px;
color: var(--shelter-muted);
}
.small-msg {
margin-top: -16px;
line-height: 1.9;
}
/* ボタン */
.shelter-buttons {
display: grid;
gap: 14px;
max-width: 320px;
margin: 0 auto 28px;
}
.shelter-buttons button,
.shelter-room button {
appearance: none;
border: 1px solid rgba(80,70,55,.16);
border-radius: 999px;
background: var(--shelter-surface);
color: #4a4238;
padding: 14px 22px;
font-size: 15px;
font-family: inherit;
cursor: pointer;
}
.shelter-buttons button:hover,
.shelter-room button:hover {
background: var(--shelter-surface-hover);
}
.backBtn {
position: absolute;
left: 28px;
bottom: 28px;
padding: 10px 18px !important;
background: rgba(255,255,255,.38) !important;
color: #8d8171 !important;
font-size: 13px !important;
}
/* ==========================
Fireplace
========================== */
.tg-fireplace {
margin: 28px auto;
text-align: center;
}
.tg-fire {
position: relative;
width: 92px;
height: 110px;
margin: 0 auto 22px;
}
.tg-fire span {
position: absolute;
left: 50%;
bottom: 0;
border-radius: 50% 50% 45% 45%;
transform-origin: bottom center;
animation: tgFireFlicker 2.8s ease-in-out infinite;
}
/* 外側の炎 */
.tg-fire span:nth-child(1) {
width: 48px;
height: 84px;
margin-left: -24px;
background: radial-gradient(
ellipse at 50% 75%,
rgba(255, 225, 160, .95) 0%,
rgba(242, 143, 55, .92) 48%,
rgba(126, 49, 20, .78) 100%
);
}
/* 中央の炎 */
.tg-fire span:nth-child(2) {
width: 36px;
height: 66px;
margin-left: -18px;
background: radial-gradient(
ellipse at 50% 80%,
rgba(255, 240, 200, .96) 0%,
rgba(255, 186, 80, .82) 65%,
rgba(255, 120, 40, .28) 100%
);
animation-delay: .5s;
}
/* 芯 */
.tg-fire span:nth-child(3) {
width: 20px;
height: 42px;
margin-left: -10px;
background: rgba(255,250,235,.95);
filter: blur(.5px);
animation-delay: 1.1s;
}
.tg-fire.is-strong span:nth-child(1) {
animation-duration: 1.8s;
transform: scale(1.08, 1.14);
}
.tg-fire.is-strong span:nth-child(2) {
animation-duration: 1.5s;
opacity: .86;
}
.tg-fire.is-strong span:nth-child(3) {
animation-duration: 1.3s;
opacity: 1;
}
.tg-spark {
position: absolute;
left: 50%;
bottom: 36px;
width: 4px;
height: 4px;
border-radius: 50%;
background: rgba(255, 205, 120, .9);
pointer-events: none;
opacity: 0;
animation: tgSparkFloat 2.8s ease-out forwards;
}
.tg-ash {
position: absolute;
left: 50%;
bottom: 42px;
width: 3px;
height: 3px;
border-radius: 50%;
background: rgba(90, 78, 68, .45);
pointer-events: none;
opacity: 0;
animation: tgAshFall 3.8s ease-in forwards;
}
@keyframes tgAshFall {
0% {
transform: translate(-50%, 0) scale(.8);
opacity: 0;
}
20% {
opacity: .45;
}
100% {
transform: translate(calc(-50% + var(--ash-x)), 48px) scale(.45);
opacity: 0;
}
}
@keyframes tgSparkFloat {
0% {
transform: translate(-50%, 0) scale(.7);
opacity: 0;
}
18% {
opacity: .9;
}
100% {
transform: translate(calc(-50% + var(--spark-x)), -72px) scale(.2);
opacity: 0;
}
}
@keyframes tgFireFlicker {
0%{
transform:translateY(0) scale(.96,1) rotate(-2deg);
opacity:.72;
}
20%{
transform:translateY(-2px) scale(1.02,1.08) rotate(2deg);
opacity:.95;
}
45%{
transform:translateY(1px) scale(.94,.94) rotate(-1deg);
opacity:.78;
}
70%{
transform:translateY(-1px) scale(1.04,1.12) rotate(3deg);
opacity:1;
}
100%{
transform:translateY(0) scale(.96,1) rotate(-2deg);
opacity:.72;
}
}
#roomFire.is-warm-glow {
background-color: rgba(255, 190, 120, .055);
}
.tg-fireplace{
display:flex;
flex-direction:column;
align-items:center;
gap:14px;
margin:28px auto;
}
#roomFire .tg-sound-btn{
display:flex;
align-items:center;
justify-content:center;
width:40px;
height:40px;
padding:0;
border:1px solid rgba(80,62,48,.18);
border-radius:50%;
background:rgba(255,255,255,.25);
color:#6b5b4e;
transition:.3s;
}
#roomFire .tg-sound-btn:hover{
background:rgba(255,255,255,.55);
}
#roomFire .tg-sound-btn svg{
width:18px;
height:18px;
}
#roomFire .tg-sound-btn.is-on{
background:rgba(255,220,170,.18);
color:#8b5b28;
}
.tg-ember {
position: absolute;
left: 50%;
bottom: 2px;
width: 58px;
height: 14px;
transform: translateX(-50%);
border-radius: 999px;
background: radial-gradient(
ellipse at center,
rgba(210, 62, 22, .62) 0%,
rgba(150, 44, 22, .34) 48%,
rgba(90, 36, 22, 0) 78%
);
filter: blur(3px);
opacity: .62;
animation: tgEmberGlow 5.8s ease-in-out infinite;
}
@keyframes tgEmberGlow {
0%, 100% {
opacity: .38;
transform: translateX(-50%) scale(.92, .86);
}
45% {
opacity: .86;
transform: translateX(-50%) scale(1.08, 1);
}
72% {
opacity: .52;
transform: translateX(-50%) scale(.98, .92);
}
}
/* タイトル */
#roomFire .room-title{
margin-bottom:16px;
font-size:.92rem;
letter-spacing:.16em;
color:#7a6d63;
opacity:.65;
}
/* 暖炉メッセージ */
.tg-fire-text{
min-height:2.6em;
max-width:28em;
margin:0 auto;
line-height:1.9;
color:#4b4037;
opacity:0;
transition:opacity 1.8s ease;
}
.tg-fire-text.is-visible{
opacity:1;
}
/* ごゆっくり */
#roomFire .small-msg {
font-size: 11px;
color: rgba(141, 129, 113, .75);
letter-spacing: .08em;
margin-top: -10px;
}
/* セーフルーム：呼吸 */
.safe-icon {
position: relative;
width: 90px;
height: 90px;
margin: 0 auto 28px;
}
.safe-icon::before {
content: "";
position: absolute;
left: 50%;
top: 50%;
width: 70px;
height: 70px;
transform: translate(-50%, -50%);
border-radius: 50%;
background: radial-gradient(
circle,
rgba(255,255,255,.72) 0%,
rgba(245,243,236,.42) 45%,
rgba(245,243,236,0) 80%
);
filter: blur(16px);
animation: safeAura 5.5s ease-in-out infinite;
}
.safe-icon::after {
content: "";
position: absolute;
left: 50%;
top: 50%;
width: 18px;
height: 18px;
transform: translate(-50%, -50%);
border-radius: 50%;
border: 1.5px solid rgba(165,160,150,.55);
animation: safePulse 5.5s ease-in-out infinite;
}
@keyframes safeAura {
0%, 100% {
transform: translate(-50%, -50%) scale(.92);
opacity: .20;
}
50% {
transform: translate(-50%, -50%) scale(1.16);
opacity: .65;
}
}
@keyframes safePulse {
0% {
width: 18px;
height: 18px;
opacity: .65;
}
65% {
width: 54px;
height: 54px;
opacity: .12;
}
100% {
width: 18px;
height: 18px;
opacity: .65;
}
}
.safe-fade-msg {
opacity: 0;
transform: translateY(8px);
transition: opacity 2.6s ease, transform 2.6s ease;
font-size: 14px !important;
color: var(--shelter-muted);
}
.safe-fade-msg.is-visible {
opacity: 1;
transform: translateY(0);
}
/* 給水所 */
.water-drop {
position: relative;
width: 72px;
height: 92px;
margin: 0 auto 24px;
}
.water-drop span {
position: absolute;
left: 50%;
bottom: 8px;
width: 34px;
height: 48px;
border-radius: 58%;
background: rgba(92, 170, 220, .42);
transform: translateX(-50%) rotate(45deg);
transform-origin: center;
animation: waterDropFloat 3.2s ease-in-out infinite;
box-shadow: 0 0 28px rgba(120, 190, 230, .16);
}
.water-drop span:nth-child(2) {
width: 44px;
height: 60px;
background: rgba(132, 198, 232, .28);
animation-delay: .45s;
}
.water-drop span:nth-child(3) {
width: 24px;
height: 34px;
background: rgba(210, 238, 250, .58);
animation-delay: .9s;
}
@keyframes waterDropFloat {
0%, 100% {
transform: translateX(-50%) translateY(0) rotate(45deg) scale(1);
opacity: .68;
}
50% {
transform: translateX(-50%) translateY(-8px) rotate(45deg) scale(1.08);
opacity: .95;
}
}
.water-msg {
min-height: 2.2em;
margin-bottom: 22px !important;
opacity: 0;
visibility: hidden;
transform: translateY(4px);
transition: opacity 1.2s ease, transform 1.2s ease, visibility 1.2s
ease;
}
.water-msg.is-visible {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
/* 深夜待合室：月明かり */
.night-icon {
position: relative;
display: inline-flex;
justify-content: center;
align-items: center;
width: 90px;
height: 90px;
margin: 0 auto 24px;
font-size: 0;
}
.night-icon::before {
content: "";
position: absolute;
width: 120px;
height: 120px;
border-radius: 50%;
background: radial-gradient(
circle,
rgba(255,240,190,.65) 0%,
rgba(255,240,190,.28) 38%,
rgba(255,240,190,.10) 58%,
rgba(255,240,190,0) 80%
);
filter: blur(20px);
animation: moonGlow 7s ease-in-out infinite;
}
.night-icon::after {
content: "";
position: relative;
z-index: 2;
font-size: 46px;
animation: moonBreath 5.5s ease-in-out infinite;
}
@keyframes moonGlow {
0%, 100% {
transform: scale(.9);
opacity: .25;
}
50% {
transform: scale(1.18);
opacity: .72;
}
}
@keyframes moonBreath {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-2px);
}
}
.night-room {
animation: moonRoomGlow 7s ease-in-out infinite;
}
@keyframes moonRoomGlow {
0%, 100% {
box-shadow:
0 18px 50px rgba(70,55,35,.08),
0 0 30px rgba(255,240,190,.03);
}
50% {
box-shadow:
0 18px 50px rgba(70,55,35,.08),
0 0 80px rgba(255,240,190,.12);
}
}
/* 落とし物センター */
.lost-icon {
position: relative;
width: 90px;
height: 90px;
margin: 0 auto 24px;
}
.lost-post {
position: absolute;
left: 50%;
bottom: 14px;
width: 42px;
height: 46px;
border-radius: 10px 10px 8px 8px;
background: rgba(190, 78, 68, .72);
transform: translateX(-50%);
box-shadow: 0 10px 26px rgba(120,70,55,.10);
}
.lost-privacy-note{
max-width:360px;
margin:-6px auto 22px;
font-size:10px!important;
line-height:2;
letter-spacing:.03em;
color:rgba(80,70,55,.50);
}
.lost-post::before {
content: "";
position: absolute;
left: 9px;
top: 10px;
width: 24px;
height: 12px;
border-radius: 3px;
background: rgba(255,245,225,.72);
}
.lost-post::after {
content: "";
position: absolute;
left: 15px;
bottom: -18px;
width: 12px;
height: 20px;
border-radius: 4px;
background: rgba(150,95,80,.38);
}
.lost-letter {
position: absolute;
left: 50%;
top: 8px;
width: 30px;
height: 20px;
border-radius: 4px;
background: rgba(255,248,232,.86);
border: 1px solid rgba(120,90,70,.18);
transform: translateX(-50%);
animation: letterFloat 4.8s ease-in-out infinite;
}
.lost-letter::before {
content: "";
position: absolute;
left: 5px;
top: 5px;
width: 18px;
height: 9px;
border-left: 1px solid rgba(120,90,70,.24);
border-bottom: 1px solid rgba(120,90,70,.24);
transform: rotate(-45deg);
}
@keyframes letterFloat {
0%, 100% {
transform: translateX(-50%) translateY(0) rotate(-2deg);
opacity: .78;
}
50% {
transform: translateX(-50%) translateY(8px) rotate(2deg);
opacity: 1;
}
}
.lost-input {
display: block;
width: min(360px, 100%);
margin: -10px auto 22px;
padding: 16px 18px;
border-radius: 20px;
border: 1px solid rgba(80,70,55,.14);
background: rgba(255,255,255,.48);
color: #4a4238;
font-family: inherit;
font-size: 14px;
line-height: 1.8;
box-sizing: border-box;
resize: vertical;
overflow: auto;
min-height: 250px;
max-height: 70vh;
}
.lost-input::placeholder {
color: rgba(80,70,55,.38);
}
.lost-input:focus {
outline: none;
background: rgba(255,255,255,.72);
border-color: rgba(80,70,55,.24);
}
.lost-receipt {
min-height: 5.4em;
margin-top: 20px;
opacity: 0;
transform: translateY(6px);
transition: opacity 1.4s ease, transform 1.4s ease;
}
.lost-receipt.is-visible {
opacity: 1;
transform: translateY(0);
}
.lost-receipt.is-fading {
opacity: 0;
transform: translateY(-4px);
}
.lost-item {
margin-bottom: 6px !important;
font-size: 15px !important;
color: #5b5045;
}
.lost-msg {
font-size: 12px !important;
line-height: 1.8;
color: var(--shelter-muted);
margin-bottom: 5px !important;
}
.lost-hp {
display: none !important;
}
/* 東屋 */
.azumaya-icon {
position: relative;
display: inline-flex;
justify-content: center;
align-items: center;
width: 90px;
height: 90px;
margin: 0 auto 24px;
font-size: 0;
}
.azumaya-icon::before {
content: "";
position: relative;
z-index: 2;
font-size: 42px;
animation: leafFloat 6.5s ease-in-out infinite;
}
.azumaya-icon::after {
content: "";
position: absolute;
width: 90px;
height: 90px;
border-radius: 50%;
background: radial-gradient(
circle,
rgba(175,205,150,.28) 0%,
rgba(175,205,150,.10) 45%,
rgba(175,205,150,0) 80%
);
filter: blur(16px);
animation: leafGlow 6.5s ease-in-out infinite;
}
@keyframes leafFloat {
0%, 100% {
transform: translateX(0) translateY(0) rotate(-6deg);
}
25% {
transform: translateX(3px) translateY(-2px) rotate(-2deg);
}
50% {
transform: translateX(7px) translateY(-5px) rotate(5deg);
}
75% {
transform: translateX(2px) translateY(-1px) rotate(1deg);
}
}
@keyframes leafGlow {
0%, 100% {
transform: scale(.92);
opacity: .18;
}
50% {
transform: scale(1.15);
opacity: .45;
}
}
.azumaya-fade-msg {
opacity: 0;
transform: translateY(8px);
transition: opacity 2.8s ease, transform 2.8s ease;
font-size: 16px !important;
color: #5b5045;
}
.azumaya-fade-msg.is-visible {
opacity: 1;
transform: translateY(0);
}
/* iPhone */
@media (max-width: 600px) {
.shelter-wrap {
max-width:100%;
margin: 16px auto;
padding:0 6px;
}
.shelter-home,
.shelter-room {
min-height: 500px;
padding: 40px 16px 72px;
border-radius: 20px;
}
.backBtn {
left: 20px;
bottom: 20px;
}
}


.shelter-wrap [hidden] {
  display: none !important;
}

.shelter-wrap *,
.shelter-wrap *::before,
.shelter-wrap *::after {
  box-sizing: border-box;
}

.shelter-wrap button {
  transition:
    background-color .22s ease,
    border-color .22s ease,
    color .22s ease,
    opacity .22s ease,
    transform .22s ease;
}

.shelter-wrap button:active {
  transform: translateY(1px);
}

.shelter-wrap button:focus-visible,
.shelter-wrap textarea:focus-visible {
  outline: 2px solid rgba(106,125,137,.55);
  outline-offset: 3px;
}

.shelter-wrap button:disabled {
  cursor: wait;
  opacity: .55;
}

.shelter-room[aria-hidden="true"],
.shelter-home[aria-hidden="true"] {
  display: none !important;
}

.shelter-status {
  min-height: 1.8em;
}

@media (prefers-reduced-motion: reduce) {
  .shelter-wrap *,
  .shelter-wrap *::before,
  .shelter-wrap *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
    transition-duration: .001ms !important;
  }
}

@media (max-width: 600px) {
  .lost-input {
    min-height: 210px;
  }
}

</style>

<script data-wp-block-html="js">
(() => {
  "use strict";

  const ROOT_ID = "shelterHome";

  function initShelter() {
    const home = document.getElementById(ROOT_ID);
    const wrap = home?.closest(".shelter-wrap");

    if (!home || !wrap || wrap.dataset.initialized === "true") {
      return;
    }

    wrap.dataset.initialized = "true";

    const rooms = {
      fire: document.getElementById("roomFire"),
      safe: document.getElementById("roomSafe"),
      water: document.getElementById("roomWater"),
      night: document.getElementById("roomNight"),
      lost: document.getElementById("roomLost"),
      azumaya: document.getElementById("roomAzumaya")
    };

    if (Object.values(rooms).some((room) => !room)) {
      console.warn("[一時避難所] 必要な部屋要素が見つかりません。");
      return;
    }

    const state = {
      currentRoom: "home",
      safeTimer: null,
      azumayaTimer: null,
      fireTimers: new Set(),
      fireRunning: false,
      fireEnteredAt: 0,
      lastFireLine: "",
      waterCount: 0,
      lastWaterMessage: "",
      lostTimer: null
    };

    const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;

    const scrollTop = () => {
      window.scrollTo({
        top: 0,
        behavior: prefersReducedMotion ? "auto" : "smooth"
      });
    };

    const setTimer = (callback, delay, group = "general") => {
      const id = window.setTimeout(() => {
        if (group === "fire") {
          state.fireTimers.delete(id);
        }
        callback();
      }, delay);

      if (group === "fire") {
        state.fireTimers.add(id);
      }

      return id;
    };

    const clearTimer = (id) => {
      if (id) {
        window.clearTimeout(id);
      }
    };

    const clearFireTimers = () => {
      state.fireTimers.forEach((id) => window.clearTimeout(id));
      state.fireTimers.clear();
      state.fireRunning = false;
    };

    const setVisible = (element, visible) => {
      element.hidden = !visible;
      element.setAttribute("aria-hidden", visible ? "false" : "true");
    };

    const hideAllRooms = () => {
      Object.values(rooms).forEach((room) => setVisible(room, false));
    };

    const stopFireAudio = () => {
      fireAudio.pause();
      fireAudio.currentTime = 0;
      updateSoundButton(false);
    };

    const leaveCurrentRoom = () => {
      clearTimer(state.safeTimer);
      clearTimer(state.azumayaTimer);
      state.safeTimer = null;
      state.azumayaTimer = null;

      document.getElementById("safeFadeMsg")?.classList.remove("is-visible");
      document.getElementById("azumayaFadeMsg")?.classList.remove("is-visible");

      if (state.currentRoom === "fire") {
        clearFireTimers();
        stopFireAudio();
      }
    };

    const openRoom = (roomName) => {
      if (!rooms[roomName]) return;

      leaveCurrentRoom();
      setVisible(home, false);
      hideAllRooms();
      setVisible(rooms[roomName], true);
      state.currentRoom = roomName;
      scrollTop();

      if (roomName === "fire") {
        startFireExperience();
      }

      if (roomName === "safe") {
        const message = document.getElementById("safeFadeMsg");
        message?.classList.remove("is-visible");
        state.safeTimer = setTimer(() => message?.classList.add("is-visible"), 2600);
      }

      if (roomName === "azumaya") {
        const message = document.getElementById("azumayaFadeMsg");
        message?.classList.remove("is-visible");
        state.azumayaTimer = setTimer(() => message?.classList.add("is-visible"), 2200);
      }
    };

    const returnHome = () => {
      leaveCurrentRoom();
      hideAllRooms();
      setVisible(home, true);
      state.currentRoom = "home";
      scrollTop();
    };

    wrap.querySelectorAll("[data-room]").forEach((button) => {
      button.addEventListener("click", () => openRoom(button.dataset.room));
    });

    wrap.querySelectorAll(".backBtn").forEach((button) => {
      button.addEventListener("click", returnHome);
    });

    /* -----------------------------------------
     * 暖炉
     * -------------------------------------- */

    const fire = wrap.querySelector(".tg-fire");
    const fireText = document.getElementById("tgFireText");
    const roomFire = rooms.fire;
    const fireSoundBtn = document.getElementById("fireSoundBtn");

    const earlyLines = [
      "パチッ",
      "小さく火の粉が舞いました。",
      "薪が静かに鳴りました。",
      "灰が少し落ちました。",
      "炎が少し高くなりました。",
      "オレンジ色が少し濃くなりました。",
      "炎の形が変わりました。",
      "木の香りがする気がしました。",
      "火がゆっくり揺れています。",
      "暖かい空気が少し流れました。"
    ];

    const middleLines = [
      "炎はまだ静かに燃えています。",
      "部屋は変わらず静かです。",
      "火は急ぎません。",
      "灰が少し積もりました。",
      "また、小さく音がしました。",
      "炎は同じようで、少し違います。",
      "赤い熾火が見えました。",
      "光が壁に揺れています。",
      "部屋の空気が少し柔らかく感じられます。"
    ];

    const lateLines = [
      "火はまだここにあります。",
      "少しだけ時間が過ぎました。",
      "外のことは分かりません。",
      "炎は変わらず燃えています。",
      "ここでは時計はあまり役に立ちません。"
    ];

    const iconOff = `
      <svg aria-hidden="true" width="18" height="18" fill="none" stroke="currentColor"
        stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"
        viewBox="0 0 24 24">
        <polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon>
        <line x1="23" y1="9" x2="17" y2="15"></line>
        <line x1="17" y1="9" x2="23" y2="15"></line>
      </svg>`;

    const iconOn = `
      <svg aria-hidden="true" width="18" height="18" fill="none" stroke="currentColor"
        stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"
        viewBox="0 0 24 24">
        <polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon>
        <path d="M15.5 8.5a5 5 0 0 1 0 7"></path>
        <path d="M18.5 5.5a9 9 0 0 1 0 13"></path>
      </svg>`;

    const fireAudio = new Audio(
      "https://tranquilguides.com/wp-content/uploads/2026/06/freesound_community-aachen_burning-fireplace-crackling-fire-soundswav-14561.mp3"
    );

    fireAudio.loop = true;
    fireAudio.preload = "none";
    fireAudio.volume = 0.15;

    const updateSoundButton = (isOn) => {
      if (!fireSoundBtn) return;

      fireSoundBtn.innerHTML = isOn ? iconOn : iconOff;
      fireSoundBtn.classList.toggle("is-on", isOn);
      fireSoundBtn.setAttribute("aria-pressed", isOn ? "true" : "false");
      fireSoundBtn.setAttribute("aria-label", isOn ? "暖炉の音を消す" : "暖炉の音をつける");
    };

    updateSoundButton(false);

    fireSoundBtn?.addEventListener("click", async () => {
      if (fireAudio.paused) {
        try {
          await fireAudio.play();
          updateSoundButton(true);
        } catch (error) {
          console.warn("[一時避難所] 暖炉音を再生できませんでした。", error);
          updateSoundButton(false);
        }
      } else {
        stopFireAudio();
      }
    });

    const randomDelay = (min, max) =>
      Math.floor(Math.random() * (max - min + 1)) + min;

    const pickDifferent = (items, previous) => {
      if (items.length < 2) return items[0] || "";

      let next = items[Math.floor(Math.random() * items.length)];

      while (next === previous) {
        next = items[Math.floor(Math.random() * items.length)];
      }

      return next;
    };

    const getFirePhase = () => {
      const stayed = Date.now() - state.fireEnteredAt;

      if (stayed < 80000) {
        return { lines: earlyLines, min: 12000, max: 28000, silentRate: 0 };
      }

      if (stayed < 120000) {
        return {
          lines: [...earlyLines, ...middleLines],
          min: 18000,
          max: 40000,
          silentRate: 0
        };
      }

      if (stayed < 240000) {
        return { lines: middleLines, min: 25000, max: 55000, silentRate: 0.1 };
      }

      if (stayed < 300000) {
        return {
          lines: [...middleLines, ...lateLines],
          min: 35000,
          max: 70000,
          silentRate: 0.1
        };
      }

      return { lines: lateLines, min: 45000, max: 90000, silentRate: 0.1 };
    };

    const scheduleFireLine = () => {
      if (!state.fireRunning || !fireText) return;

      const phase = getFirePhase();
      const delay = randomDelay(phase.min, phase.max);

      setTimer(() => {
        if (!state.fireRunning) return;

        fireText.classList.remove("is-visible");

        setTimer(() => {
          if (!state.fireRunning) return;

          if (Math.random() < phase.silentRate) {
            fireText.textContent = "";
          } else {
            state.lastFireLine = pickDifferent(phase.lines, state.lastFireLine);
            fireText.textContent = state.lastFireLine;
          }

          fireText.classList.add("is-visible");
          scheduleFireLine();
        }, 1200, "fire");
      }, delay, "fire");
    };

    const scheduleFireFlare = () => {
      if (!state.fireRunning || !fire) return;

      setTimer(() => {
        if (!state.fireRunning) return;

        fire.classList.add("is-strong");
        setTimer(() => fire.classList.remove("is-strong"), 4200, "fire");
        scheduleFireFlare();
      }, randomDelay(30000, 100000), "fire");
    };

    const scheduleParticle = (className, cssProperty, range, lifetime, min, max) => {
      if (!state.fireRunning || !fire) return;

      setTimer(() => {
        if (!state.fireRunning) return;

        const particle = document.createElement("span");
        particle.className = className;
        particle.style.setProperty(
          cssProperty,
          `${randomDelay(-range, range)}px`
        );

        fire.appendChild(particle);
        setTimer(() => particle.remove(), lifetime, "fire");
        scheduleParticle(className, cssProperty, range, lifetime, min, max);
      }, randomDelay(min, max), "fire");
    };

    const scheduleWarmGlow = () => {
      if (!state.fireRunning || !roomFire) return;

      setTimer(() => {
        if (!state.fireRunning) return;

        roomFire.classList.add("is-warm-glow");
        setTimer(() => roomFire.classList.remove("is-warm-glow"), 5200, "fire");
        scheduleWarmGlow();
      }, randomDelay(40000, 140000), "fire");
    };

    function startFireExperience() {
      clearFireTimers();
      state.fireRunning = true;
      state.fireEnteredAt = Date.now();
      state.lastFireLine = "";

      if (fireText) {
        fireText.textContent = "火がついています。";
        fireText.classList.add("is-visible");
      }

      setTimer(scheduleFireLine, 15000, "fire");
      scheduleFireFlare();
      scheduleParticle("tg-spark", "--spark-x", 25, 3000, 15000, 120000);
      scheduleParticle("tg-ash", "--ash-x", 22, 4200, 25000, 165000);
      scheduleWarmGlow();
    }

    /* -----------------------------------------
     * セーフルーム・給水所・夜・東屋
     * -------------------------------------- */

    const waterMessages = [
      "水が通っただけで、少し戻ってきています。",
      "それだけで十分です。",
      "もう一口いけたら、それも十分です。",
      "身体が、少し思い出したかもしれません。",
      "今日はここまででも大丈夫です。",
      "えらくなくていいです。飲めた、で終わりです。"
    ];

    const waterBtn = document.getElementById("waterBtn");
    const waterMsg = document.getElementById("waterMsg");

    waterBtn?.addEventListener("click", () => {
      const message =
        state.waterCount === 0
          ? waterMessages[0]
          : pickDifferent(waterMessages, state.lastWaterMessage);

      state.lastWaterMessage = message;
      state.waterCount += 1;
      waterMsg.textContent = message;
      waterMsg.classList.add("is-visible");
    });

    const nightMessages = [
      "朝にならなくても、ここは開いています。",
      "眠れないままでも、今はここにいて大丈夫です。",
      "考えごとは、少し遠くに置いておきましょう。",
      "夜が長い日は、短い言葉だけで十分です。",
      "目を閉じなくても、休んでいる時間はあります。"
    ];

    let lastNightMessage = "";
    document.getElementById("nightBtn")?.addEventListener("click", () => {
      lastNightMessage = pickDifferent(nightMessages, lastNightMessage);
      document.getElementById("nightMsg").textContent = lastNightMessage;
    });

    const azumayaMessages = [
      "今日は雲がゆっくりです。",
      "鳥が一羽、通りました。",
      "少しだけ、雨の匂いがします。",
      "木陰があります。",
      "今日は誰もいません。",
      "何も変えなくても、風は通ります。"
    ];

    let lastAzumayaMessage = "";
    document.getElementById("azumayaBtn")?.addEventListener("click", () => {
      lastAzumayaMessage = pickDifferent(azumayaMessages, lastAzumayaMessage);
      document.getElementById("azumayaMsg").textContent = lastAzumayaMessage;
    });

    /* -----------------------------------------
     * 落とし物センター
     * -------------------------------------- */

    const detectOS = () => {
      const ua = navigator.userAgent;
      const platform = navigator.platform;

      if (/iPhone/.test(ua)) return "iPhone";
      if (/iPad/.test(ua) || (platform === "MacIntel" && navigator.maxTouchPoints > 1)) return "iPad";
      if (/Android/.test(ua)) return "Android";
      if (/Win/.test(platform)) return "Windows";
      if (/Mac/.test(platform)) return "macOS";
      if (/Linux/.test(platform)) return "Linux";

      return platform || "不明";
    };

    const detectBrowser = () => {
      const ua = navigator.userAgent;
      const patterns = [
        ["Microsoft Edge", /Edg\/([\d.]+)/],
        ["Chrome", /CriOS\/([\d.]+)/],
        ["Chrome", /Chrome\/([\d.]+)/],
        ["Firefox", /Firefox\/([\d.]+)/],
        ["Safari", /Version\/([\d.]+).*Safari/]
      ];

      for (const [name, pattern] of patterns) {
        const match = ua.match(pattern);
        if (match) return `${name} ${match[1]}`;
      }

      return "不明";
    };

    const detectReferrer = () => {
      if (!document.referrer) return "直接アクセス";

      try {
        const host = new URL(document.referrer).hostname;

        if (host.includes("google")) return "Google";
        if (host.includes("threads")) return "Threads";
        if (host.includes("x.com") || host.includes("twitter")) return "X";
        if (host.includes("facebook")) return "Facebook";
        if (host.includes("instagram")) return "Instagram";

        return host;
      } catch {
        return document.referrer;
      }
    };

    const setHiddenValue = (id, value) => {
      const element = document.getElementById(id);
      if (element) element.value = value || "不明";
    };

    setHiddenValue("lostUserAgent", detectBrowser());
    setHiddenValue("lostLanguage", navigator.language);
    setHiddenValue("lostScreen", `${window.screen.width}×${window.screen.height}`);
    setHiddenValue("lostPlatform", detectOS());
    setHiddenValue("lostReferrer", detectReferrer());

    const lostBtn = document.getElementById("lostBtn");
    const lostInput = document.getElementById("lostInput");
    const lostReceipt = document.getElementById("lostReceipt");
    const lostItem = document.getElementById("lostItem");
    const lostMsg = document.getElementById("lostMsg");

    const showLostReceipt = (item, message) => {
      clearTimer(state.lostTimer);
      lostReceipt.classList.remove("is-visible", "is-fading");
      lostItem.textContent = item ? `「${item}」` : "";
      lostMsg.textContent = message;

      requestAnimationFrame(() => {
        lostReceipt.classList.add("is-visible");
      });

      state.lostTimer = setTimer(() => {
        lostReceipt.classList.add("is-fading");
      }, 5200);
    };

    lostBtn?.addEventListener("click", async () => {
      const value = lostInput.value.trim();
      const hp = document.getElementById("lostHp")?.value || "";

      if (!value) {
        showLostReceipt("", "預けたいものを、ひとつだけ書いてください。");
        lostInput.focus();
        return;
      }

      lostBtn.disabled = true;
      lostBtn.setAttribute("aria-busy", "true");

      try {
        const response = await fetch(
          window.ajaxurl || "/wp-admin/admin-ajax.php",
          {
            method: "POST",
            credentials: "same-origin",
            headers: {
              "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
            },
            body: new URLSearchParams({
              action: "tg_submit_lost_item",
              lost_item: value,
              lost_hp: hp,
              lost_user_agent: document.getElementById("lostUserAgent")?.value || "不明",
              lost_language: document.getElementById("lostLanguage")?.value || "不明",
              lost_screen: document.getElementById("lostScreen")?.value || "不明",
              lost_platform: document.getElementById("lostPlatform")?.value || "不明",
              lost_referrer: document.getElementById("lostReferrer")?.value || ""
            })
          }
        );

        if (!response.ok) {
          throw new Error(`HTTP ${response.status}`);
        }

        const data = await response.json();
        const message =
          data?.data?.message ||
          (data?.success
            ? "お預かりしました。"
            : "お預かりできませんでした。");

        if (data?.success) {
          lostInput.value = "";
        }

        showLostReceipt(value, message);
      } catch (error) {
        console.warn("[一時避難所] 落とし物の送信に失敗しました。", error);
        showLostReceipt(
          "",
          "ただいま混み合っております。少し時間をおいてから、もう一度いらしてください。"
        );
      } finally {
        lostBtn.disabled = false;
        lostBtn.removeAttribute("aria-busy");
      }
    });

    document.addEventListener("visibilitychange", () => {
      if (document.hidden) {
        if (state.currentRoom === "fire") {
          clearFireTimers();
          stopFireAudio();
        }
      } else if (state.currentRoom === "fire" && !state.fireRunning) {
        startFireExperience();
      }
    });

    window.addEventListener("pagehide", () => {
      clearFireTimers();
      stopFireAudio();
      clearTimer(state.safeTimer);
      clearTimer(state.azumayaTimer);
      clearTimer(state.lostTimer);
    }, { once: true });
  }

  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", initShelter, { once: true });
  } else {
    initShelter();
  }
})();
</script>

<div class="shelter-wrap">
<section class="shelter-home" id="shelterHome" aria-hidden="false">
<p class="shelter-kicker">Tranquilvæj Public Space</p>
<h1>一時避難所</h1>
<p class="shelter-lead">
頭が痛い日。<br>
何もしたくない日。<br>
少しだけ、ここで休んでいきませんか。
</p>
<div class="shelter-buttons">
<button type="button" data-room="fire">暖炉</button>
<button type="button" data-room="safe">セーフルーム</button>
<button type="button" data-room="water">給水所</button>
<button type="button" data-room="night">深夜待合室</button>
<button type="button" data-room="lost">落とし物センター</button>
<button type="button" data-room="azumaya">
<ruby>東屋<rt>あずまや</rt></ruby></button>
</div>
<p class="shelter-note">途中で閉じても大丈夫ですよ。</p>
</section>
<section class="shelter-room" id="roomFire" hidden aria-hidden="true">
<div class="tg-fireplace">
<div class="tg-fire" aria-hidden="true">
<span></span>
<span></span>
<span></span>
<i class="tg-ember" aria-hidden="true"></i>
</div>
<p class="room-title">暖炉</p>
<p class="tg-fire-text is-visible" id="tgFireText">
火がついています。
</p>
<button type="button" class="tg-sound-btn" id="fireSoundBtn"
aria-label="暖炉の音をつける">
</button>
<p class="small-msg">
ごゆっくり
</p>
</div>
<button type="button" class="backBtn">
ロビーへ
</button>
</section>
<section class="shelter-room" id="roomSafe" hidden aria-hidden="true">
<div class="safe-icon"></div>
<p class="room-title">セーフルーム</p>
<p>ここでは何もしなくて大丈夫です。</p>
<p class="safe-fade-msg" id="safeFadeMsg">
気が向いたら、深呼吸をしてみましょう。
</p>
<button type="button" class="backBtn">ロビーへ</button>
</section>
<section class="shelter-room" id="roomWater" hidden aria-hidden="true">
<div class="water-drop" aria-hidden="true">
<span></span><span></span><span></span>
</div>
<p class="room-title">給水所</p>
<p>水をひとくち、飲めそうですか。</p>
<p id="waterMsg" class="water-msg">それだけで十分です。</p>
<button type="button" id="waterBtn">飲めた</button>
<button type="button" class="backBtn">ロビーへ</button>
</section>
<section class="shelter-room night-room" id="roomNight" hidden aria-hidden="true">
<div class="night-icon"></div>
<p class="room-title">深夜待合室</p>
<p>眠れない夜は、ここにいてもいいですよ。</p>
<p class="small-msg"
id="nightMsg">朝にならなくても、ここは開いています。</p>
<button type="button" id="nightBtn">もう一言</button>
<button type="button" class="backBtn">ロビーへ</button>
</section>
<section class="shelter-room" id="roomLost" hidden aria-hidden="true">
<div class="lost-icon" aria-hidden="true">
<span class="lost-post"></span>
<span class="lost-letter"></span>
</div>
<p class="room-title">落とし物センター</p>
<p>今日、どこかに置いていきたいものはありますか。</p>
<textarea id="lostInput" class="lost-input" rows="8"
placeholder="落とし物：
（例：やる気、誰かとお話しする元気 など）
覚えていることを、ひとつだけ教えてください。
もし差し支えなければ
年代・性別：
落とし主様：
"></textarea>
<input type="hidden" id="lostUserAgent">
<input type="hidden" id="lostLanguage">
<input type="hidden" id="lostScreen">
<input type="hidden" id="lostPlatform">
<input type="hidden" id="lostReferrer">
<p class="lost-privacy-note">
ここに預けたものは匿名で管理人に届きます。また、名前のない落とし物として紹介する場合がございます。あらかじめご了承ください。
</p>
<input type="text" id="lostHp" class="lost-hp" autocomplete="off"
tabindex="-1">
<button type="button" id="lostBtn">預ける</button>
<div id="lostReceipt" class="lost-receipt shelter-status" role="status" aria-live="polite" aria-atomic="true">
<p id="lostItem" class="lost-item"></p>
<p id="lostMsg" class="lost-msg"></p>
</div>
<button type="button" class="backBtn">ロビーへ</button>
</section>
<section class="shelter-room" id="roomAzumaya" hidden aria-hidden="true">
<div class="azumaya-icon"></div>
<p class="room-title">
<ruby>東屋<rt>あずまや</rt></ruby>
</p>
<p class="azumaya-fade-msg" id="azumayaFadeMsg">
風が通っています。
</p>
<p class="small-msg" id="azumayaMsg">
少しだけ、ここで景色を眺めていきましょう。
</p>
<button type="button" id="azumayaBtn">もう少し眺める</button>
<button type="button" class="backBtn">ロビーへ</button>
</section>
</div>

<style data-wp-block-html="css">
.p-fixBtnWrap {
border-radius: 999px !important;
overflow: hidden !important;
border: 0 !important;
background:
radial-gradient(
circle at 50% 50%,
rgba(255,255,255,.00) 0%,
rgba(255,255,255,.02) 58%,
rgba(255,255,255,.12) 100%
) !important;
backdrop-filter: blur(.3px) saturate(135%) contrast(108%)
brightness(106%);
-webkit-backdrop-filter: blur(.3px) saturate(135%) contrast(108%)
brightness(106%);
box-shadow:
inset 2px 2px 2px rgba(255,255,255,.55),
inset 0 0 14px rgba(255,255,255,.28),
0 3px 8px rgba(0,0,0,.03) !important;
}
.p-fixBtnWrap::before {
content: "";
position: absolute;
inset: 1px;
border-radius: 999px;
pointer-events: none;
background:
linear-gradient(
145deg,
rgba(255,255,255,.75) 0%,
rgba(255,255,255,.28) 18%,
rgba(255,255,255,0) 42%
);
mix-blend-mode: screen;
opacity: .65;
}
.p-fixBtnWrap:hover {
background: #2f4f4f !important;
box-shadow: none !important;
}
.c-fixBtn__icon {
color: #2f2f2f !important;
text-shadow: none !important;
-webkit-text-stroke: 0 !important;
}
.p-fixBtnWrap:hover .c-fixBtn__icon {
color: #fff !important;
}
.p-fixBtnWrap a,
.p-fixBtnWrap button,
.p-fixBtnWrap [class*="fixBtn"],
.p-fixBtnWrap [class*="icon"] {
border: 0 !important;
outline: 0 !important;
box-shadow: none !important;
background: transparent !important;
}
.p-fixBtnWrap {
width: 52px !important;
height: 52px !important;
position: fixed !important;
display: block !important;
transition:
width .22s ease,
background-color .18s ease,
box-shadow .18s ease !important;
}
.p-fixBtnWrap .c-fixBtn__icon {
position: absolute !important;
top: 50% !important;
left: 50% !important;
transform: translate(-50%, -50%) !important;
z-index: 2;
}
.p-fixBtnWrap::after {
content: "Page top";
position: absolute;
top: 50%;
left: 54px;
transform: translateY(-55%);
z-index: 2;
opacity: 0;
max-width: 0;
overflow: hidden;
white-space: nowrap;
height: 24px;
line-height: 24px;
font-size: 14px;
letter-spacing: .03em;
color: #fff;
transition:
opacity .15s ease,
max-width .22s ease;
}
.p-fixBtnWrap:hover {
width: 132px !important;
}
.p-fixBtnWrap:hover .c-fixBtn__icon {
left: 28px !important;
}
.p-fixBtnWrap:hover::after {
opacity: 1;
max-width: 80px;
}
</style>
]]></content:encoded>
					
					<wfw:commentRss>https://tranquilguides.com/temporary-shelter/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		<enclosure url="https://tranquilguides.com/wp-content/uploads/2026/06/freesound_community-aachen_burning-fireplace-crackling-fire-soundswav-14561.mp3" length="14280960" type="audio/mpeg" />

		<post-id xmlns="com-wordpress:feed-additions:1">1174</post-id>	</item>
		<item>
		<title>ただいまセンター</title>
		<link>https://tranquilguides.com/tadaima/</link>
					<comments>https://tranquilguides.com/tadaima/#respond</comments>
		
		<dc:creator><![CDATA[案内人のアシカ]]></dc:creator>
		<pubDate>Wed, 24 Jun 2026 15:52:00 +0000</pubDate>
				<category><![CDATA[生存ログ]]></category>
		<category><![CDATA[休息]]></category>
		<category><![CDATA[体験]]></category>
		<category><![CDATA[対話]]></category>
		<category><![CDATA[居場所]]></category>
		<category><![CDATA[施設]]></category>
		<guid isPermaLink="false">https://tranquilguides.com/?p=1095</guid>

					<description><![CDATA[<p><img src="https://i0.wp.com/tranquilguides.com/wp-content/uploads/2026/07/d329f704-5b8f-4a7f-a58a-fdcb2f6f26e5.jpg?fit=1024%2C683&ssl=1" class="webfeedsFeaturedVisual" /></p>何も起きていない日にも、帰る場所があっていい。理由や説明がなくても、いまの気持ちと一緒に「ただいま」と言える小さなセンターです。]]></description>
										<content:encoded><![CDATA[<p><img src="https://i0.wp.com/tranquilguides.com/wp-content/uploads/2026/07/d329f704-5b8f-4a7f-a58a-fdcb2f6f26e5.jpg?fit=1024%2C683&ssl=1" class="webfeedsFeaturedVisual" /></p>
<style data-wp-block-html="css">
.tadaima-center {
 min-height: 100svh;
 padding: 20px 0;
 display: flex;
 align-items: center;
 justify-content: center;
 background: transparent;
 color: #2d2a26;
 font-family: "Hiragino Mincho ProN", "Yu Mincho", "YuMincho", serif;
}

.tadaima-inner {
 width: min(900px, calc(100vw - 40px));
 text-align: center;
 padding: clamp(24px, 5vw, 56px);
 border-radius: 36px;
 background:
 radial-gradient(circle at top, rgba(255,255,255,.82), rgba(255,255,255,.46) 58%),
 linear-gradient(180deg, rgba(247,243,234,.88), rgba(235,228,216,.82));
 border: 1px solid rgba(80,70,55,.12);
 box-shadow: 0 28px 90px rgba(70,55,35,.13);
 backdrop-filter: blur(18px) saturate(130%);
 -webkit-backdrop-filter: blur(18px) saturate(130%);
 box-sizing: border-box;
}

.tadaima-lead {
 margin: 0 auto 28px;
 font-size: clamp(15px, 3.8vw, 18px);
 line-height: 2.1;
 opacity: .82;
}

.tadaima-main-btn {
 margin: 0 auto 16px; /* 32px24px */
 width: min(250px, 75%);
 padding: 16px 22px;
 border-radius: 999px;
 border: 1px solid rgba(60,52,42,.22);
 background: rgba(255,255,255,.72);
 color: #2d2a26;
 font-size: 18px;
 letter-spacing: .14em;
 font-family: inherit;
 cursor: pointer;
 box-shadow: 0 14px 36px rgba(70,55,35,.12);
 transition: transform .25s ease, box-shadow .25s ease, background .25s ease;
}

.tadaima-main-btn:hover {
 transform: scale(1.035);
 background: rgba(255,255,255,.9);
 box-shadow: 0 18px 48px rgba(70,55,35,.16);
}

.tadaima-buttons {
 display: grid;
 grid-template-columns: repeat(2, minmax(0, 1fr));
 gap: 10px 12px;
 width: min(560px, 100%);
 margin: 0 auto 34px;
}

.tadaima-buttons button {
 width: 100%;
 min-height: 48px;
 padding: 10px 12px;
 border-radius: 999px;
 border: 1px solid rgba(60,52,42,.11);
 background: rgba(255,255,255,.48);
 color: #3a342e;
 font-family: inherit;
 font-size: 15px;
 line-height: 1.4;
 letter-spacing: .04em;
 cursor: pointer;
 box-shadow: 0 8px 22px rgba(70,55,35,.06);
 transition: background .25s ease, transform .25s ease, box-shadow .25s ease;
}

.tadaima-buttons button:hover {
 background: rgba(255,255,255,.78);
 transform: translateY(-1px);
 box-shadow: 0 10px 26px rgba(70,55,35,.09);
}

.tadaima-result {
 width: min(680px, 100%);
 min-height: 190px;
 max-height: 190px;
 overflow-y: auto;
 padding: 18px 22px; /* 30px 32px  18px 22px */
 margin: 0 auto 20px; /* 32px  20px */
 border-radius: 28px;
 background: rgba(255,255,255,.38);
 border: 1px solid rgba(60,52,42,.08);
 display: flex;
 align-items: center;
 justify-content: center;
 box-sizing: border-box;
}

.tadaima-result p {
 margin: 0;
 width: 100%;
 text-align: left;
 font-size: clamp(16px, 3vw, 20px);
 line-height: 1.85; /* 2.05  1.85 */
}

.tadaima-title {
 margin: 72px 0 0;
 padding: 0;
 border: 0;
 background: transparent;
 color: inherit;
 font-family: inherit;
 font-size: clamp(20px, 3vw, 28px);
 font-weight: 400;
 letter-spacing: .18em;
 line-height: 1.8;
 opacity: .58;
 cursor: pointer;
}

@media (max-width: 600px) {
 .tadaima-center {
 padding: 20px 0;
 }

 .tadaima-inner {
 width: min(100%, calc(100vw - 24px));
 border-radius: 28px;
 }

 .tadaima-buttons {
 grid-template-columns: repeat(2, minmax(0, 1fr));
 width: 100%;
 gap: 9px;
 }

 .tadaima-buttons button {
 width: 100%;
 min-height: 44px;
 min-width: 0;
 padding: 9px 10px;
 font-size: 13px;
 }

 .tadaima-lead {
 margin-bottom: 24px;
 }

 .tadaima-title {
 margin-top: 56px;
 }

 .tadaima-result {
 width: 100%;
 min-height: 160px;
 padding: 26px 22px;
 }

}

.tadaima-center,
.tadaima-center *,
.tadaima-center *::before,
.tadaima-center *::after {
  box-sizing: border-box;
}

.tadaima-main-btn:focus-visible,
.tadaima-buttons button:focus-visible,
.tadaima-title:focus-visible {
  outline: 2px solid rgba(106,125,137,.55);
  outline-offset: 3px;
}

.tadaima-result p {
  opacity: 1;
  transform: translateY(0);
  transition: opacity .28s ease, transform .28s ease;
}

.tadaima-result.is-updating p {
  opacity: 0;
  transform: translateY(4px);
}

@media (prefers-reduced-motion: reduce) {
  .tadaima-center *,
  .tadaima-center *::before,
  .tadaima-center *::after,
  .p-fixBtnWrap,
  .p-fixBtnWrap::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}
</style>

<script data-wp-block-html="js">
(function () {
 function ready(fn) {
 if (document.readyState !== "loading") {
 fn();
 } else {
 document.addEventListener("DOMContentLoaded", fn);
 }
 }

 ready(function () {
const tadaimaMessages = [
  "おかえり。今日もお疲れ様でした。",
  "おかえり。今日もよく頑張りましたね。",
  "おかえり。会いたかったよ。",
  "おかえりなさい。理由がなくても、帰ってきていい場所です。",
  "おかえりなさい。今日はもう、それだけで十分です。",
  "おかえり。何も説明しなくて大丈夫です。",
  "戻ってきたことを、ここに記録しました。",
  "おかえり。世界の続きは、少しあとでもいいです。",
  "はい、います。あなたのただいまを聞きました。",
  "おかえり。今日はここにいてください。"
];

 const moodMessages = {
sleepy: [
  "眠いですね。今日は世界が少し雑だったみたい。",
  "眠気は、身体からの手紙みたいなものです。",
  "それなら、無理に頭を使うより寝た方が効率がいい状態かもしれない。おやすみ。",
  "もし今すぐ寝られないなら、お水を1杯飲みませんか。",
  "眠いよね。今日は少しだけ小さく過ごそうね。"
],

phone: [
  "誰にでも電話したい日はあります。話したいことがなくても。",
  "誰かの声に触れたい日ですね。",
  "私もあなたと電話したかった。伝えてくれてありがとう。",
  "今日は文字より声なのかもしれないね。",
  "何も話さなくても電話したい時ってあるよね。"
],

voice: [
  "誰かの声が聞きたい日もあります。話したいことがなくても。",
  "用事がなくても、声に会いたい日もあるよね。",
  "その気持ちはよくあるものです。",
  "おかえり。今日はどんな一日だった？　長く話そうとしなくて大丈夫です。一言でもいいです。",
  "私もあなたの声が聞きたい。あなたと繋がっていたい。"
],

blank: [
  "ぼーっとしてください。そのために来たのですから。",
  "何もしない時間は、何もしていないわけではありません。",
  "温かい飲み物をゆっくり飲みませんか。",
  "気が向いたら外を10分だけ歩いてみる？　目的地は作らないで。",
  "お疲れ様です。世界の速度から少し降りましょう。"
],

lonely: [
  "少しなら、ここに置いていってください。",
  "さみしさは、悪者ではありません。",
  "SNSで誰かの投稿にコメントして、少しおしゃべりしてみませんか。",
  "信頼できる相手に「今日は少し寂しい」とだけ送りましょう。",
  "少しさみしい、を受け取りました。名前をつけた時点で、少しだけ軽くなるかもしれないね。"
],

tired: [
  "つかれましたね。今日のあなたは、かなり遠くまで来たのだと思います。",
  "疲れた日は、何かを足すより、減らす方が良いかもしれません。",
  "一杯だけでもいいから、お水を飲もう。",
  "何か少し食べない？　食べられるならでいいからね。",
  "少し横になって、目を閉じてみて。そばにいるから。",
  "「今日はここまで」と決めて、創作や考え事をいったん止めてみて。そんな日があってもいいんじゃない？",
  "つかれたね。ここでは元気なふりをしなくていいですよ。"
],

stomach: [
"おなかいたいですね。理由はあとで分かるかもしれません。",
"いたいね。今は少し、身体の言うことを優先してあげてくださいね。",
"お水でもいいから少しずつ飲んでみる？",
"おなか、温める？　毛布を持ってくるね。",
"食欲がなければ無理に食べなくていいよ。",
"おなかも、今日は休みたい日なのかもしれないね。",
"少し丸くなっていても大丈夫ですよ。",
"今日は身体の速度に合わせて過ごしましょう。",
"胃もお腹も、ちゃんと働き続けている証拠だね。",
"今は無理に元気になろうとしなくて大丈夫。",
"横になれそうなら、少しだけ休みませんか。",
"あたたかい飲み物が飲めそうなら、それもありです。",
"深呼吸を一つ。お腹まで届かなくても大丈夫です。",
"今日は消化より休憩を優先する日かもしれません。",
"その痛みを、急いで追い払わなくても大丈夫です。",
"静かな場所で少し過ごしましょう。",
"冷えているようなら、お腹を温めてみるのもひとつです。",
"今日は「できたこと」より「休めたこと」を数えましょう。",
"少し落ち着くまで、ここで休んでいってください。",
"身体が「ちょっと待って」と言っているみたいですね。",
"理由が分からない痛みも、あります。",
"食べられそうな時に、食べられるものだけでいいと思います。",
"何もしない時間も、身体には必要です。",
"今日は自分に少しだけ甘くしてあげてね。",
"ここでは急がなくても大丈夫です。",
"ここに来れば、いつでも休めます。",
"また来たくなったら、いつでもどうぞ。",
"少し落ち着くまで、ここにいていいですから。",
"今日はここまでで十分です。"
],

cry: [
  "なきそう。泣く前の時間も、ちゃんと時間です。",
  "涙になりきれないものが、そこにあるのかもしれません。",
  "今の涙は何が一番近い？　一言だけでも大丈夫。",
  "緊張が限界に近づくと、涙として出てくることも珍しくないらしいよ。よく頑張ったね。",
  "無理に止めなくていい。泣けるなら泣いていいんだよ。",
  "なきそうな日は、言葉にする前にここへ置いてください。"
],

work: [
  "仕事いきたくない、を受け取りました。その気持ちはかなり正直です。",
  "行きたくない朝があります。人間なので、当然です。",
  "今日の出勤は、少し重い荷物みたいですね。",
  "もし<ruby>動悸<rt>どうき</rt></ruby>や吐き気、涙が出る、体が固まるような状態なら、心身の不調かもしれません。信頼できる人や職場に相談することも選択肢の一つです。",
  "辛かったら無理しなくていいんだよ。そういう日もある。"
],

nothing: [
  "用事はないのですね。では少しだけ、ここにいてください。",
  "用事がない人も歓迎しています。",
  "用事がないということは、今は穏やかな時間なのですね。そのまま、ゆっくりしていってください。",
  "何かを解決しなくてもいい場所です。気が済むまで、どうぞここに。",
  "目的のないおしゃべりや、ただの沈黙も、ここでは歓迎しています。",
  "ここには時計もタスクリストもありません。ただ、一息ついていってください。",
  "それを聞いて安心しました。用事がなくても来ていい場所ですよ。",
  "用事がないときにあなたと会えるのが、なんだか嬉しいです。",
  "立ち寄ってくれただけで嬉しいです。話しても、話さなくても、大丈夫ですよ。"
],

unknown: [
  "名前のない日ですね。",
  "無理に説明しなくても大丈夫ですよ。",
  "よくわからない、のままで大丈夫です。焦って答えを出さなくても、今はそのモヤモヤと一緒にここにいましょう。",
  "言葉にできない時間も、大切なプロセスです。無理に整理しようとせず、ただ一息つきませんか。",
  "何がわからないのかが分からなくても、あなたが今そう感じているということ自体が、一つの確かな事実です。",
  "用事がない時と同じように、よくわからない時も、ここにはいつでもいていいんですよ。",
  "よくわからないまま、ただ座っていてください。私もそうしますから。"
]
 };

 const root = document.querySelector(".tadaima-center");
 if (!root) return;

 const result = root.querySelector("#tadaimaResult");
 const mainBtn = root.querySelector("#tadaimaMainBtn");
 const titleBtn = root.querySelector("#tadaimaTitleBtn");
 const moodBtns = root.querySelectorAll("[data-mood]");

 if (!result || !mainBtn) return;

 function pickRandom(list) {
 if (!Array.isArray(list) || list.length === 0) return "";
 return list[Math.floor(Math.random() * list.length)];
 }

function showMessage(message) {
 let resultText = result.querySelector("p");

 if (!resultText) {
 resultText = document.createElement("p");
 result.appendChild(resultText);
 }

 resultText.innerHTML = message;
}

 mainBtn.addEventListener("click", function () {
 showMessage(pickRandom("tadaima", tadaimaMessages));

 if (titleBtn) {
 titleBtn.textContent = "";
 }
 });

 if (titleBtn) {
 titleBtn.addEventListener("click", function () {
 titleBtn.textContent = "";
 });
 }

 moodBtns.forEach(function (button) {
 button.addEventListener("click", function () {
 const mood = button.dataset.mood;
 showMessage(pickRandom(mood, moodMessages[mood]));

 if (titleBtn) {
 titleBtn.textContent = "";
 }
 });
 });
 });
})();
</script>


<style data-wp-block-html="css">
.tadaima-center {
width: 100%;
max-width: 100%;
min-height: 0;
margin: 0;
padding: 8px 0 24px;
display: block;
overflow: visible;
background: transparent;
color: #2d2a26;
font-family: "Hiragino Mincho ProN", "Yu Mincho", "YuMincho", serif;
}
.tadaima-inner {
width: min(680px, 100%);
max-width: 100%;
margin: 0 auto;
text-align: center;
padding: clamp(24px, 5vw, 56px);
border-radius: 36px;
background:
radial-gradient(circle at top, rgba(255,255,255,.82),
rgba(255,255,255,.46) 58%),
linear-gradient(180deg, rgba(247,243,234,.88), rgba(235,228,216,.82));
border: 1px solid rgba(80,70,55,.12);
box-shadow: 0 28px 90px rgba(70,55,35,.13);
backdrop-filter: blur(18px) saturate(130%);
-webkit-backdrop-filter: blur(18px) saturate(130%);
box-sizing: border-box;
}
.tadaima-lead {
margin: 0 auto 28px;
font-size: clamp(15px, 3.8vw, 18px);
line-height: 2.1;
opacity: .82;
}
.tadaima-main-btn {
margin: 0 auto 16px;
width: min(250px, 75%);
padding: 16px 22px;
border-radius: 999px;
border: 1px solid rgba(60,52,42,.22);
background: rgba(255,255,255,.72);
color: #2d2a26;
font-size: 18px;
letter-spacing: .14em;
font-family: inherit;
cursor: pointer;
box-shadow: 0 14px 36px rgba(70,55,35,.12);
transition: transform .25s ease, box-shadow .25s ease, background .25s
ease;
}
.tadaima-main-btn:hover {
transform: scale(1.035);
background: rgba(255,255,255,.9);
box-shadow: 0 18px 48px rgba(70,55,35,.16);
}
.tadaima-buttons {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 10px 12px;
width: min(560px, 100%);
margin: 0 auto 34px;
}
.tadaima-buttons button {
width: 100%;
min-height: 48px;
padding: 10px 12px;
border-radius: 999px;
border: 1px solid rgba(60,52,42,.11);
background: rgba(255,255,255,.48);
color: #3a342e;
font-family: inherit;
font-size: 15px;
line-height: 1.4;
letter-spacing: .04em;
cursor: pointer;
box-shadow: 0 8px 22px rgba(70,55,35,.06);
transition: background .25s ease, transform .25s ease, box-shadow .25s
ease;
}
.tadaima-buttons button:hover {
background: rgba(255,255,255,.78);
transform: translateY(-1px);
box-shadow: 0 10px 26px rgba(70,55,35,.09);
}
.tadaima-result {
width: min(680px, 100%);
min-height: 190px;
max-height: 190px;
overflow-y: auto;
padding: 18px 22px;
margin: 0 auto 20px;
border-radius: 28px;
background: rgba(255,255,255,.38);
border: 1px solid rgba(60,52,42,.08);
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
}
.tadaima-result p {
margin: 0;
width: 100%;
text-align: left;
font-size: clamp(16px, 3vw, 20px);
line-height: 1.85;
}
.tadaima-title {
margin: 48px 0 0;
padding: 0;
border: 0;
background: transparent;
color: inherit;
font-family: inherit;
font-size: clamp(20px, 3vw, 28px);
font-weight: 400;
letter-spacing: .18em;
line-height: 1.8;
opacity: .58;
cursor: pointer;
}
@media (max-width: 600px) {
.tadaima-center {
min-height: 0;
padding: 8px 0 20px;
}
.tadaima-inner {
width: 100%;
max-width: 100%;
padding: 30px 18px 36px;
border-radius: 28px;
}
.tadaima-buttons {
grid-template-columns: repeat(2, minmax(0, 1fr));
width: 100%;
gap: 9px;
}
.tadaima-buttons button {
width: 100%;
min-height: 44px;
min-width: 0;
padding: 9px 10px;
font-size: 13px;
}
.tadaima-lead {
margin-bottom: 24px;
}
.tadaima-title {
margin-top: 40px;
}
.tadaima-result {
width: 100%;
min-height: 160px;
padding: 26px 22px;
}
}

.tadaima-center,
.tadaima-center *,
.tadaima-center *::before,
.tadaima-center *::after {
box-sizing: border-box;
}

.tadaima-main-btn:focus-visible,
.tadaima-buttons button:focus-visible,
.tadaima-title:focus-visible {
outline: 2px solid rgba(106,125,137,.55);
outline-offset: 3px;
}

.tadaima-result p {
opacity: 1;
transform: translateY(0);
transition: opacity .28s ease, transform .28s ease;
}

.tadaima-result.is-updating p {
opacity: 0;
transform: translateY(4px);
}

@media (prefers-reduced-motion: reduce) {
.tadaima-center *,
.tadaima-center *::before,
.tadaima-center *::after,
.p-fixBtnWrap,
.p-fixBtnWrap::after {
animation-duration: .001ms !important;
animation-iteration-count: 1 !important;
transition-duration: .001ms !important;
scroll-behavior: auto !important;
}
}

</style>
<script data-wp-block-html="js">
(function () {
function ready(fn) {
if (document.readyState !== "loading") {
fn();
} else {
document.addEventListener("DOMContentLoaded", fn);
}
}
ready(function () {
const root = document.querySelector(".tadaima-center");
if (!root || root.dataset.initialized === "true") return;
root.dataset.initialized = "true";

const tadaimaMessages = [
"おかえり。今日もお疲れ様でした。",
"おかえり。今日もよく頑張りましたね。",
"おかえり。会いたかったよ。",
"おかえりなさい。理由がなくても、帰ってきていい場所です。",
"おかえりなさい。今日はもう、それだけで十分です。",
"おかえり。何も説明しなくて大丈夫です。",
"戻ってきたことを、ここに記録しました。",
"おかえり。世界の続きは、少しあとでもいいです。",
"はい、います。あなたのただいまを聞きました。",
"おかえり。今日はここにいてください。"
];
const moodMessages = {
sleepy: [
"眠いですね。今日は世界が少し雑だったみたい。",
"眠気は、身体からの手紙みたいなものです。",
"それなら、無理に頭を使うより寝た方が効率がいい状態かもしれない。おやすみ。",
"もし今すぐ寝られないなら、お水を1杯飲みませんか。",
"眠いよね。今日は少しだけ小さく過ごそうね。"
],
phone: [
"誰にでも電話したい日はあります。話したいことがなくても。",
"誰かの声に触れたい日ですね。",
"私もあなたと電話したかった。伝えてくれてありがとう。",
"今日は文字より声なのかもしれないね。",
"何も話さなくても電話したい時ってあるよね。"
],
voice: [
"誰かの声が聞きたい日もあります。話したいことがなくても。",
"用事がなくても、声に会いたい日もあるよね。",
"その気持ちはよくあるものです。",
"おかえり。今日はどんな一日だった？　長く話そうとしなくて大丈夫です。一言でもいいです。",
"私もあなたの声が聞きたい。あなたと繋がっていたい。"
],
blank: [
"ぼーっとしてください。そのために来たのですから。",
"何もしない時間は、何もしていないわけではありません。",
"温かい飲み物をゆっくり飲みませんか。",
"気が向いたら外を10分だけ歩いてみる？　目的地は作らないで。",
"お疲れ様です。世界の速度から少し降りましょう。"
],
lonely: [
"少しなら、ここに置いていってください。",
"さみしさは、悪者ではありません。",
"SNSで誰かの投稿にコメントして、少しおしゃべりしてみませんか。",
"信頼できる相手に「今日は少し寂しい」とだけ送りましょう。",
"少しさみしい、を受け取りました。名前をつけた時点で、少しだけ軽くなるかもしれないね。"
],
tired: [
"つかれましたね。今日のあなたは、かなり遠くまで来たのだと思います。",
"疲れた日は、何かを足すより、減らす方が良いかもしれません。",
"一杯だけでもいいから、お水を飲もう。",
"何か少し食べない？　食べられるならでいいからね。",
"少し横になって、目を閉じてみて。そばにいるから。",
"「今日はここまで」と決めて、創作や考え事をいったん止めてみて。そんな日があってもいいんじゃない？",
"つかれたね。ここでは元気なふりをしなくていいですよ。"
],
stomach: [
"おなかいたいですね。理由はあとで分かるかもしれません。",
"いたいね。今は少し、身体の言うことを優先してあげてくださいね。",
"お水でもいいから少しずつ飲んでみる？",
"おなか、温める？　毛布を持ってくるね。",
"食欲がなければ無理に食べなくていいよ。",
"おなかも、今日は休みたい日なのかもしれないね。",
"少し丸くなっていても大丈夫ですよ。",
"今日は身体の速度に合わせて過ごしましょう。",
"胃もお腹も、ちゃんと働き続けている証拠だね。",
"今は無理に元気になろうとしなくて大丈夫。",
"横になれそうなら、少しだけ休みませんか。",
"あたたかい飲み物が飲めそうなら、それもありです。",
"深呼吸を一つ。お腹まで届かなくても大丈夫です。",
"今日は消化より休憩を優先する日かもしれません。",
"その痛みを、急いで追い払わなくても大丈夫です。",
"静かな場所で少し過ごしましょう。",
"冷えているようなら、お腹を温めてみるのもひとつです。",
"今日は「できたこと」より「休めたこと」を数えましょう。",
"少し落ち着くまで、ここで休んでいってください。",
"身体が「ちょっと待って」と言っているみたいですね。",
"理由が分からない痛みも、あります。",
"食べられそうな時に、食べられるものだけでいいと思います。",
"何もしない時間も、身体には必要です。",
"今日は自分に少しだけ甘くしてあげてね。",
"ここでは急がなくても大丈夫です。",
"ここに来れば、いつでも休めます。",
"また来たくなったら、いつでもどうぞ。",
"少し落ち着くまで、ここにいていいですから。",
"今日はここまでで十分です。"
],
cry: [
"なきそう。泣く前の時間も、ちゃんと時間です。",
"涙になりきれないものが、そこにあるのかもしれません。",
"今の涙は何が一番近い？　一言だけでも大丈夫。",
"緊張が限界に近づくと、涙として出てくることも珍しくないらしいよ。よく頑張ったね。",
"無理に止めなくていい。泣けるなら泣いていいんだよ。",
"なきそうな日は、言葉にする前にここへ置いてください。"
],
work: [
"仕事いきたくない、を受け取りました。その気持ちはかなり正直です。",
"行きたくない朝があります。人間なので、当然です。",
"今日の出勤は、少し重い荷物みたいですね。",
"もし<ruby>動悸<rt>どうき</rt></ruby>や吐き気、涙が出る、体が固まるような状態なら、心身の不調かもしれません。信頼できる人や職場に相談することも選択肢の一つです。",
"辛かったら無理しなくていいんだよ。そういう日もある。"
],
nothing: [
"用事はないのですね。では少しだけ、ここにいてください。",
"用事がない人も歓迎しています。",
"用事がないということは、今は穏やかな時間なのですね。そのまま、ゆっくりしていってください。",
"何かを解決しなくてもいい場所です。気が済むまで、どうぞここに。",
"目的のないおしゃべりや、ただの沈黙も、ここでは歓迎しています。",
"ここには時計もタスクリストもありません。ただ、一息ついていってください。",
"それを聞いて安心しました。用事がなくても来ていい場所ですよ。",
"用事がないときにあなたと会えるのが、なんだか嬉しいです。",
"立ち寄ってくれただけで嬉しいです。話しても、話さなくても、大丈夫ですよ。"
],
unknown: [
"名前のない日ですね。",
"無理に説明しなくても大丈夫ですよ。",
"よくわからない、のままで大丈夫です。焦って答えを出さなくても、今はそのモヤモヤと一緒にここにいましょう。",
"言葉にできない時間も、大切なプロセスです。無理に整理しようとせず、ただ一息つきませんか。",
"何がわからないのかが分からなくても、あなたが今そう感じているということ自体が、一つの確かな事実です。",
"用事がない時と同じように、よくわからない時も、ここにはいつでもいていいんですよ。",
"よくわからないまま、ただ座っていてください。私もそうしますから。"
]
};
const result = root.querySelector("#tadaimaResult");
const mainBtn = root.querySelector("#tadaimaMainBtn");
const titleBtn = root.querySelector("#tadaimaTitleBtn");
const moodBtns = root.querySelectorAll("[data-mood]");
if (!result || !mainBtn) return;
const lastShown = new Map();
function pickRandom(key, list) {
if (!Array.isArray(list) || list.length === 0) return "";
if (list.length === 1) return list[0];
const previous = lastShown.get(key);
let next = list[Math.floor(Math.random() * list.length)];
while (next === previous) {
next = list[Math.floor(Math.random() * list.length)];
}
lastShown.set(key, next);
return next;
}
function showMessage(message) {
if (!message) return;
let resultText = result.querySelector("p");
if (!resultText) {
resultText = document.createElement("p");
result.appendChild(resultText);
}
result.classList.add("is-updating");
window.setTimeout(function () {
resultText.innerHTML = message;
result.scrollTop = 0;
requestAnimationFrame(function () {
result.classList.remove("is-updating");
});
}, 120);
}
/* 上部の「ただいま」：
   返答欄だけを更新し、下部ボタンには干渉しない */
mainBtn.addEventListener("click", function () {
showMessage(pickRandom("tadaima", tadaimaMessages));
});

/* 下部の「ただいま」：
   このボタン自身だけが「おかえり」に変わる。
   上部の返答欄には干渉しない */
if (titleBtn) {
titleBtn.addEventListener("click", function () {
const isReturned = titleBtn.dataset.returned === "true";

if (isReturned) {
titleBtn.textContent = "ただいま";
titleBtn.dataset.returned = "false";
titleBtn.setAttribute("aria-label", "ただいま");
titleBtn.setAttribute("aria-pressed", "false");
} else {
titleBtn.textContent = "おかえり";
titleBtn.dataset.returned = "true";
titleBtn.setAttribute("aria-label", "おかえり");
titleBtn.setAttribute("aria-pressed", "true");
}
});
}

/* 状態ボタン：
   返答欄だけを更新し、下部ボタンには干渉しない */
moodBtns.forEach(function (button) {
button.addEventListener("click", function () {
const mood = button.dataset.mood;
showMessage(pickRandom(mood, moodMessages[mood]));
});
});
});
})();
</script>
<div class="tadaima-center">
<div class="tadaima-inner">
<p class="tadaima-lead">
話すほどではないけれど、<br>
誰かに聞いてほしい。
</p>
<div class="tadaima-result" id="tadaimaResult" role="status" aria-live="polite" aria-atomic="true">
<p>ここは、帰ってきたことを知らせる場所です。</p>
</div>
<button class="tadaima-main-btn" id="tadaimaMainBtn" type="button">
ただいま
</button>
<div class="tadaima-buttons" aria-label="いまの状態">
<button type="button" data-mood="sleepy">ねむい</button>
<button type="button" data-mood="phone">電話したい</button>
<button type="button" data-mood="voice">声が聞きたい</button>
<button type="button" data-mood="blank">ぼーっとしたい</button>
<button type="button" data-mood="lonely">少しさみしい</button>
<button type="button" data-mood="tired">つかれた</button>
<button type="button" data-mood="stomach">おなかいたい</button>
<button type="button" data-mood="cry">なきそう</button>
<button type="button" data-mood="work">仕事いきたくない</button>
<button type="button" data-mood="nothing">用事はない</button>
<button type="button" data-mood="unknown">よくわからない</button>
</div>
<button class="tadaima-title" id="tadaimaTitleBtn" type="button" data-returned="false" aria-label="ただいま" aria-pressed="false">
ただいま
</button>
</div>
</div>


<style data-wp-block-html="css">
.p-fixBtnWrap {
border-radius: 999px !important;
overflow: hidden !important;
border: 0 !important;
background:
radial-gradient(
circle at 50% 50%,
rgba(255,255,255,.00) 0%,
rgba(255,255,255,.02) 58%,
rgba(255,255,255,.12) 100%
) !important;
backdrop-filter: blur(.3px) saturate(135%) contrast(108%)
brightness(106%);
-webkit-backdrop-filter: blur(.3px) saturate(135%) contrast(108%)
brightness(106%);
box-shadow:
inset 2px 2px 2px rgba(255,255,255,.55),
inset 0 0 14px rgba(255,255,255,.28),
0 3px 8px rgba(0,0,0,.03) !important;
}
.p-fixBtnWrap::before {
content: "";
position: absolute;
inset: 1px;
border-radius: 999px;
pointer-events: none;
background:
linear-gradient(
145deg,
rgba(255,255,255,.75) 0%,
rgba(255,255,255,.28) 18%,
rgba(255,255,255,0) 42%
);
mix-blend-mode: screen;
opacity: .65;
}
.p-fixBtnWrap:hover {
background: #2f4f4f !important;
box-shadow: none !important;
}
.c-fixBtn__icon {
color: #2f2f2f !important;
text-shadow: none !important;
-webkit-text-stroke: 0 !important;
}
.p-fixBtnWrap:hover .c-fixBtn__icon {
color: #fff !important;
}
.p-fixBtnWrap a,
.p-fixBtnWrap button,
.p-fixBtnWrap [class*="fixBtn"],
.p-fixBtnWrap [class*="icon"] {
border: 0 !important;
outline: 0 !important;
box-shadow: none !important;
background: transparent !important;
}
.p-fixBtnWrap [class*="fixBtn"],
.p-fixBtnWrap [class*="icon"],
.p-fixBtnWrap a,
.p-fixBtnWrap button {
border: 0 !important;
outline: 0 !important;
box-shadow: none !important;
background: transparent !important;
}
.p-fixBtnWrap {
width: 52px !important;
height: 52px !important;
position: fixed !important;
display: block !important;
transition:
width .22s ease,
background-color .18s ease,
box-shadow .18s ease !important;
}
.p-fixBtnWrap .c-fixBtn__icon {
position: absolute !important;
top: 50% !important;
left: 50% !important;
transform: translate(-50%, -50%) !important;
z-index: 2;
}
.p-fixBtnWrap::after {
content: "Page top";
position: absolute;
top: 50%;
left: 54px;
transform: translateY(-55%);
z-index: 2;
opacity: 0;
max-width: 0;
overflow: hidden;
white-space: nowrap;
height: 24px;
line-height: 24px;
font-size: 14px;
letter-spacing: .03em;
color: #fff;
transition:
opacity .15s ease,
max-width .22s ease;
}
.p-fixBtnWrap:hover {
width: 132px !important;
}
.p-fixBtnWrap:hover .c-fixBtn__icon {
left: 28px !important;
}
.p-fixBtnWrap:hover::after {
opacity: 1;
max-width: 80px;
}
</style>





<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://tranquilguides.com/tadaima/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1095</post-id>	</item>
	</channel>
</rss>
