:root {
  color-scheme: dark;
  --fg:#fff; --dim:rgba(255,255,255,.62); --dim2:rgba(255,255,255,.38);
  --glass:rgba(20,20,26,.52); --glass-hi:rgba(40,40,50,.72);
  --hair:rgba(255,255,255,.13); --hair-hi:rgba(255,255,255,.24);
  --acc:#4d9dff; --acc2:#8cc4ff; --acc-glow:rgba(77,157,255,.45);
  --good:#4ade80; --bad:#ff6b6b; --gold:#ffd24a;
  --sheet:rgba(14,14,18,.93);
  --mono: ui-monospace, SFMono-Regular, Menlo, monospace;
  --ease: cubic-bezier(.22,.61,.36,1);
  --blur: blur(22px) saturate(1.6);
}
* { box-sizing:border-box; -webkit-tap-highlight-color:transparent; }
html,body { margin:0; height:100%; overflow:hidden; background:#000; color:var(--fg);
            font:15px/1.35 system-ui,-apple-system,"Segoe UI",sans-serif;
            overscroll-behavior:none; -webkit-font-smoothing:antialiased; }
/* every inset is handled here exactly once; nothing below re-applies env() */
body { position:relative; display:flex; flex-direction:column;
       padding:env(safe-area-inset-top) env(safe-area-inset-right)
               env(safe-area-inset-bottom) env(safe-area-inset-left); }
svg { display:block; width:1em; height:1em; fill:none; stroke:currentColor;
      stroke-width:2; stroke-linecap:round; stroke-linejoin:round; }
::-webkit-scrollbar { width:0; height:0; }

/* ================= stage + console =================
   Portrait letterboxes a 16:9 stream badly, so the video is pinned to the top
   of its box and the leftover black is absorbed by the console below it rather
   than left as a void with controls floating in it. Landscape, where the frame
   nearly fills the screen, goes back to controls floating over the picture. */
/* the card is exactly the frame's shape, so there is no letterbox at all */
#stage { position:relative; flex:none; width:100%; aspect-ratio:16/9; min-height:0;
         background:#000; touch-action:none; border-radius:0 0 24px 24px; overflow:hidden; }
video { width:100%; height:100%; object-fit:contain; display:block; background:#000; }
/* controls sit at the bottom of what is left: thumb reach on a tall phone */
#console { flex:1; min-height:0; display:flex; flex-direction:column;
           justify-content:flex-end; gap:12px;
           padding:12px 16px 14px; }
#ctlrow { display:flex; align-items:center; gap:14px; margin-top:auto; }

/* everything floats; the layer itself never eats taps */
#ui { position:absolute; inset:0; pointer-events:none; z-index:2; }
#ui > * { pointer-events:auto; }
/* must out-specify the rule above, or the pills swallow drags in the corners */
#ui > .pill { pointer-events:none; }

.glass { background:var(--glass); backdrop-filter:var(--blur); -webkit-backdrop-filter:var(--blur);
         border:1px solid var(--hair); box-shadow:0 4px 24px rgba(0,0,0,.42); }

/* ---- status ---- */
.pill { position:absolute; display:flex; align-items:center; gap:7px; padding:8px 13px;
        border-radius:999px; font:11px/1 var(--mono); color:var(--dim); letter-spacing:.03em; }
#badge { top:12px; left:14px; }
#badge .dot { width:7px; height:7px; border-radius:50%; background:var(--dim2); flex:none; }
#badge.live { color:var(--good); }
#badge.live .dot { background:var(--good); box-shadow:0 0 0 0 rgba(74,222,128,.6); animation:pulse 2.4s infinite; }
#badge.err  { color:var(--bad); } #badge.err .dot { background:var(--bad); }
@keyframes pulse { 70%{box-shadow:0 0 0 8px rgba(74,222,128,0);} 100%{box-shadow:0 0 0 0 rgba(74,222,128,0);} }
#readout { top:12px; right:14px; }
/* an outage matters most when nobody is watching, so it shouts */
#alert { top:52px; left:14px; display:none; color:#ffd0d0;
         border-color:rgba(255,107,107,.5); background:rgba(120,20,20,.72); }
body.outage #alert { display:flex; }
#hint { left:50%; transform:translateX(-50%); top:58px;
        opacity:0; transition:opacity .4s var(--ease); }
#hint.show { opacity:1; }

/* ---- vertical zoom rail ---- */
/* sits above the icon rail rather than centred: at 375x812 a centred rail
   overlapped the top button by 20px */
