/* ══════════════════════════════════════════════════════════════════════════
   SecureAccess console — the SHELL only.

   Everything visual comes from ultracns.css: Barlow and Bebas Neue, the token
   set, and the components (.card .kpi .tile .chip .btn .fld .inp .note .seg
   .lbl .num). That file was extracted verbatim from the CRM, so this console
   is the same product as the rest of the estate rather than a family
   resemblance.

   What is left here is what the house theme deliberately does not ship: the
   app shell. It even provides --rail and --head as tokens for exactly this,
   which is a strong hint about where the seam belongs.

   THE ONE RULE: build with tokens, never a literal colour. A colour written
   into a component is a colour that will be wrong in the other theme —
   check.py fails the build on any hex outside a token definition.
   ══════════════════════════════════════════════════════════════════════════ */

*{box-sizing:border-box}
html,body{height:100%}
/* ══════════════════════════════════════════════════════════════════════════
   THE SHELL, IN KEEPING WITH UltraCNS NEXUS

   Jag: "we should update all the dasboards so they are in keeping with
   http://127.0.0.1:8088/#overview".

   Every number below was read off Nexus's computed styles, not matched by eye
   — the same discipline the sign-in page went through, and for the same
   reason: near-misses are what make two products look like two products.

     bar        48px, #060F1E, fixed, wordmark 20px display over the rail
     rail       232px (--rail), nav items 13px/500, 7px 14px, radius 3px,
                active = brand-soft + inset 3px 0 0 var(--accent)
     count      10.5px/700 pill, surface-3, radius 20px, 1px 7px, tabular
     card       1px border, radius 4px, padding 16px
     kpi        label 11.5px/700 uppercase with an 8px swatch, value in the
                MONO face at 22px tabular, footnote 11.5px
     content    20px gutter, 56px at the bottom
     page title 24px/700, letter-spacing -.5px

   Nexus calls its ink --text-primary/--muted and its blue --brand; here those
   are --ink/--ink-3 and --accent, and they hold the same hex. Nothing is
   renamed to match, because a token renamed for cosmetic agreement is a token
   two places now disagree about.
   ══════════════════════════════════════════════════════════════════════════ */
body{
  margin:0;
  display:grid; grid-template-columns:var(--rail) 1fr;
  padding-top:var(--head);           /* clears the fixed bar */
}

/* ── the navy bar ───────────────────────────────────────────────────────── */
.topbar{
  position:fixed; top:0; left:0; right:0; z-index:60;
  height:var(--head); padding:0 16px 0 14px;
  display:flex; align-items:center; gap:18px;
  background:var(--navy); box-sizing:border-box;
}
.topbar .wm{
  font-family:var(--f-display); font-size:20px; letter-spacing:.4px; line-height:1;
  display:flex; align-items:baseline; gap:0;
  /* Sits over the rail, so it lines up with the nav beneath it. */
  flex:0 0 calc(var(--rail) - 62px);
}
.topbar .wm b{color:var(--on-navy); font-weight:400}
/* --brand, the logo blue. It does not carry any words, so its contrast is not
   a reading question; --accent is what text uses. */
.topbar .wm em{color:var(--brand); font-style:normal; font-weight:400}
.topbar .wm-app{
  font-family:var(--f-ui); font-size:9px; font-weight:600; letter-spacing:.22em;
  color:var(--on-navy-3); margin-left:10px; align-self:center;
  text-transform:uppercase;
}
.topbar .crumb{font-size:12.5px; color:var(--on-navy-2)}
.topbar .crumb b{font-family:var(--f-ui); font-size:12.5px; letter-spacing:0;
  color:var(--on-navy); font-weight:600}
.topbar .stamp{margin-left:auto; color:var(--on-navy-4)}

.stamp{font-size:11.5px; color:var(--ink-3); font-variant-numeric:tabular-nums}

/* ── the page head ──────────────────────────────────────────────────────── */
.page-head{
  display:flex; align-items:flex-start; justify-content:space-between;
  gap:16px; flex-wrap:wrap; margin-bottom:22px;
}
.page-title{
  margin:0; font-family:var(--f-ui);
  font-size:24px; font-weight:700; letter-spacing:-.5px; color:var(--ink);
}
:focus-visible{outline:2px solid var(--accent); outline-offset:2px; border-radius:var(--r)}
@media (prefers-reduced-motion:reduce){ *{animation:none !important; transition:none !important} }

