/* marlins_memories: compact top controls, the portal field, a persistent dock. */
.mind{grid-template-rows:auto 1fr auto}
.topbar{display:flex;align-items:center;gap:6px;padding:4px 10px;border-bottom:1px solid var(--stroke);min-height:52px}
.icon{appearance:none;width:44px;height:44px;display:grid;place-items:center;padding:0;border:1px solid transparent;background:none;color:var(--paper);cursor:pointer}
.icon svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:1.6}
.icon[aria-pressed="true"],.icon[aria-expanded="true"]{color:var(--signal);border-color:var(--stroke);filter:drop-shadow(0 0 4px rgba(255,77,0,.6))}
.icon:focus-visible,.act:focus-visible,.portal:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.switch{display:flex;gap:2px}
.chip{margin-left:auto;font-size:10px;letter-spacing:.06em;color:var(--muted);text-align:right}
.clear{min-height:44px;padding:0 10px;font-size:10px}
.info{position:absolute;z-index:8;left:8px;right:8px;top:calc(56px + env(safe-area-inset-top));max-width:560px;padding:10px 6px;background:var(--panel);border:1px solid var(--stroke);box-shadow:0 8px 30px #000}
.info .status{text-align:left;padding:0 16px 6px}

main{position:relative;min-height:0;overflow:hidden;display:flex;flex-direction:column}
main>section{flex:1;min-height:0;display:flex;flex-direction:column;overflow-y:auto;overscroll-behavior:contain}
#view-mind{overflow-x:hidden}
.field{position:relative;width:100%;flex:0 0 auto;isolation:isolate} /* portals' stacking stays inside the field: never over the loader or the panel */

/* A portal: one memory, masked by its own feathered blob; transform-only motion. */
.portal{position:absolute;left:0;top:0;width:200px;height:200px;padding:0;border:0;background:none;color:var(--paper);font:inherit;pointer-events:none;transform-origin:0 0;transition:transform .7s cubic-bezier(.2,.7,.2,1);will-change:transform}
.portal .wob{position:absolute;inset:0}
.portal canvas{display:block;width:100%;height:100%;-webkit-mask-size:100% 100%;mask-size:100% 100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}
.portal.live .wob{animation:undulate var(--wob-dur,9s) ease-in-out var(--wob-delay,0s) infinite alternate}
@keyframes undulate{from{transform:rotate(calc(var(--wob-rot,2deg) * -1)) scale(1.025,.975)}to{transform:rotate(var(--wob-rot,2deg)) scale(.975,1.03)}}
.portal span{position:absolute;left:12%;right:12%;bottom:14%;text-align:center;font-size:calc(9px / var(--k,1));letter-spacing:.02em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-shadow:0 0 3px #000,0 0 3px #000;opacity:0;transition:opacity .2s}
.field.labels .portal span{font-size:calc(7.5px / var(--k,1))}
.portal .badge{right:22%;top:18%;font-size:calc(9px / var(--k,1))}
/* Awake: a glow that follows the form's own alpha (drop-shadow, never a box). */
.portal.active .wob{filter:drop-shadow(0 0 5px rgba(255,77,0,.55))}
.portal.focus .wob{filter:drop-shadow(0 0 7px var(--signal)) drop-shadow(0 0 2px var(--gold))}
.portal.focus span,.portal:focus-visible span,.field.labels .portal span{opacity:1}
.field.waking .portal:not(.active) .wob{opacity:.8}

.dreams{display:flex;flex-direction:column;padding:8px 16px 16px}
.dream{appearance:none;display:flex;align-items:center;gap:10px;min-height:56px;padding:4px 0;border:0;border-bottom:1px solid var(--stroke);background:none;color:var(--paper);font:inherit;font-size:11px;letter-spacing:.04em;text-align:left;cursor:pointer}
.dream img{width:56px;height:56px;object-fit:cover;-webkit-mask:radial-gradient(closest-side,#fff 55%,transparent);mask:radial-gradient(closest-side,#fff 55%,transparent)}

.dock{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px 12px;padding:8px 12px calc(8px + env(safe-area-inset-bottom));border-top:1px solid var(--stroke);background:var(--bg)}
.actions{display:flex;align-items:stretch}
.act{appearance:none;min-height:44px;padding:0 12px;border:0;border-left:1px solid var(--stroke);background:none;color:var(--paper);font:inherit;font-size:12px;letter-spacing:.08em;cursor:pointer}
.act:first-child{border-left:0}
.act[aria-pressed="true"]{color:var(--signal);text-shadow:0 0 8px rgba(255,77,0,.7)}
.act:disabled{opacity:.35;cursor:default}
#conflate{touch-action:none;cursor:crosshair}
#view-conflate .stage{background:none;border:0}

/* Controls never scroll away (MADRiD): the top bar and dock sit outside the scrolling field, and in
   RECALL and CONFLATE the stage gives up height before the readout and buttons do. Dreams, recalls
   and conflations fill the stage edge to edge (MADRiD): no padding, the picture squeezed to fill (mind.js fit). */
#view-recall,#view-conflate{overflow:hidden}
#view-recall .stage,#view-conflate .stage{flex:1 1 auto;min-height:120px;padding:0}
#view-recall .readout,#view-conflate .readout{flex:none;max-height:5.6em;overflow-y:auto;overscroll-behavior:contain}
#view-recall .row,#view-conflate .row{flex:none}

/* Waiting, over the view only: Jeremy's Marlin in orange DOS text (the TV lane's mountText, unchanged),
   small; DREAM waits add the REM Constellation band beneath him; RECALL waits close the eyes first
   (the phosphenes fill the view behind him). */
.loader{position:absolute;inset:0;z-index:30;background:var(--bg);display:grid;place-items:center}
.loader[hidden]{display:none}
.loader[data-kind="recall"]{background:transparent}
.loader-bg{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);display:none;image-rendering:pixelated}
.loader[data-kind="recall"] .loader-bg{display:block}
.loader[data-kind="recall"]::before{content:"";position:absolute;inset:0;background:#000;opacity:0;animation:lids .3s steps(1,end) forwards}
@keyframes lids{to{opacity:1}}
.loader-stack{position:relative;display:flex;flex-direction:column;align-items:center;gap:14px}
.loader-mark{width:min(38vw,24vh,200px);aspect-ratio:1;display:grid;place-items:center}
.loader-band{width:min(84vw,400px);aspect-ratio:400/208;display:none;image-rendering:pixelated}
.loader[data-kind="dream"] .loader-band{display:block}

@media (prefers-reduced-motion:reduce){.portal{transition:none}.portal.live .wob{animation:none}}

/* On the TV (MadridHost output): one 16:9 picture, no controls, the ident bottom-right
   (≤ 12 % wide, ≤ 85 % opaque, its line for 4 s). The phone remote shows no sound/film. */
.ident,.tv-mark{display:none}
body.tv-out{background:#000;cursor:none;overflow:hidden;grid-template-rows:1fr}
body.tv-out .topbar,body.tv-out .info,body.tv-out .actions,body.tv-out .row,body.tv-out .readout,body.tv-out .portal span,body.tv-out .badge{display:none!important}
body.tv-out main{position:fixed;inset:0}
body.tv-out main>section{overflow:hidden}
body.tv-out .portal.tv-off{visibility:hidden}
body.tv-out .field.waking .portal:not(.active) .wob{opacity:1}
body.tv-out .dock{position:fixed;right:5vw;bottom:5vh;max-width:12vw;padding:0;border:0;background:none;opacity:.85;pointer-events:none;flex-direction:column;align-items:flex-end}
body.tv-out .app-title{display:none}
/* The channel ident is Jeremy's Marlin mark (the TV lane's MarlinsMemoriesLogo-20261029/ident.svg, unchanged). */
body.tv-out .tv-mark{display:block;width:7vw;height:auto}
body.tv-out .ident{display:block;margin:0;font-size:clamp(9px,.75vw,15px);letter-spacing:.08em;color:var(--muted)}
body.tv-out .ident[hidden]{display:none}
body.tv-out #view-conflate .stage,body.tv-out #view-recall .stage{min-height:100vh;padding:0}
body.tv-controls #sound,body.tv-controls #conflate-sound,body.tv-controls #save-film,body.tv-controls #conflate-film,body.tv-controls #conflate-start{display:none}