#zrail { position:relative; flex:none; margin-left:auto; width:58px; height:132px;
         border-radius:29px;
         display:flex; flex-direction:column; align-items:center; justify-content:center; gap:2px; }
#zval { font:10px var(--mono); color:var(--acc2); letter-spacing:.04em; }
#zbox { flex:1; width:100%; display:flex; align-items:center; justify-content:center; }
/* rotate a normal range: iOS never supported appearance:slider-vertical */
#zoom { width:104px; transform:rotate(-90deg); }

/* ---- joystick ---- */
#joy { position:relative; flex:none; width:132px; height:132px;
       border-radius:50%; touch-action:none; }
#joy::after { content:""; position:absolute; inset:15px; border-radius:50%;
              border:1px dashed rgba(255,255,255,.10); }
#knob { position:absolute; left:50%; top:50%; width:52px; height:52px; margin:-26px 0 0 -26px;
        border-radius:50%; background:rgba(255,255,255,.94);
        box-shadow:0 3px 16px rgba(0,0,0,.55), 0 0 0 0 var(--acc-glow);
        transition:box-shadow .16s var(--ease), transform .22s var(--ease); }
#joy.act #knob { transition:none; box-shadow:0 3px 16px rgba(0,0,0,.55), 0 0 0 8px var(--acc-glow); }
#joy .tick { position:absolute; color:var(--dim2); font-size:9px; }
#joy .tick.u { top:6px;  left:50%; transform:translateX(-50%); }
#joy .tick.d { bottom:6px; left:50%; transform:translateX(-50%); }
#joy .tick.l { left:7px;  top:50%; transform:translateY(-50%); }
#joy .tick.r { right:7px; top:50%; transform:translateY(-50%); }

/* ---- round icon rail ---- */
#rail { display:flex; flex-direction:row; gap:10px; justify-content:space-between; }
.ib { width:50px; height:50px; border-radius:50%; font-size:18px; color:var(--fg);
      display:flex; align-items:center; justify-content:center; cursor:pointer;
      transition:background .15s var(--ease), transform .1s var(--ease), border-color .15s; }
.ib:active { transform:scale(.9); background:var(--acc); border-color:var(--acc); }
.ib.on { background:rgba(77,157,255,.3); border-color:var(--acc); color:#fff;
         box-shadow:0 0 20px -4px var(--acc-glow); }
#home { color:var(--acc2); }

/* ---- preset chips ---- */
#dial { display:flex; gap:8px; overflow-x:auto; scrollbar-width:none; padding-bottom:2px; }
.chip { flex:none; height:38px; padding:0 16px; border-radius:999px; font-size:13px;
        font-weight:500; white-space:nowrap; max-width:160px; overflow:hidden; color:var(--fg);
        display:flex; align-items:center; cursor:pointer;
        transition:background .15s var(--ease), transform .1s var(--ease); }
.chip:active { transform:scale(.94); background:var(--acc); border-color:var(--acc); }
.chip.add { color:var(--dim); border-style:dashed; }

#saverow { display:none; gap:8px; padding:7px; border-radius:999px; }
body.saving #saverow { display:flex; animation:rise .22s var(--ease); }
body.saving #dial { display:none; }
#pname { flex:1; min-width:0; height:38px; padding:0 15px; border-radius:999px;
         background:rgba(0,0,0,.35); border:1px solid var(--hair-hi); color:var(--fg);
         font:14px inherit; outline:none; }
#pname:focus { border-color:var(--acc); box-shadow:0 0 0 3px var(--acc-glow); }
#saverow button { height:38px; padding:0 17px; font-size:13px; flex:none; border-radius:999px;
                  border:1px solid var(--hair); background:var(--glass-hi); color:var(--fg);
                  font-family:inherit; cursor:pointer; }
#psave { background:var(--acc); border-color:var(--acc); font-weight:600; }

/* a clip takes the whole screen; sheets simply cover the console */
body.playing #console, body.playing #hint { display:none; }

/* ================= clip player ================= */
/* Portrait pins the video to a 16:9 card at the top, so an overlaid transport
   covered the picture while the console area below sat empty. Here it simply
   takes the console's place. Landscape puts it back over the frame, where it
   auto-hides -- see the landscape block. */
#player { display:none; flex:1; min-height:0; flex-direction:column; justify-content:flex-end;
          gap:12px; padding:14px 16px 18px; }
body.playing #player { display:flex; animation:rise .26s var(--ease); }
#scrub { position:relative; height:30px; display:flex; align-items:center; touch-action:none; cursor:pointer; }
#scrub .track { position:absolute; left:0; right:0; height:6px; border-radius:99px; background:rgba(255,255,255,.2); }
#scrub .fill { position:absolute; left:0; top:0; bottom:0; width:0; border-radius:99px;
               background:linear-gradient(90deg,var(--acc),var(--acc2)); }
