/* Portal Hub.
   A DARK console on purpose. This is the operator's tool, not a client facing
   surface, and it should not be mistaken for one on a screen share. It also
   means every client's own mark, which is a light-on-dark variant in each case,
   sits on it without recolouring, and their own colour carries the card rather
   than fighting a house palette. */

:root {
  --bg:#0E1418; --surface:#161E23; --surface-2:#1C262C; --raised:#222E35;
  --line:#2A363D; --line-soft:#222C33;
  --ink:#E9EFF1; --muted:#94A5AD; --faint:#65767E;
  --accent:#71B6FF; --accent-deep:#00155D;
  --ok:#4FB286; --warn:#D9A441; --alert:#D96C63;
  --sans:"Plus Jakarta Sans","SF Pro Text",-apple-system,BlinkMacSystemFont,sans-serif;
  --brand:"Outfit","Plus Jakarta Sans",-apple-system,sans-serif;
  --pill:999px; --r:14px; --r-lg:20px;
  --sat: env(safe-area-inset-top, 0px);
  --sab: env(safe-area-inset-bottom, 0px);
  --sal: env(safe-area-inset-left, 0px);
  --sar: env(safe-area-inset-right, 0px);
  --gut: 22px;
}

* { box-sizing:border-box; }
html,body { margin:0; padding:0; max-width:100%; overflow-x:hidden; }
html {
  background:var(--bg); -webkit-text-size-adjust:100%; text-size-adjust:100%;
}
html, body { overscroll-behavior-y:none; }
body {
  font-family:var(--sans); color:var(--ink); background:var(--bg);
  font-size:15px; line-height:1.6; -webkit-font-smoothing:antialiased;
  -webkit-tap-highlight-color:transparent;
  min-height: 100vh;
  min-height: 100dvh;
}
a { color:var(--accent); }
button, input, select, textarea { font-family:inherit; font-size:inherit; color:inherit; }
.top, .btn, .pill, .overline { -webkit-user-select:none; user-select:none; }