/* ── the rail ─────────────────────────────────────────────────────────── */
.rail{
  position:sticky; top:var(--head); height:calc(100vh - var(--head));
  display:flex; flex-direction:column;
  background:var(--surface); border-right:1px solid var(--rule);
  padding:4px 0 12px; min-width:0;
}

/* The section label above the vessel, in the mono face as Nexus sets it. */
.nav-label{
  font-family:var(--f-mono); font-size:10.5px; font-weight:400;
  letter-spacing:.16em; text-transform:uppercase; color:var(--ink-3);
  padding:14px 14px 5px;
}
.rail-vessel{
  padding:0 14px 12px; font-size:14px; font-weight:600; color:var(--ink);
  border-bottom:1px solid var(--rule-2); margin-bottom:6px;
}
.brand{
  display:flex; gap:9px; align-items:center; padding:2px 15px 12px;
  border-bottom:1px solid var(--rule-2); margin-bottom:8px;
}
.brand-mark{
  font-family:var(--f-display); font-size:23px; line-height:1;
  color:var(--brand); letter-spacing:.04em;
}
.brand-text{min-width:0}
.brand-name{
  font-family:var(--f-display); font-size:18px; letter-spacing:.05em;
  line-height:1.05; color:var(--ink);
}
.brand-vessel{
  font-size:11.5px; color:var(--ink-3);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}

/* .nav-i is the house nav item; this only stacks them. */
.nav{display:flex; flex-direction:column; gap:0}
/* The count pill lives in ultracns.css now, matching Nexus:
   10.5px/700 on surface-3, fully rounded, tabular. */
.nav-i svg{
  width:15px; height:15px; flex:none; fill:none; stroke:currentColor;
  stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round;
}
.nav-i>span:first-of-type{flex:1; min-width:0; text-align:left}

/* Gateway liveness, visible from every screen: nothing anywhere can happen
   while the vessel is unreachable. */
