/* ============================================================
   studio.INTERVAL — v2 FLOW engine
   One persistent tile per project; every mode is just a target
   geometry. CSS transitions morph between galerie / raster /
   index / zeit / graph. Raum 3D crossfades to WebGL.
   ============================================================ */

.flowwrap{ position:relative; }
.flow{ position:relative; width:100%; }

/* the persistent project tile */
.fc{
  position:absolute; top:0; left:0; display:block;
  transition:left .82s cubic-bezier(.5,.05,.15,1),
             top .82s cubic-bezier(.5,.05,.15,1),
             width .82s cubic-bezier(.5,.05,.15,1),
             height .82s cubic-bezier(.5,.05,.15,1),
             opacity .5s ease;
  will-change:left,top,width,height;
}
.fc__img{ position:relative; display:block; width:100%; height:100%; overflow:hidden; background:#fafafa;
  border-radius:0%;   /* %-based so it can morph to 50% (a circle) without length↔% snap */
  transition:opacity .5s ease, border-radius .82s ease; }
.fc__img img{ width:100%; height:100%; object-fit:cover; display:block; }
.fc__massing{ position:absolute; inset:0; opacity:0; transition:opacity .5s ease; pointer-events:none; }
.fc.models .fc__img img{ opacity:0; }
.fc.models .fc__massing{ opacity:1; }
/* 3D models are freestanding objects on the page — never a boxed container */
.fc.models .fc__img{ overflow:visible; border-radius:0; background:transparent; box-shadow:none; }
.fc.models .fc__massing{ overflow:visible; inset:-25% -20%; }
.fc.models .massing{ overflow:visible; background:transparent; }
.fc.models .massing__shadow{ opacity:.45; }

/* caption: number + title (hover only in image modes) */
.fc__cap{ position:absolute; left:0; right:0; top:100%; margin-top:9px;
  display:flex; justify-content:space-between; gap:12px; align-items:baseline;
  opacity:0; transition:opacity .3s ease; pointer-events:none; }
.fc:hover .fc__cap{ opacity:1; }
.fc__t{ font-size:14px; font-weight:500; letter-spacing:-0.01em; color:var(--ink); }
.fc__no{ font-family:var(--mono); font-size:12px; color:var(--grey); margin-right:8px; }
.fc__m{ font-family:var(--mono); font-size:12px; color:var(--grey); white-space:nowrap; }
.fc:hover .fc__t{ color:var(--accent); }

/* ---- INDEX mode: tiles become rows, image hidden, text shown ---- */
.flow.is-index .fc .fc__img{ opacity:0; }
.flow.is-index .fc .fc__cap{ opacity:1; top:0; margin-top:0; height:100%; align-items:center;
  border-bottom:1px solid var(--line); }
.flow.is-index .fc{ }
.flow.is-index .fc__t{ font-size:clamp(16px,1.5vw,19px); }
.flow.is-index .fc:hover{ padding-left:0; }
.flow.is-index .fc .ix-extra{ opacity:1; }
.ix-extra{ font-family:var(--mono); font-size:12px; color:var(--grey); opacity:0; transition:opacity .4s; }

/* in graph + zeit, captions are smaller and hover-only */
.flow.is-graph .fc__cap, .flow.is-zeit .fc__cap{ justify-content:flex-start; }

/* ---- overlay: graph connector lines ---- */
.flow-lines{ position:absolute; inset:0; width:100%; height:100%; overflow:visible; pointer-events:none;
  opacity:0; transition:opacity .6s ease; z-index:0; }
.flow.is-graph .flow-lines, .flow.is-raum .flow-lines, .flow.is-zeit .flow-lines{ opacity:1; }
.flow-lines line{ stroke:var(--ink); stroke-width:1; opacity:.16; }
.flow-lines line.hot{ stroke:var(--accent); opacity:.85; stroke-width:1.4; }
.flow-lines line.tlc{ stroke:var(--line); stroke-width:1; opacity:.9; }
.flow-lines line.dim{ opacity:.05; }

/* ---- graph + raum: nodes become circles (radius driven inline by JS) ---- */
.flow.is-graph .fc, .flow.is-raum .fc{ z-index:2; }
.flow.is-graph .fc{ cursor:grab; }
.flow.is-graph.graph-dragging .fc{ cursor:grabbing; }
/* hover grows the node back to full size; image stays centred on the node */
.flow.is-graph .fc.hot{ transform:scale(1.34); z-index:60; }
.flow.is-graph.has-hot .fc:not(.hot):not(.rel){ opacity:.2; }
.flow.is-graph .fc.q-out{ opacity:.12 !important; }
.flow.is-graph .fc__img, .flow.is-raum .fc__img{ overflow:hidden; box-shadow:none; background:transparent; }
.flow.is-graph .fc__cap, .flow.is-raum .fc__cap{ top:auto; bottom:-26px; justify-content:center; }
.flow.is-raum{ cursor:grab; touch-action:none; }
.flow.is-raum:active{ cursor:grabbing; }