#scrub .knob { position:absolute; width:16px; height:16px; margin-left:-8px; border-radius:50%;
               background:#fff; box-shadow:0 1px 6px #000b, 0 0 0 5px var(--acc-glow); left:0; }
#prow { display:flex; align-items:center; gap:10px; }
#ptime { font:11px var(--mono); color:var(--dim); flex:none; min-width:86px; }
#pspacer { flex:1; }
#plabel { font:12px var(--mono); color:var(--fg); flex:none; }
#pplay { width:56px; height:56px; background:#fff; color:#000; border-color:#fff; font-size:20px; }
#pplay:active { background:var(--acc); border-color:var(--acc); color:#fff; }

/* ================= sheets ================= */
@keyframes rise { from { opacity:0; transform:translateY(16px); } to { opacity:1; transform:none; } }
.sheet { position:absolute; left:0; right:0; bottom:0; display:none; z-index:5;
         background:var(--sheet); backdrop-filter:var(--blur); -webkit-backdrop-filter:var(--blur);
         border-top:1px solid var(--hair); border-radius:22px 22px 0 0;
         box-shadow:0 -14px 44px rgba(0,0,0,.6);
         padding:0 16px 14px;
         max-height:74vh; overflow-y:auto; -webkit-overflow-scrolling:touch; }
body.precision #panel { display:block; animation:rise .26s var(--ease); }
body.events    #tl    { display:block; animation:rise .26s var(--ease); }
body.playing .sheet { display:none; }
.grab { width:40px; height:4px; border-radius:99px; background:var(--hair-hi);
        margin:10px auto 14px; cursor:grab; }
.sheet.drag { transition:none; animation:none; }
.sheet.snap { transition:transform .22s var(--ease); }
.grabzone { touch-action:none; }

.shead { display:flex; align-items:center; gap:10px; margin-bottom:14px; }
.shead h2 { margin:0; font-size:15px; font-weight:600; letter-spacing:-.01em; }
.shead .count { font:11px var(--mono); color:var(--dim2); }
.seg { display:flex; gap:2px; padding:3px; border-radius:999px;
       background:rgba(255,255,255,.07); border:1px solid var(--hair); }
.seg button { height:28px; padding:0 13px; font-size:12px; border:0; border-radius:999px;
              background:transparent; color:var(--dim); font-family:inherit; cursor:pointer; }