.rail-gateway{margin-top:14px; padding:0 12px}
.gw{
  border:1px solid var(--rule); border-radius:var(--r-card);
  padding:8px 10px; background:var(--surface-2); font-size:11.5px;
}
.gw-name{
  font-weight:600; color:var(--ink);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.gw-age{color:var(--ink-3); margin-top:2px}
.gw.gone{border-color:var(--danger); background:var(--danger-w)}
.gw.gone .gw-age{color:var(--danger)}

.acting{margin-top:auto; border-top:1px solid var(--rule-2); padding:11px 12px 2px}
.acting-head{
  display:flex; justify-content:space-between; align-items:center;
  margin-bottom:6px;
}
/* The signed-in person, and their role beneath it. A name, not a control:
   there is nothing here to change. */
.who-name{color:var(--ink); font-size:13px; font-weight:500; margin-top:2px}
.acting-note{color:var(--ink-3); font-size:11px; margin-top:6px; min-height:1.2em}
.dev-chip{
  background:var(--warm-w); color:var(--warm);
  border:1px solid color-mix(in srgb, var(--warm) 30%, transparent);
  border-radius:4px; padding:0 6px;
  font-size:9.5px; font-weight:700; letter-spacing:.11em; line-height:16px;
}

/* ── content ──────────────────────────────────────────────────────────── */
main{padding:0 0 40px; min-width:0}
/* The white sticky header that used to sit here is gone. Its job — the screen
   name and when it was last read — moved into .page-head, and the identity it
   carried moved into the navy bar, which is where Nexus keeps it. */
.screenpad{padding:20px 20px 56px}
.screen{display:none}
.screen.on{display:block}
.lead{color:var(--ink-2); max-width:64ch; margin:0 0 16px; font-size:13px}
h2{margin:22px 0 9px}
h2:first-of-type{margin-top:0}

/* The dashboard's answer line. Calm when nothing needs doing; it earns
   attention only when something actually wants it. */
.headline{
  display:flex; align-items:center; gap:12px;
  background:var(--surface); border:1px solid var(--rule);
  border-left:3px solid var(--ink-3);
  border-radius:var(--r-card); box-shadow:var(--shadow); padding:13px 15px;
}
.headline .what{font-size:15px; font-weight:600; color:var(--ink)}
.headline .why{color:var(--ink-2); font-size:12.5px; margin-top:2px}
.headline.act{border-left-color:var(--warm)}
.headline.bad{border-left-color:var(--danger)}
.headline.calm{border-left-color:var(--good)}
.headline .btn{margin-left:auto; flex:none}

.cols{display:grid; grid-template-columns:1fr 1fr; gap:14px}
@media (max-width:900px){ .cols{grid-template-columns:1fr} }
.tiles{display:flex; flex-direction:column; gap:9px}
.tile .big{font-size:14px; font-weight:600; color:var(--ink)}
.tile .sub{color:var(--ink-3); font-size:11.5px}

/* ── the approval card: the ten-second read ───────────────────────────── */
.card.approval{margin-bottom:12px; max-width:640px; padding:15px 16px}
.approval .who{font-size:15.5px; font-weight:600; color:var(--ink)}
.approval .company{color:var(--ink-2); font-weight:400}
.approval .what{margin:5px 0 0; font-size:13px; color:var(--ink-2)}
.approval .what b{color:var(--ink); font-weight:600}
.approval .why{
  background:var(--surface-2); border-left:3px solid var(--accent);
  padding:9px 12px; margin:11px 0; border-radius:0 var(--r) var(--r) 0;
  font-size:13px; color:var(--ink);
}
/* What the session actually opens onto. On a jump host this is the fact the
   decision turns on, so it is given its own block rather than a footnote. */
.approval .reach{
  border:1px solid var(--rule-2); border-radius:var(--r);
  padding:8px 11px; margin:0 0 11px; font-size:12px; background:var(--surface-2);
}
.approval .reach .lbl{display:block; margin-bottom:3px}
.approval .reach .devices{color:var(--ink-2)}
.approval .meta{
  color:var(--ink-3); font-size:11.5px; display:flex; gap:14px; flex-wrap:wrap;
}
.approval .actions{display:flex; gap:8px; margin-top:13px; align-items:center}
.approval .actions .inp{flex:1; min-width:0}

/* ── request form ─────────────────────────────────────────────────────── */
.panel{max-width:540px}
.panel .fld{margin-bottom:14px}
.panel textarea.inp{height:auto; min-height:58px; padding:8px 10px; resize:vertical}
.panel .seg button{
  border:0; border-right:1px solid var(--rule); background:none;
  color:var(--ink-2); padding:0 13px; height:32px;
  font:inherit; font-size:12.5px; cursor:pointer;
}
.panel .seg button:last-child{border-right:0}
.panel .seg button.on{background:var(--accent-wash); color:var(--accent-ink); font-weight:600}

/* ── tables ───────────────────────────────────────────────────────────── */
/* The house theme styles table/th/td; this only stops a wide one scrolling
   the page instead of itself. */
.tablewrap{
  overflow-x:auto; border:1px solid var(--rule);
  border-radius:var(--r-card); background:var(--surface);
}
td .sub{color:var(--ink-3); font-size:11.5px}
td.seq{font-variant-numeric:tabular-nums; color:var(--ink-3); width:1%}
.mono{
  font-family:var(--f-mono); font-size:11px;
  color:var(--ink-3); word-break:break-all;
}

/* ── states ───────────────────────────────────────────────────────────── */
.empty{
  border:1px dashed var(--rule); border-radius:var(--r-card); padding:20px;
  color:var(--ink-3); text-align:center; font-size:13px; background:var(--surface-2);
}
.empty b{color:var(--ink-2); font-weight:600}
.skeleton{
  border:1px solid var(--rule); border-radius:var(--r-card);
  padding:14px; background:var(--surface);
}
.skeleton i{
  display:block; height:9px; border-radius:3px; background:var(--surface-3);
  margin-bottom:8px; animation:pulse 1.4s ease-in-out infinite;
}
.skeleton i:nth-child(2){width:72%}
.skeleton i:nth-child(3){width:45%; margin-bottom:0}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.45}}

.chain.broken{border-left:3px solid var(--danger); background:var(--danger-w)}
.chain.broken .big{color:var(--danger)}
.chain.intact{border-left:3px solid var(--good)}

.foot{color:var(--ink-3); font-size:11px; margin-top:28px; padding:0 24px}