/* ---- 3D models in graph/raum: real floating objects, NOT clipped ---- */
.flow.is-graph .fc.models .fc__img, .flow.is-raum .fc.models .fc__img{
  overflow:visible; border-radius:0; background:transparent; box-shadow:none; }
.flow.is-graph .fc.models .fc__massing, .flow.is-raum .fc.models .fc__massing{
  border-radius:0; overflow:visible; inset:-40% -30%; }
.flow.is-graph .fc.models .massing, .flow.is-raum .fc.models .massing{
  overflow:visible; background:transparent; }
.flow.is-graph .fc.models .massing__shadow, .flow.is-raum .fc.models .massing__shadow{ opacity:.5; }

/* ---- raster: drawn plan grid with A/B/C + 1/2/3 axes ---- */
.flow.is-raster .fc{ z-index:1; }
.rgrid{ position:absolute; left:0; top:0; pointer-events:none; z-index:0; overflow:visible; }
.rgrid line{ stroke:var(--line); stroke-width:1;
  stroke-dasharray:var(--len); stroke-dashoffset:var(--len);
  animation:rdraw .55s cubic-bezier(.45,.55,.15,1) forwards; animation-delay:var(--d,0s); }
@keyframes rdraw{ to{ stroke-dashoffset:0; } }
.rgrid text{ font-family:var(--mono); font-size:11px; letter-spacing:0.04em; fill:var(--grey);
  opacity:0; animation:rfade .45s ease forwards; animation-delay:var(--d,0s); }
@keyframes rfade{ to{ opacity:1; } }
@media (prefers-reduced-motion: reduce){
  .rgrid line{ stroke-dashoffset:0; animation:none; }
  .rgrid text{ opacity:1; animation:none; }
}

/* ---- overlay: timeline axis ---- */
.flow-axis{ position:absolute; top:0; bottom:0; left:50%; width:1px; background:var(--ink);
  opacity:0; transition:opacity .6s ease; }
.flow.is-zeit .flow-axis{ opacity:1; }
.flow-year{ position:absolute; transform:translate(-50%,-50%); background:#fff; padding:3px 10px;
  font-family:var(--mono); font-size:12px; letter-spacing:0.04em; color:var(--accent-deep);
  opacity:0; transition:opacity .5s ease; z-index:3; }
.flow.is-zeit .flow-year{ opacity:1; }
.flow-dot{ position:absolute; transform:translate(-50%,-50%); width:7px; height:7px; border-radius:50%;
  background:var(--ink); opacity:0; transition:opacity .5s ease, background .25s; z-index:3; }
.flow.is-zeit .flow-dot{ opacity:1; }
/* horizontal timeline becomes a sideways-scrolling strip */
.flow.is-zeit-h{ overflow-x:auto; overflow-y:hidden; scrollbar-width:thin; }
.flow.is-zeit-h .fc__cap{ position:absolute; }

/* ---- subtle timeline flip button ---- */
.tl-flip{ display:none; align-items:center; gap:6px; margin-left:14px; padding:3px 8px;
  background:none; border:none; cursor:pointer; color:var(--grey);
  font-family:var(--mono); font-size:10.5px; letter-spacing:0.08em; text-transform:uppercase;
  opacity:.55; transition:opacity .2s, color .2s; }
.tl-flip:hover{ opacity:1; color:var(--accent); }
.tl-flip svg{ width:16px; height:16px; }
.flow-wrap-zeit .tl-flip{ display:inline-flex; }
.v2 .proj-sub.zeit-on .tl-flip{ display:inline-flex; }

/* ---- raum layer (legacy WebGL crossfade — no longer used) ---- */
.flow-raum{ display:none; }