.seg button.on { background:var(--acc); color:#fff; }

.ax { padding:11px 0; border-top:1px solid rgba(255,255,255,.07); }
.ax:first-of-type { border-top:0; }
.axhead { display:flex; align-items:baseline; gap:8px; margin-bottom:3px; }
.axname { font-size:13px; font-weight:600; }
.axlim { font:10px var(--mono); color:var(--dim2); }
.axval { margin-left:auto; font:12px var(--mono); color:var(--acc2); font-weight:600; }
.axrow { display:flex; align-items:center; gap:10px; }
.axrow input { flex:1; min-width:0; }
.sb { width:38px; height:34px; border-radius:11px; flex:none; font-size:17px; color:var(--fg);
      background:rgba(255,255,255,.08); border:1px solid var(--hair); cursor:pointer;
      display:flex; align-items:center; justify-content:center; font-family:inherit;
      transition:background .14s, transform .09s; }
.sb:active { background:var(--acc); border-color:var(--acc); transform:scale(.93); }
.axauto { width:auto; padding:0 12px; font-size:11px; letter-spacing:.04em; }
.axauto.on { background:rgba(77,157,255,.28); border-color:var(--acc); color:#fff; }

.subhead { font-size:15px; font-weight:600; letter-spacing:-.01em; margin:20px 0 11px;
           padding-top:16px; border-top:1px solid rgba(255,255,255,.07); }
.hrow { display:flex; gap:9px; margin-bottom:12px; }
.hrow .sb { flex:1; width:auto; height:42px; font-size:13px; gap:7px; }
.prow { display:flex; align-items:center; gap:10px; margin-bottom:8px; }
.prow .nm { flex:1; min-width:0; font-size:14px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.prow .co { font:10px var(--mono); color:var(--dim2); flex:none; }
.prow .del:active { background:var(--bad); border-color:var(--bad); }

/* ---- sliders ---- */
input[type=range] { -webkit-appearance:none; appearance:none; height:34px; background:transparent;
                    margin:0; width:100%; }
input[type=range]::-webkit-slider-runnable-track { height:6px; border-radius:99px;
    background:linear-gradient(90deg,var(--acc) var(--pct,0%), rgba(255,255,255,.18) var(--pct,0%)); }
input[type=range]::-webkit-slider-thumb { -webkit-appearance:none; width:22px; height:22px;
    border-radius:50%; background:#fff; margin-top:-8px; box-shadow:0 1px 6px #000a, 0 0 0 5px var(--acc-glow); }
input[type=range]::-moz-range-track { height:6px; border-radius:99px; background:rgba(255,255,255,.18); }
input[type=range]::-moz-range-progress { height:6px; border-radius:99px; background:var(--acc); }
input[type=range]::-moz-range-thumb { width:22px; height:22px; border:0; border-radius:50%; background:#fff; }

/* ---- events ---- */
/* lives in the console, not the sheet: the last hours of motion should be
   readable without opening anything */
#strip { position:relative; height:72px; border-radius:16px; background:rgba(255,255,255,.05);
         border:1px solid var(--hair); overflow:hidden; touch-action:pan-y; flex:none; }
#strip .hr { position:absolute; top:0; bottom:16px; width:1px; background:rgba(255,255,255,.06); }
#strip .hrlab { position:absolute; bottom:3px; font:9px var(--mono); color:var(--dim2);
                transform:translateX(4px); pointer-events:none; }
/* bars sit on the baseline and scale by peak, so strength reads at a glance */
#strip .ev { position:absolute; bottom:16px; min-width:4px; border-radius:4px 4px 1px 1px;
             background:linear-gradient(180deg,var(--acc2),var(--acc)); opacity:.92; cursor:pointer; }
#strip .ev.sel { background:linear-gradient(180deg,#fff0c0,var(--gold)); opacity:1;
                 box-shadow:0 0 14px -1px rgba(255,210,74,.75); }
#now { position:absolute; top:0; bottom:16px; width:2px; background:var(--bad); }
#strip .empty-in { position:absolute; inset:0; display:flex; align-items:center;
                   justify-content:center; font-size:12px; color:var(--dim2); }

#list { max-height:42vh; overflow-y:auto; margin:12px -16px 0; padding:0 16px; }
.row-ev { display:flex; align-items:center; gap:12px; padding:12px 14px; border-radius:14px;
          border:1px solid var(--hair); margin-bottom:7px; background:rgba(255,255,255,.045);
          cursor:pointer; transition:border-color .15s, background .15s; }
.row-ev:active { background:rgba(255,255,255,.09); }
.row-ev.sel { border-color:var(--acc); background:rgba(77,157,255,.16); }
.row-ev .tm { font:13px var(--mono); font-weight:600; flex:none; line-height:1.25; }
.row-ev .day { font:10px var(--mono); color:var(--dim2); font-weight:400; }
.row-ev .bar { flex:1; min-width:24px; height:4px; border-radius:99px;
               background:rgba(255,255,255,.12); overflow:hidden; }
.row-ev .bar i { display:block; height:100%; border-radius:99px;
                 background:linear-gradient(90deg,var(--acc),var(--acc2)); }
.row-ev .meta { font:11px var(--mono); color:var(--dim); flex:none; }
.row-ev .go { color:var(--dim2); font-size:12px; flex:none; }
.row-ev .star { flex:none; width:34px; height:34px; border-radius:10px; border:1px solid var(--hair);
                background:rgba(255,255,255,.05); color:var(--dim2); font-size:15px; line-height:1;
                display:flex; align-items:center; justify-content:center; cursor:pointer;
                transition:color .15s, background .15s, transform .09s; }
.row-ev .star:active { transform:scale(.9); }
.row-ev .star.on { color:var(--gold); border-color:rgba(255,210,74,.4); background:rgba(255,210,74,.12); }
#strip .ev.fav { background:linear-gradient(180deg,#fff0c0,var(--gold)); }
.empty { color:var(--dim); font-size:13px; padding:16px 2px; text-align:center; }

/* ---- sign-in gate ---- */
#gate { position:absolute; inset:0; z-index:20; display:none; flex-direction:column;
        align-items:center; justify-content:center; gap:16px; text-align:center;
        padding:24px; background:radial-gradient(120% 90% at 50% 0%, #16161e, #050508); }
body.locked #gate { display:flex; }
body.locked #stage, body.locked #console, body.locked .sheet { display:none; }
#gate img { width:104px; height:104px; border-radius:26px; box-shadow:0 12px 40px rgba(0,0,0,.6); }
#gate h1 { margin:0; font-size:25px; font-weight:600; letter-spacing:-.02em; }
#gate p { margin:0; max-width:300px; font-size:13px; color:var(--dim); line-height:1.5; }
#gate button { height:50px; padding:0 26px; border-radius:999px; font-size:15px; font-weight:600;
               background:var(--acc); border:1px solid var(--acc); color:#fff;
               box-shadow:0 8px 26px -8px var(--acc-glow); }