/* ── the live session ─────────────────────────────────────────────────── */
#session-overlay{display:none}
body.viewing #session-overlay{
  display:flex; flex-direction:column; position:fixed; inset:0; z-index:50;
  background:var(--navy);
}
.session-bar{
  display:flex; align-items:center; gap:13px; flex:none; height:var(--head);
  background:var(--surface); border-bottom:1px solid var(--rule); padding:0 16px;
  font-size:13px;
}
.session-bar .rec{
  display:flex; align-items:center; gap:6px; color:var(--danger);
  font-weight:700; font-size:10.5px; letter-spacing:.13em;
}
.rec-dot{
  width:7px; height:7px; border-radius:50%; background:var(--danger);
  animation:blink 1.6s ease-in-out infinite;
}
@keyframes blink{0%,100%{opacity:1}50%{opacity:.25}}
.session-bar .asset{font-weight:600; color:var(--ink)}
.session-bar .status{color:var(--ink-3); font-size:12px}
.session-bar .session-hint{margin-left:auto; color:var(--ink-3); font-size:11px}
#session-display{
  flex:1; min-height:0; display:flex; align-items:center; justify-content:center;
  overflow:hidden;
}
#session-display canvas{display:block}
/* The rail and content stay mounted underneath, so disconnecting returns to
   exactly the screen the session was launched from. */
body.viewing .rail, body.viewing main{visibility:hidden}

/* ── narrow: the rail becomes a top bar ───────────────────────────────── */
@media (max-width:760px){
  body{grid-template-columns:1fr}
  .rail{
    position:static; height:auto; flex-direction:row; align-items:center;
    gap:10px; border-right:0; border-bottom:1px solid var(--rule);
    padding:8px 12px; flex-wrap:wrap;
  }
  .brand{border-bottom:0; margin:0; padding:0}
  .brand-vessel{display:none}
  .nav{flex-direction:row; flex:1; flex-wrap:wrap}
  .nav-i{width:auto; margin:0}
  .nav-i svg{display:none}
  .rail-gateway{margin:0; padding:0; order:3; width:100%}
  .acting{margin:0; border-top:0; padding:0; width:190px}
  .acting-head,.acting-note{display:none}
  .top{padding:0 16px}
  .screenpad{padding:16px}
  .foot{padding:0 16px}
}


/* ══════════════════════════════════════════════════════════════════════════
   LIVE SESSIONS, AND ASKING TO JOIN ONE
   ══════════════════════════════════════════════════════════════════════════ */

/* One row per session. The holder's name is the most important thing on it —
   joining is asking a PERSON, not requesting a resource. */
.live {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 13px 15px;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-card);
  margin-bottom: 8px;
}
.live.mine { border-color: var(--accent); background: var(--accent-wash); }

.live .what { font: 600 14px/1.3 var(--f-ui); color: var(--ink); }
.live .who  { font: 400 12.5px/1.4 var(--f-ui); color: var(--ink-2); margin-top: 2px; }
.live .sub  { font: 400 11.5px/1.4 var(--f-ui); color: var(--ink-3); margin-top: 2px; }
.live .grow { flex: 1; min-width: 0; }
.live .acts { display: flex; gap: 7px; align-items: center; flex-shrink: 0; }

/* A live indicator that is a MEASUREMENT, not a decoration: it is drawn from
   the session having been opened and the gateway having named a connection.
   Nothing here blinks green because it feels alive. */
.live .dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--good); flex-shrink: 0;
}
.live .dot.waiting { background: var(--warm); }

/* ── the prompt inside a session ────────────────────────────────────────── */
/* Fixed to the viewport, so it reaches the holder whether they are looking at
   the remote machine or at the console. */
#session-ask {
  position: fixed;
  top: calc(var(--head) + 14px);
  right: 16px;
  z-index: 90;
  width: 330px;
  padding: 14px 15px;
  background: var(--surface);
  border: 1px solid var(--accent);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-lg);
  font: 400 13px/1.5 var(--f-ui);
  color: var(--ink);
}
#session-ask[hidden] { display: none; }
#session-ask .asking { font: 600 14px/1.3 var(--f-ui); }
#session-ask .about  { color: var(--ink-2); margin-top: 3px; }
#session-ask .appr   { color: var(--ink-3); font-size: 11.5px; margin-top: 7px; }
#session-ask .acts   { display: flex; gap: 6px; margin-top: 11px; flex-wrap: wrap; }
#session-ask .acts .btn { flex: 1 0 auto; }