/* ---- zeit hover info: reveals details about each piece ---- */
.fc__info{ position:absolute; left:0; right:0; bottom:0; z-index:4; padding:12px 13px;
  display:none; flex-direction:column; gap:5px;
  background:color-mix(in srgb, #ffffff 92%, transparent);
  -webkit-backdrop-filter:blur(5px); backdrop-filter:blur(5px);
  opacity:0; transform:translateY(8px); transition:opacity .26s ease, transform .26s ease; pointer-events:none; }
.flow.is-zeit .fc__info{ display:flex; }
.flow.is-zeit .fc:hover .fc__info{ opacity:1; transform:none; }
.fc__info-t{ font-family:var(--mono); font-size:10.5px; letter-spacing:0.04em; color:var(--accent); }
.fc__info-d{ font-size:12px; line-height:1.42; color:var(--ink); text-wrap:pretty;
  display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden; }
.fc__info-m{ font-family:var(--mono); font-size:10px; letter-spacing:0.03em; color:var(--grey); }

/* ---- the axis line physically rotating ---- */
.flow.zeit-spinning .flow-dot,
.flow.zeit-spinning .flow-year{ opacity:0 !important; }
.flow.zeit-spinning .flow-lines{ opacity:0 !important; }
.flow.zeit-spinning .flow-axis{ z-index:5; background:var(--accent); }

/* 90° rotate: fade tiles fully out, snap to the new layout, fade back in
   (opacity-only transition makes the position change instant = no nervous move) */
.flow.zeit-fading .fc{ opacity:0 !important; transition:opacity .3s ease !important; }
/* during the rotate, the axis line + dots + years + connectors fade too,
   then the axis is redrawn growing from the centre of the screen */
.flow.zeit-chrome-out .flow-axis,
.flow.zeit-chrome-out .flow-dot,
.flow.zeit-chrome-out .flow-year,
.flow.zeit-chrome-out .flow-lines{ opacity:0 !important; transition:opacity .3s ease !important; }

/* ---- zeit entrance: line draws from the centre out, then dots, then years ---- */
.flow.zeit-in .flow-axis{ animation:axisGrowV .6s cubic-bezier(.5,.05,.15,1) both; }
.flow.zeit-in.is-zeit-h .flow-axis{ animation:axisGrowH .6s cubic-bezier(.5,.05,.15,1) both; }
@keyframes axisGrowV{ from{ transform:scaleY(0); } to{ transform:scaleY(1); } }
@keyframes axisGrowH{ from{ transform:scaleX(0); } to{ transform:scaleX(1); } }
.flow.zeit-in .flow-dot{ animation:zeitPop .4s ease both; animation-delay:calc(.52s + var(--di,0) * .035s); }
.flow.zeit-in .flow-year{ animation:zeitPop .45s ease both; animation-delay:calc(.66s + var(--di,0) * .035s); }
.flow.zeit-in .flow-lines{ opacity:0; animation:zeitFadeIn .5s ease both; animation-delay:.8s; }
@keyframes zeitPop{ from{ opacity:0; transform:translate(-50%,-50%) scale(.4); } to{ opacity:1; transform:translate(-50%,-50%) scale(1); } }
@keyframes zeitFadeIn{ to{ opacity:1; } }

/* rotate commit: dots + years pop in, axis already drawn (no axis grow) */
.flow.zeit-in-dots .flow-dot{ animation:zeitPop .4s ease both; animation-delay:calc(.06s + var(--di,0) * .035s); }
.flow.zeit-in-dots .flow-year{ animation:zeitPop .45s ease both; animation-delay:calc(.2s + var(--di,0) * .035s); }
.flow.zeit-in-dots .flow-lines{ opacity:0; animation:zeitFadeIn .5s ease both; animation-delay:.34s; }

/* while pinch-zooming, snap (no per-tile transition lag) */
.flow.zeit-zooming .fc,
.flow.zeit-zooming .flow-dot,
.flow.zeit-zooming .flow-year{ transition:none !important; }

@media(prefers-reduced-motion:reduce){
  .flow.zeit-in .flow-axis, .flow.zeit-in .flow-dot, .flow.zeit-in .flow-year, .flow.zeit-in .flow-lines,
  .flow.zeit-in-dots .flow-dot, .flow.zeit-in-dots .flow-year, .flow.zeit-in-dots .flow-lines{ animation:none; }
}

/* sublabel under the switch */
.flow-note{ font-family:var(--mono); font-size:12.5px; color:var(--grey); }

/* ---- hashtag labels floating in graph / raum (capsule fields) ---- */
.flow-kw{ position:absolute; inset:0; pointer-events:none; z-index:1; }
.flow-kw .kw{ position:absolute; transform:translate(-50%,-50%); white-space:nowrap;
  font-family:var(--mono); letter-spacing:0.02em; color:var(--ink-2);
  background:color-mix(in srgb,#ffffff 88%, transparent); border:1px solid var(--line);
  border-radius:999px; padding:3px 10px; box-shadow:0 1px 2px rgba(0,0,0,.05);
  opacity:0; transition:opacity .5s ease, color .2s ease, border-color .2s ease; }
/* v2: hashtags are real nodes the hover can light up (text + border only) */
.flow-kw .kw.kw-hot{ color:var(--accent); border-color:var(--accent); }

/* ---- fine solver toggle, top-left of the graph ---- */
.graph-solver{ position:absolute; top:12px; left:12px; z-index:30; display:none;
  align-items:center; gap:6px; font-family:var(--mono); }
.flow.is-graph .graph-solver{ display:inline-flex; }
.graph-solver__l{ font-size:10px; letter-spacing:0.08em; text-transform:uppercase; color:var(--grey-2); }
.graph-solver button{ width:20px; height:20px; border:1px solid var(--line); background:color-mix(in srgb,#fff 70%, transparent);
  -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
  font-family:var(--mono); font-size:11px; color:var(--ink-2); cursor:pointer; transition:all .16s; }
.graph-solver button:hover{ border-color:var(--grey); color:var(--ink); }
.graph-solver button.on{ background:var(--ink); border-color:var(--ink); color:#fff; }
.flow.is-graph .flow-kw, .flow.is-raum .flow-kw{ }
.flow:not(.is-graph):not(.is-raum) .flow-kw .kw{ opacity:0 !important; }