#gate .sub { font-size:12px; color:var(--dim2); }

/* ---- access section ---- */
.krow { display:flex; align-items:center; gap:10px; margin-bottom:8px; }
.krow .nm { flex:1; min-width:0; font-size:14px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.krow .co { font:10px var(--mono); color:var(--dim2); flex:none; }
.warn { font-size:12px; color:var(--dim); line-height:1.5; margin:2px 0 10px; }
.statebar { display:flex; gap:8px; flex-wrap:wrap; margin:10px 0 8px; }
.statebar span { font:11px var(--mono); padding:5px 11px; border-radius:999px;
                 border:1px solid var(--hair); letter-spacing:.02em; }
.statebar .sgood { color:#8ee6a8; border-color:rgba(74,222,128,.35); background:rgba(74,222,128,.10); }
.statebar .sbad  { color:#ffd28a; border-color:rgba(251,191,36,.35); background:rgba(251,191,36,.10); }
#addrow { display:none; }
body.enrolling #addrow { display:flex; }
body.enrolling #addkey { display:none; }
#kname { flex:2; min-width:0; height:42px; padding:0 14px; border-radius:11px;
         background:rgba(255,255,255,.06); border:1px solid var(--hair-hi); color:var(--fg);
         font:14px inherit; outline:none; }
#kname:focus { border-color:var(--acc); box-shadow:0 0 0 3px var(--acc-glow); }
#kadd { background:rgba(77,157,255,.22); border-color:var(--acc); }
.danger { color:#ffb4b4; }

/* installed to the home screen: no browser chrome, so tighten the margins and
   let the video card run to the very top */
@media (display-mode: standalone) {
  #stage { border-radius:0 0 26px 26px; }
  #console { padding-top:14px; }
}

/* Any landscape viewport, not just a short one. The 16:9 card in the portrait
   rules is sized off the width, so on a 1899px-wide desktop it becomes ~1068px
   tall and pushes the console off the bottom of the window. Wherever the frame
   can fill the screen, the controls float over it instead. */
@media (orientation:landscape) {
  body { display:block; }
  #stage { position:absolute; inset:0; aspect-ratio:auto; border-radius:0; }
  #console { position:absolute; left:0; right:0; bottom:0; z-index:3; flex:none; gap:9px;
             padding:34px 14px 10px;
             background:linear-gradient(to top, rgba(0,0,0,.82), rgba(0,0,0,0)); }
  /* Landscape stacks the console under the picture: the joystick comes first,
     and the things you read rather than drive sit beneath it. */
  #ctlrow  { gap:12px; margin-top:0; order:1; }
  #dial    { order:2; }
  #saverow { order:2; }
  #strip   { order:3; }
  #rail    { justify-content:flex-end; gap:10px; order:4; }
  /* the console now spans the whole window, so keep these off the far edge */
  #dial, #strip, #saverow { max-width:min(760px, 68vw); }
  /* the frame fills the screen here, so the transport floats and gets out of
     the way by itself; a tap anywhere on the picture brings it back */
  #player { position:absolute; left:0; right:0; bottom:0; z-index:6; flex:none;
            padding:36px 14px 12px;
            background:linear-gradient(to top, rgba(0,0,0,.9) 45%, rgba(0,0,0,0));
            transition:opacity .3s var(--ease), transform .3s var(--ease); }
  body.playing.chrome-off #player { opacity:0; transform:translateY(14px); pointer-events:none; }
  .sheet { max-height:100vh; border-radius:22px 0 0 0; left:auto; width:min(66vw,430px); top:0; }
  #list { max-height:none; }
}

/* landscape on a phone: shrink everything so the picture keeps the room */
@media (orientation:landscape) and (max-height:560px) {
  #joy { width:104px; height:104px; }
  #knob { width:44px; height:44px; margin:-22px 0 0 -22px; }
  #zrail { width:52px; height:104px; }
  #zoom { width:78px; }
  .ib { width:46px; height:46px; }
  #console { gap:8px; padding:28px 12px 8px; }
  #strip { height:52px; }
  #dial, #strip, #saverow { max-width:none; }
}