/* Who else is in here, in the session bar. A person driving a machine with
   somebody watching must never have to go and look that up. */
.session-bar .who-here {
  font: 500 11.5px/1 var(--f-ui);
  letter-spacing: 0.04em;
  color: var(--warm);
  padding: 3px 7px;
  border: 1px solid var(--warm);
  border-radius: var(--r);
}
.session-bar .who-here:empty { display: none; }

/* ── handing control over, from inside the session ───────────────────────── */
.session-bar .hand { display: flex; gap: 6px; align-items: center; }
.session-bar .hand[hidden] { display: none; }
.session-bar .hand .lbl {
  font-size: 10.5px; letter-spacing: 0.1em; color: var(--ink-3);
}
.session-bar .hand select {
  font: 400 12px/1 var(--f-ui);
  padding: 4px 6px;
  border: 1px solid var(--rule-2);
  border-radius: var(--r);
  background: var(--surface);
  color: var(--ink);
  max-width: 170px;
}

/* Said when a stream is re-established because control changed hands. It is
   not an error and must not look like one. */
.session-bar .status.reattaching { color: var(--warm); }

/* ── the security review ──────────────────────────────────────────────────
   Outcomes are the point of the attempts table, so they carry the colour and
   everything else stays quiet. */
.outcome-chip { font-family: var(--f-mono); font-size: 10.5px; }
#security-attempts .sub { color: var(--ink-3); font-size: 11.5px }
#security-sessions .btn { white-space: nowrap }

/* ── adding a person ──────────────────────────────────────────────────────
   Three fields in a row, because they are one decision and stacking them
   makes it look like three. */
.cols3 { display: grid; grid-template-columns: 1fr 1.3fr 1fr; gap: 12px }
@media (max-width: 900px) { .cols3 { grid-template-columns: 1fr } }

/* The invitation link, shown ONCE. Set to be selected and copied, and said
   plainly to be the only time it will appear. */
.invite {
  margin-top: 12px;
  padding: 12px 13px;
  background: var(--accent-wash);
  border: 1px solid var(--accent);
  border-radius: var(--r-card);
}
.invite .link {
  display: block;
  margin-top: 6px;
  font: 500 12px/1.5 var(--f-mono);
  color: var(--accent-ink);
  word-break: break-all;
  user-select: all;
}
.invite .once { font: 500 12.5px/1.4 var(--f-ui); color: var(--ink) }

/* ── playing a recording ──────────────────────────────────────────────────
   The same overlay as a live session. The scrub bar appears only when there
   IS one, because a control that is always there and usually does nothing
   teaches people to ignore it. */
.session-bar .replay { display: none; align-items: center; gap: 9px; flex: 1 }
body.replaying .session-bar .replay { display: flex }
body.replaying .session-bar .session-hint { display: none }

.session-bar .replay .at {
  font: 500 11.5px/1 var(--f-num), var(--f-mono);
  color: var(--ink-2);
  min-width: 34px;
  text-align: center;
}
.session-bar .replay #replay-bar { flex: 1; accent-color: var(--accent); max-width: 520px }

/* A recording is not a session: no keyboard goes to it, so the display must
   not look like something that takes one. */
body.replaying #session-display { cursor: default }

/* Watching is an access event in its own right, so the button says so rather
   than looking like a link. */
.watch-recording { white-space: nowrap }

/* Why an invitation was not emailed. The mail server's own words: "mailbox
   unavailable" and "authentication required" are different problems with
   different fixes, and flattening them costs somebody an afternoon. */
.invite .why {
  margin-top: 7px;
  font: 400 11.5px/1.45 var(--f-mono);
  color: var(--ink-2);
}

/* ── the vessel switcher ────────────────────────────────────────────────────
   In the rail, under the name of the vessel you are on, because that is where
   somebody looks to answer "which boat am I on" and the two belong together.
   Hidden entirely for anybody who works on one vessel, which is everybody
   aboard — it exists for the visiting engineer covering five. */
.vessel-switch {
  padding: 0 14px 14px;
  border-bottom: 1px solid var(--rule-2);
  margin-bottom: 10px;
}
.vessel-switch .lbl { display: block; margin-bottom: 5px; }
.vessel-switch .inp { width: 100%; }