/* ---------------------------------------------------------------- shell */
.top {
  position:sticky; top:0; z-index:40;
  padding-top:var(--sat);
  background:linear-gradient(180deg, #0B1114 0%, var(--surface) 100%);
  border-bottom:1px solid var(--line-soft);
}
.top-in {
  max-width:1180px; margin:0 auto;
  padding:18px max(var(--gut), var(--sar)) 18px max(var(--gut), var(--sal));
  display:flex; align-items:center; gap:18px;
}
.top .spacer { flex:1; }
.who { font-size:.86rem; color:var(--muted); }
.wrap {
  max-width:1180px; margin:0 auto;
  padding:30px max(var(--gut), var(--sar)) calc(80px + var(--sab)) max(var(--gut), var(--sal));
}

/* ---------------------------------------------------------------- lockup */
/* THE OVERLAP BUG, AND WHY IT WAS AN OVERLAP RATHER THAN AN OVERFLOW.
   `.lockup` carries `min-width:0`, which lets the flex algorithm shrink the BOX
   below its content. The images keep their intrinsic width, spill out of it, and
   draw underneath the buttons. So the masthead did not push the buttons off the
   edge, it silently stacked them on top of the wordmarks.
   Two fixes, both needed: the marks never shrink, and below 720 they are icons
   small enough that there is nothing to shrink. */
.lockup { display:flex; align-items:center; gap:15px; text-decoration:none; min-width:0; }
.lockup img { display:block; width:auto; height:21px; opacity:.95; flex:0 0 auto; }
.lg-house, .lg-agencies { flex:0 0 auto; }

/* Hidden until the breakpoint. The element is named in the selector on purpose:
   `.lockup img` is (0,1,1) and a bare `.lg-mina-icon` is (0,1,0), so a bare rule
   LOSES to it regardless of source order and the icon renders at full size
   beside the wordmark on desktop. That exact trap has now cost a pass on three
   separate surfaces. */
.lockup img.lg-mina-icon,
.lockup img.lg-dmc-icon { display:none; }

/* Refresh keeps its glyph and loses its word when the masthead runs out of room. */
#refresh .ic { font-size:1.02rem; line-height:1; }
#refresh .lbl { margin-left:1px; }
.lg-dot { width:3px; height:3px; border-radius:50%; background:rgba(148,165,173,.5); flex:0 0 auto; }
.lg-cap {
  font-size:.58rem; font-weight:700; letter-spacing:.2em; text-transform:uppercase;
  color:var(--faint); white-space:nowrap; line-height:1;
}
.lg-house { display:flex; flex-direction:column; gap:7px; }
.lg-agencies { display:flex; align-items:center; gap:14px; }

/* ---------------------------------------------------------------- type */
h1 { font-family:var(--brand); font-size:1.62rem; font-weight:700; letter-spacing:-.022em; margin:0 0 4px; }
h2 { font-family:var(--brand); font-size:1.04rem; font-weight:600; margin:0 0 10px; }
.sub { color:var(--muted); margin:0 0 26px; }
.overline {
  font-size:.66rem; font-weight:700; letter-spacing:.13em; text-transform:uppercase;
  color:var(--faint); margin:0 0 10px;
}

/* ---------------------------------------------------------------- buttons */
.btn {
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  border-radius:var(--pill); border:1.5px solid transparent; cursor:pointer;
  font-weight:700; font-size:.9rem; padding:10px 20px;
  background:var(--accent); color:#08121F; text-decoration:none; white-space:nowrap;
  transition:transform .14s ease, background .14s ease, border-color .14s ease;
}
.btn:hover { transform:translateY(-1px); background:#8FC6FF; }
.btn[disabled] { opacity:.45; cursor:not-allowed; transform:none; }
.btn.ghost { background:transparent; color:var(--ink); border-color:var(--line); }
.btn.ghost:hover { background:var(--raised); border-color:var(--faint); }
.btn.sm { padding:7px 14px; font-size:.83rem; }

/* ---------------------------------------------------------------- forms */
label.f { display:block; margin:0 0 16px; }
label.f > span {
  display:block; font-size:.79rem; font-weight:700; color:var(--muted);
  margin-bottom:6px;
}
.inp {
  width:100%; padding:12px 14px; border:1.5px solid var(--line); border-radius:var(--r);
  background:var(--surface-2); color:var(--ink);
  transition:border-color .14s ease, box-shadow .14s ease;
}
.inp:focus {
  outline:none; border-color:var(--accent); box-shadow:0 0 0 4px rgba(113,182,255,.18);
}
/* A field under 16px makes iOS zoom the whole page when you tap it, and it does
   not zoom back out. Desktop keeps 15px, where the problem does not exist. */
@media (hover: none) and (pointer: coarse) { .inp { font-size:16px; } }

/* ---------------------------------------------------------------- pills */
.pill {
  display:inline-flex; align-items:center; gap:6px; border-radius:var(--pill);
  padding:4px 11px; font-size:.72rem; font-weight:700; letter-spacing:.02em;
  background:var(--raised); color:var(--muted); border:1px solid var(--line);
  white-space:nowrap;
}
.pill.up      { background:rgba(79,178,134,.12); border-color:rgba(79,178,134,.35); color:var(--ok); }
.pill.problem { background:rgba(217,108,99,.12); border-color:rgba(217,108,99,.35); color:var(--alert); }
.pill.unknown { background:var(--raised); border-color:var(--line); color:var(--faint); }
.pill.ag {
  background:transparent; border-color:var(--line-soft); color:var(--faint);
  font-size:.62rem; letter-spacing:.06em; text-transform:uppercase; padding:3px 8px;
}

/* ---------------------------------------------------------------- the grid */
.grid {
  display:grid; gap:16px;
  grid-template-columns:repeat(auto-fill, minmax(290px, 1fr));
}

/* One client. The whole card is the button, because the only thing you ever
   want to do with a client here is go into their desk. */
.card {
  position:relative; display:flex; flex-direction:column; gap:0;
  background:var(--surface); border:1px solid var(--line); border-radius:20px;
  padding:0; overflow:hidden; cursor:pointer; text-align:left;
  color:inherit; font:inherit; width:100%;
  transition:border-color .16s ease, transform .16s ease, box-shadow .16s ease;
}
.card:hover {
  transform:translateY(-2px); border-color:var(--faint);
  box-shadow:0 18px 40px -24px rgba(0,0,0,.9);
}
.card:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
.card[disabled] { cursor:not-allowed; opacity:.55; transform:none; }

/* The client's own colour, as a hairline at the top of their card. The only
   place a client's palette appears in this console, which is enough to tell
   them apart at a glance and not enough to make the console look like theirs. */
.card .tint { height:3px; width:100%; background:var(--faint); }

.card .mark {
  padding:22px 22px 16px; display:flex; align-items:center; min-height:76px;
}
.card .mark img { max-height:30px; max-width:74%; width:auto; display:block; }
.card .mark .fallback {
  font-family:var(--brand); font-weight:700; font-size:1.12rem; letter-spacing:-.02em;
}

.card .body { padding:0 22px 20px; display:flex; flex-direction:column; gap:12px; flex:1; }
.card .nm { font-weight:700; font-size:1.02rem; letter-spacing:-.01em; }
.card .meta { font-size:.8rem; color:var(--faint); }
.card .row { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }

/* The number. This is the one thing on the card that should pull the eye, and
   only when it is not zero. */
.card .waiting {
  display:flex; align-items:baseline; gap:9px; margin-top:2px;
  padding-top:13px; border-top:1px solid var(--line-soft);
}
.card .waiting b {
  font-family:var(--brand); font-size:1.55rem; font-weight:700; line-height:1;
  color:var(--warn); letter-spacing:-.02em;
}
.card .waiting.clear b { color:var(--faint); font-size:1.1rem; }
.card .waiting span { font-size:.82rem; color:var(--muted); }

/* ---------------------------------------------------------------- misc */
.err {
  background:rgba(217,108,99,.1); border:1px solid rgba(217,108,99,.35); color:var(--alert);
  border-radius:var(--r); padding:11px 14px; margin-bottom:14px; font-size:.9rem;
}
.okmsg {
  background:rgba(79,178,134,.1); border:1px solid rgba(79,178,134,.35); color:var(--ok);
  border-radius:var(--r); padding:11px 14px; margin-bottom:14px; font-size:.9rem;
}
.empty {
  background:var(--surface); border:1px dashed var(--line); border-radius:20px;
  padding:56px 26px; text-align:center; color:var(--faint);
}
.hide { display:none !important; }
.muted { color:var(--muted); }
.small { font-size:.84rem; }
.spin {
  display:inline-block; width:15px; height:15px; border:2px solid rgba(8,18,31,.35);
  border-top-color:#08121F; border-radius:50%; animation:sp .7s linear infinite;
}
.btn.ghost .spin { border-color:rgba(233,239,241,.3); border-top-color:var(--ink); }
@keyframes sp { to { transform:rotate(360deg); } }
.credit {
  text-align:center; margin-top:44px; padding-top:22px;
  border-top:1px solid var(--line-soft); color:var(--faint); font-size:.76rem;
}

@media (max-width:720px) {
  :root { --gut:16px; }
  .top-in { padding-top:13px; padding-bottom:13px; gap:10px; }
  .who { display:none; }
  .grid { grid-template-columns:1fr; }
  h1 { font-size:1.4rem; }
  /* Two wordmarks and three buttons do not fit a phone. The marks become their
     icons, which is enough for ours to be present, and the buttons keep their
     labels because they are the things you actually tap. */
  .lg-house { display:none; }
  .lockup img.lg-mina-icon,
  .lockup img.lg-dmc-icon { display:block; height:22px; }
  .lockup { gap:11px; }
}
@media (max-width:560px) {
  /* Next to go is the word on Refresh, not the action. */
  #refresh .lbl { display:none; }
  #refresh { padding:7px 12px; }
  .top-in { gap:8px; }
  .lockup { gap:9px; }
  .lockup img.lg-mina-icon,
  .lockup img.lg-dmc-icon { height:20px; }
}
@media (max-width:400px) {
  :root { --gut:13px; }
  .top-in { gap:7px; padding-left:13px; padding-right:13px; }
  .top .btn.sm { padding:6px 10px; font-size:.78rem; }
  .lockup img.lg-mina-icon,
  .lockup img.lg-dmc-icon { height:19px; }
}
@media (max-width:350px) {
  /* At 320 there is genuinely not room for two house marks and three controls.
     DMC yields and MINA stays: one mark is enough to say whose console this is,
     and both are named in the footer credit on the same page. */
  .lockup img.lg-dmc-icon, .lg-dot { display:none; }
  .top .btn.sm { padding:6px 9px; font-size:.74rem; }
}

/* Installed to the home screen, iOS draws the page under the status bar. On a
   phone WITHOUT a notch it still does that but reports a zero inset, so the
   masthead needs a floor or it sits under the clock. Scoped to iOS standalone,
   because Android puts its status bar above the viewport and reports zero
   correctly. */
@media (display-mode: standalone) {
  @supports (-webkit-touch-callout: none) {
    .top { padding-top: max(var(--sat), 20px); }
    body.auth { padding-top: calc(24px + max(var(--sat), 20px)); }
  }
}

/* ---------------------------------------------------------------- login */
body.auth {
  min-height:100vh; min-height:100dvh;
  display:flex; justify-content:center; align-items:flex-start;
  background:
    radial-gradient(80% 60% at 76% 4%, rgba(113,182,255,.10) 0%, transparent 58%),
    var(--bg);
  padding-top:calc(24px + var(--sat)); padding-bottom:calc(24px + var(--sab));
  padding-left:max(24px, var(--sal)); padding-right:max(24px, var(--sar));
}
body.auth > .box { margin-block:auto; width:100%; max-width:392px; }
.panel {
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r-lg);
  padding:28px 26px; box-shadow:0 30px 70px -34px rgba(0,0,0,.95);
}
.auth-lockup {
  display:flex; flex-direction:column; align-items:center; gap:18px; margin-bottom:26px;
}
.auth-lockup .lg-agencies img { height:24px; }
.auth-title {
  font-family:var(--brand); font-weight:700; font-size:1.1rem; letter-spacing:-.02em;
  color:var(--ink);
}
@media (max-height: 640px) {
  body.auth { padding-top:calc(14px + var(--sat)); padding-bottom:calc(14px + var(--sab)); }
  .auth-lockup { gap:13px; margin-bottom:17px; }
  .auth-lockup .lg-agencies img { height:20px; }
  .panel { padding:21px 20px; }
}
