/* The portal's server-rendered pages (pages.py: the Live 3D, waiting and error pages; every other
   page is the browser app's, web/), in the 529 console's design: its colour tokens (dark by
   default, light when the browser asks for it), Inter, the 48 px top bar with the 529 mark, and
   its chip and button styles. Tokens are copied from the console's globals.css; keep them in
   step. */

@font-face {
  font-family: "Inter";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url("inter-latin-wght-normal.woff2") format("woff2-variations");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url("inter-latin-ext-wght-normal.woff2") format("woff2-variations");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
    U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---------------------------------------------------------------- tokens (console: .dark) */
:root {
  color-scheme: dark;
  --background: oklch(0.145 0.045 265);
  --foreground: oklch(0.95 0.008 260);
  --card: oklch(0.195 0.042 260);
  --popover: oklch(0.195 0.042 260);
  --primary: oklch(0.78 0.19 175);
  --primary-foreground: oklch(0.145 0.045 265);
  --secondary: oklch(0.24 0.05 260);
  --muted: oklch(0.18 0.04 260);
  --muted-foreground: oklch(0.65 0.025 260);
  --accent: oklch(0.26 0.05 260);
  --accent-foreground: oklch(0.82 0.015 260);
  --destructive: oklch(0.6368 0.2078 25.3313);
  --border: oklch(0.32 0.04 260);
  --input: oklch(0.32 0.04 260);
  --ring: oklch(0.78 0.19 175);
  --bar: oklch(0.16 0.042 260);
  --bar-border: oklch(0.3 0.04 260);
  --ok-soft: oklch(0.696 0.17 162.48 / 0.15);
  --ok-fg: oklch(0.765 0.177 163.223);
  --ok-border: oklch(0.696 0.17 162.48 / 0.4);
  --warn-soft: oklch(0.769 0.188 70.08 / 0.15);
  --warn-fg: oklch(0.828 0.189 84.429);
  --warn-border: oklch(0.769 0.188 70.08 / 0.4);
  --bad-soft: oklch(0.637 0.237 25.331 / 0.15);
  --bad-fg: oklch(0.704 0.191 22.216);
  --bad-border: oklch(0.637 0.237 25.331 / 0.4);
  --info-soft: oklch(0.623 0.214 259.815 / 0.15);
  --info-fg: oklch(0.707 0.165 254.624);
  --info-border: oklch(0.623 0.214 259.815 / 0.4);
  --neutral-soft: oklch(0.554 0.046 257.42 / 0.15);
  --neutral-fg: oklch(0.704 0.04 256.788);
  --neutral-border: oklch(0.554 0.046 257.42 / 0.4);
  --shadow-xs: 0 4px 8px -1px hsl(0 0% 0% / 0.05);
  --shadow-sm: 0 4px 8px -1px hsl(0 0% 0% / 0.1), 0 1px 2px -2px hsl(0 0% 0% / 0.1);
  --shadow-md: 0 4px 8px -1px hsl(0 0% 0% / 0.1), 0 2px 4px -2px hsl(0 0% 0% / 0.1);
  --shadow-lg: 0 4px 8px -1px hsl(0 0% 0% / 0.1), 0 4px 6px -2px hsl(0 0% 0% / 0.1);
  --shadow-2xl: 0 4px 8px -1px hsl(0 0% 0% / 0.25);
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --radius: 0.5rem;
  /* the console's dark: variants */
  --outline-bg: color-mix(in oklch, var(--input) 30%, transparent);
  --outline-border: var(--input);
  --outline-hover: color-mix(in oklch, var(--input) 50%, transparent);
  --ghost-hover: color-mix(in oklch, var(--accent) 50%, transparent);
  --field-bg: color-mix(in oklch, var(--input) 10%, transparent);
  --switch-off: color-mix(in oklch, var(--input) 80%, transparent);
  --switch-thumb-off: var(--foreground);
  --switch-thumb-on: var(--primary-foreground);
}
/* console :root (light) */
@media (prefers-color-scheme: light) {
  :root:not(.dark) {
    color-scheme: light;
    --background: oklch(1 0 0);
    --foreground: oklch(0.3729 0.0306 259.7328);
    --card: oklch(1 0 0);
    --popover: oklch(1 0 0);
    --primary: oklch(0.55 0.18 149.5793);
    --primary-foreground: oklch(1 0 0);
    --secondary: oklch(0.92 0.025 236.8242);
    --muted: oklch(0.93 0.0029 264.5419);
    --muted-foreground: oklch(0.551 0.0234 264.3637);
    --accent: oklch(0.92 0.0507 163.0508);
    --accent-foreground: oklch(0.3729 0.0306 259.7328);
    --destructive: oklch(0.5 0.2 25.3313);
    --border: oklch(0.85 0.0058 264.5313);
    --input: oklch(0.88 0.0058 264.5313);
    --ring: oklch(0.55 0.18 149.5793);
    --bar: oklch(1 0 0);
    --bar-border: oklch(0.85 0.0058 264.5313);
    --ok-soft: oklch(0.696 0.17 162.48 / 0.15);
    --ok-fg: oklch(0.508 0.118 165.612);
    --ok-border: oklch(0.696 0.17 162.48 / 0.3);
    --warn-soft: oklch(0.769 0.188 70.08 / 0.18);
    --warn-fg: oklch(0.555 0.163 48.998);
    --warn-border: oklch(0.769 0.188 70.08 / 0.35);
    --bad-soft: oklch(0.637 0.237 25.331 / 0.15);
    --bad-fg: oklch(0.505 0.213 27.518);
    --bad-border: oklch(0.637 0.237 25.331 / 0.3);
    --info-soft: oklch(0.623 0.214 259.815 / 0.15);
    --info-fg: oklch(0.488 0.243 264.376);
    --info-border: oklch(0.623 0.214 259.815 / 0.3);
    --neutral-soft: oklch(0.554 0.046 257.42 / 0.15);
    --neutral-fg: oklch(0.372 0.044 257.287);
    --neutral-border: oklch(0.554 0.046 257.42 / 0.3);
    --outline-bg: var(--background);
    --outline-border: var(--border);
    --outline-hover: var(--accent);
    --ghost-hover: var(--accent);
    --field-bg: transparent;
    --switch-off: var(--input);
    --switch-thumb-off: var(--background);
    --switch-thumb-on: var(--background);
  }
}

/* ---------------------------------------------------------------- base */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  min-height: 100dvh;
  background: var(--background);
  color: var(--foreground);
  font-family: "Inter", ui-sans-serif, system-ui, sans-serif;
  font-size: 14px;
  line-height: 1.5;
  letter-spacing: -0.025em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
a { color: inherit; text-decoration: none; }
[hidden] { display: none !important; }
h1, h2, h3, p { margin: 0; }
code, .id { font-size: 11px; color: var(--muted-foreground); letter-spacing: 0; }
:focus-visible { outline: 2px solid color-mix(in oklch, var(--ring) 60%, transparent); outline-offset: 2px; }
svg.i { width: 16px; height: 16px; flex: none; stroke: currentColor; fill: none; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round; }
.muted { color: var(--muted-foreground); }
.micro { font-size: 12px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.075em;
  color: color-mix(in oklch, var(--muted-foreground) 70%, transparent); }
.line { --line: color-mix(in oklch, var(--border) 60%, transparent); }
@media (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; } }

/* ---------------------------------------------------------------- shell: top bar, main */
.topbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 20;
  height: 49px; display: flex; align-items: center; gap: 8px;
  padding: 0 24px 0 12px;
  background: var(--bar); border-bottom: 1px solid var(--bar-border);
}
/* The console's breadcrumb (app-breadcrumb.tsx and its breadcrumb*.tsx primitives): 529 / Twins /
   the twin / the page. 16 px between steps and slashes; 14 px text at 90 % foreground, full on
   hover; the slash at 40 % of the muted colour; a step's icon 14 px and muted, 6 px before its
   label; a linked label underlines on hover (4 px offset). A label stops at 240 px and, when the
   bar runs out of room, the steps before the last shrink first, with an ellipsis. */
.crumbs { display: flex; align-items: center; gap: 16px; min-width: 0; font-size: 14px; line-height: 20px; }
.crumbs .home { display: flex; align-items: center; flex: none; }
.crumbs .home img { height: 18px; width: auto; display: block; }
.crumbs .sep { flex: none; color: color-mix(in oklch, var(--muted-foreground) 40%, transparent); user-select: none; }
.crumb { display: flex; align-items: center; gap: 6px; min-width: 0; flex: 0 2 auto;
  color: color-mix(in oklch, var(--foreground) 90%, transparent); }
.crumb:last-child { flex-shrink: 1; }
.crumb svg.i { width: 14px; height: 14px; color: var(--muted-foreground); }
.crumb .t { display: block; min-width: 0; max-width: 240px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; transition: color 150ms var(--ease); }
.crumb a.t:hover { color: var(--foreground); text-decoration: underline; text-underline-offset: 4px; }
/* a phone: 8 px steps, and no Twins step (the 529 mark goes to the same page) */
@media (max-width: 639px) {
  .crumbs { gap: 8px; }
  .crumbs .twins, .crumbs .twins + .sep { display: none; }
}
.spacer { flex: 1; }
.who { display: flex; align-items: center; gap: 4px; }
.avatar { width: 28px; height: 28px; border-radius: 999px; display: grid; place-items: center;
  background: var(--secondary); color: var(--accent-foreground); font-size: 11px; font-weight: 600;
  margin-right: 4px; letter-spacing: 0; }
.who .name { font-size: 13px; color: var(--muted-foreground); margin-right: 6px; }

.main { margin-left: 56px; padding-top: 49px; min-height: 100dvh;
  min-width: 0; transition: margin-left 150ms ease; }
html.rail-pinned .main { margin-left: 224px; }
.main.full, html.rail-pinned .main.full { margin-left: 0; }
@media (max-width: 767px) {
  .who .name, .btn .hide-sm { display: none; }
  .topbar { padding-right: 12px; }
}

/* ---------------------------------------------------------------- badges */
.badge { display: inline-flex; align-items: center; gap: 4px; padding: 2px 6px; border-radius: 4px;
  border: 1px solid var(--border); font-size: 13px; font-weight: 500; line-height: 1.3;
  white-space: nowrap; letter-spacing: -0.01em; }
.badge svg.i { width: 12px; height: 12px; }
.badge .dot { width: 6px; height: 6px; border-radius: 99px; background: currentColor; }
.badge.ok { background: var(--ok-soft); color: var(--ok-fg); border-color: var(--ok-border); }
.badge.warn { background: var(--warn-soft); color: var(--warn-fg); border-color: var(--warn-border); }
.badge.bad { background: var(--bad-soft); color: var(--bad-fg); border-color: var(--bad-border); }
.badge.info { background: var(--info-soft); color: var(--info-fg); border-color: var(--info-border); }
.badge.neutral { background: var(--neutral-soft); color: var(--neutral-fg); border-color: var(--neutral-border); }
.badge.ok .dot { animation: pulse 2s ease-in-out infinite; }
.badge.warn .dot { animation: pulse 1s ease-in-out infinite; }
@keyframes pulse { 50% { opacity: 0.35; } }

/* ---------------------------------------------------------------- buttons */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 40px; padding: 0 16px; border-radius: 6px; border: 1px solid transparent;
  background: transparent; color: var(--foreground); font: inherit; font-size: 14px; font-weight: 500;
  white-space: nowrap; cursor: pointer; transition: background-color 0.15s, border-color 0.15s, color 0.15s; }
.btn:has(svg.i) { padding: 0 12px; }
.btn-sm { height: 32px; padding: 0 10px; font-size: 13px; gap: 6px; }
.btn-sm:has(svg.i) { padding: 0 10px; }
.btn-soft { border-color: color-mix(in oklch, var(--primary) 50%, transparent);
  background: color-mix(in oklch, var(--primary) 10%, transparent); color: var(--primary); }
.btn-soft:hover { background: color-mix(in oklch, var(--primary) 20%, transparent); border-color: var(--primary); }
.btn-outline { border-color: var(--outline-border); background: var(--outline-bg); box-shadow: var(--shadow-xs); }
.btn-outline:hover { background: var(--outline-hover); color: var(--accent-foreground); }
.btn-primary { background: var(--primary); color: var(--primary-foreground); }
.btn-primary:hover { background: color-mix(in oklch, var(--primary) 90%, transparent); }
.btn:disabled { opacity: 0.5; pointer-events: none; }
.btn:focus-visible { outline: none; border-color: var(--ring);
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--ring) 50%, transparent); }
.btn-ghost { color: var(--muted-foreground); }
.btn-ghost:hover { background: var(--ghost-hover); color: var(--foreground); }
.btn-danger { color: var(--bad-fg); }
.btn-danger:hover { background: var(--bad-soft); color: var(--bad-fg); }
form.inline { display: inline; margin: 0; }

/* ---------------------------------------------------------------- notes */
.panel { border-radius: 6px; border: 1px solid color-mix(in oklch, var(--border) 40%, transparent);
  background: color-mix(in oklch, var(--card) 30%, transparent); padding: 0 12px; }
.section { display: grid; gap: 10px; margin-bottom: 28px; }
.section > .micro { margin-bottom: 2px; }
.note { display: flex; gap: 8px; align-items: flex-start; padding: 10px 12px; border-radius: 6px; font-size: 13px;
  border: 1px solid color-mix(in oklch, var(--border) 40%, transparent);
  background: color-mix(in oklch, var(--card) 30%, transparent); color: var(--muted-foreground); }
.note.bad { border-color: var(--bad-border); background: var(--bad-soft); color: var(--bad-fg); }
.note.warn { border-color: var(--warn-border); background: var(--warn-soft); color: var(--warn-fg); }
.note.warn b, .note b { font-weight: 600; }
.note > div { min-width: 0; line-height: 1.5; }

/* ---------------------------------------------------------------- waiting, errors */
.center { min-height: calc(100dvh - 49px); display: grid; place-items: center; padding: 24px 16px; }
.state { max-width: 420px; text-align: center; display: grid; gap: 12px; justify-items: center; }
.state h1 { font-size: 20px; font-weight: 600; }
.state p { color: var(--muted-foreground); font-size: 13px; }
.spinner { width: 28px; height: 28px; border-radius: 99px; border: 2px solid var(--border);
  border-top-color: var(--primary); animation: spin 0.8s linear infinite; }
.spinner.sm { width: 14px; height: 14px; }
@keyframes spin { to { transform: rotate(360deg); } }
.state .code { font-size: 48px; font-weight: 700; line-height: 1; letter-spacing: -0.04em;
  background: linear-gradient(110deg, #00b7ef, #32cd32); -webkit-background-clip: text; background-clip: text;
  color: transparent; }

/* ---------------------------------------------------------------- dialog close button
   the console's Dialog close (dialog.tsx), on the Live 3D information panel */
.dialog-close { position: absolute; top: 16px; right: 16px; display: flex; padding: 0; border: 0;
  background: transparent; color: var(--foreground); border-radius: 2px; opacity: 0.7; cursor: pointer;
  transition: opacity 150ms var(--ease); }
.dialog-close:hover { opacity: 1; }
.dialog-close:focus-visible { outline: none; opacity: 1;
  box-shadow: 0 0 0 2px var(--background), 0 0 0 4px var(--ring); }

/* ---------------------------------------------------------------- the live 3D page */
.v3d { display: flex; flex-direction: column; height: calc(100dvh - 49px); }
/* on the stream: translucent chips readable in both themes; the layer itself lets the mouse
   through to the stream, only the chips take it */
.v3d-chip { position: absolute; z-index: 4; display: flex; align-items: center; gap: 6px;
  padding: 4px; border-radius: 8px; border: 1px solid color-mix(in oklch, var(--border) 70%, transparent);
  background: color-mix(in oklch, var(--background) 72%, transparent);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); color: var(--foreground); }
.v3d-chip[hidden] { display: none; }
.v3d-status { left: 12px; bottom: 12px; padding: 4px 6px; flex-wrap: wrap; font-size: 12px;
  max-width: calc(100% - 24px); }
.v3d-actions { top: 12px; right: 12px; }
.v3d-actions form { display: contents; }
.v3d-act { display: grid; place-items: center; width: 32px; height: 32px; padding: 0; border: 0;
  border-radius: 6px; background: transparent; color: var(--foreground); opacity: 0.8; cursor: pointer;
  transition: opacity 150ms var(--ease), background-color 150ms var(--ease); }
.v3d-act:hover { opacity: 1; background: color-mix(in oklch, var(--foreground) 10%, transparent); }
.v3d-act:focus-visible { outline: none; opacity: 1; box-shadow: 0 0 0 2px var(--ring); }
.v3d-act .i { width: 16px; height: 16px; }
.v3d-act .on-full, .v3d-stage:fullscreen .v3d-act .on-normal { display: none; }
.v3d-stage:fullscreen .v3d-act .on-full { display: block; }
.v3d-stage:fullscreen { width: 100vw; height: 100vh; }
/* the information panel takes the right-hand side; the actions sit left of it */
.v3d-stage:has(.v3d-info:not([hidden])) .v3d-actions { right: calc(min(400px, 100%) + 12px); }
.v3d-info-x { position: static; flex: none; margin-top: 2px; }
.v3d-stage { position: relative; flex: 1; min-height: 0; background: var(--background); }
.v3d-stage .center { min-height: 100%; }
.v3d-state[hidden], .v3d-state [hidden] { display: none; }
.v3d-frame { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; }
.v3d-frame[hidden] { display: none; }
/* the 3D page: what is happening while 3D starts, the status line, the information panel */
.v3d-frame.loading { visibility: hidden; }
.v3d .state { max-width: 520px; width: 100%; justify-items: stretch; text-align: left; }
.v3d .state h1 { text-align: center; }
.v3d-steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px;
  border: 1px solid color-mix(in oklch, var(--border) 60%, transparent); }
.v3d-step { display: grid; grid-template-columns: 20px 150px 1fr auto; align-items: center; gap: 10px;
  padding: 9px 12px; font-size: 13px; }
.v3d-step + .v3d-step { border-top: 1px solid color-mix(in oklch, var(--border) 40%, transparent); }
.v3d-step .mark { display: grid; place-items: center; }
.v3d-step .mark .i { width: 16px; height: 16px; }
.v3d-step .mark .dot { width: 7px; height: 7px; border-radius: 99px; background: var(--border); }
.v3d-step .label { font-weight: 500; color: var(--foreground); }
.v3d-step .detail { color: var(--muted-foreground); }
.v3d-step .time { color: var(--muted-foreground); font-variant-numeric: tabular-nums; font-size: 12px; white-space: nowrap; }
.v3d-step.done .mark { color: var(--ok-fg); }
.v3d-step.failed .mark, .v3d-step.failed .detail { color: var(--bad-fg); }
.v3d-step.waiting .label { color: var(--muted-foreground); }
.v3d-note { text-align: center; }
.v3d-admin { text-align: center; font-size: 12px; color: var(--muted-foreground); }
.v3d-state [data-retry] { justify-self: center; }
.v3d-health { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.v3d-health[hidden] { display: none; }
.v3d-info { position: absolute; top: 0; right: 0; bottom: 0; width: min(400px, 100%); overflow-y: auto;
  background: var(--card); border-left: 1px solid var(--border); z-index: 3; }
.v3d-info[hidden] { display: none; }
.v3d-info-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px;
  padding: 12px 12px 8px 16px; }
.v3d-info-tag { font-size: 16px; font-weight: 600; }
.v3d-info-name { font-size: 13px; color: var(--muted-foreground); }
.v3d-info-state { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; padding: 0 16px 10px; }
.v3d-info-state[hidden], .v3d-info-links[hidden] { display: none; }
.v3d-key { font-size: 13px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.v3d-key .muted { color: var(--muted-foreground); }
.v3d-info-links { display: flex; gap: 6px; padding: 0 16px 12px;
  border-bottom: 1px solid color-mix(in oklch, var(--border) 60%, transparent); }
.v3d-info-body { padding: 0 0 16px; }
/* sections fold like a properties panel's: a chevron and a title, then compact label / value
   rows edge to edge (no margin, border or rounding beside the table); numbers in monospace and
   units in their own right-hand column */
.v3d-sec { border-top: 1px solid color-mix(in oklch, var(--border) 60%, transparent); }
.v3d-sec-h { display: flex; align-items: center; gap: 6px; width: 100%; padding: 8px 16px 8px 10px;
  border: 0; background: color-mix(in oklch, var(--muted) 60%, transparent); color: var(--foreground);
  font: inherit; font-size: 12px; font-weight: 600; text-align: left; cursor: pointer; }
.v3d-sec-h:hover { background: var(--accent); }
.v3d-sec-h:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--ring); }
.v3d-sec-h .i { width: 14px; height: 14px; transform: rotate(-90deg); transition: transform 150ms var(--ease);
  color: var(--muted-foreground); }
.v3d-sec.open .v3d-sec-h .i { transform: none; }
.v3d-sec-n { margin-left: auto; font-weight: 400; color: var(--muted-foreground); font-variant-numeric: tabular-nums; }
.v3d-sec:not(.open) .v3d-kv { display: none; }
.v3d-kv { width: 100%; border-collapse: collapse; font-size: 12px; line-height: 1.35; }
.v3d-kv th { text-align: left; font-weight: 400; color: var(--muted-foreground); padding: 4px 8px 4px 16px;
  vertical-align: top; width: 46%; }
.v3d-kv td { padding: 4px 0; text-align: right; overflow-wrap: anywhere; }
.v3d-kv td.u { width: 1%; white-space: nowrap; padding: 4px 16px 4px 6px; color: var(--muted-foreground); text-align: left; }
.v3d-kv .n { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-variant-numeric: tabular-nums; }
.v3d-kv td .badge { vertical-align: 1px; }
.v3d-kv tr + tr { border-top: 1px solid color-mix(in oklch, var(--border) 30%, transparent); }
.v3d-kv tr.g th { padding-top: 8px; font-size: 11px; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--muted-foreground); }
.v3d-kv tr.d td, .v3d-kv tr.a td, .v3d-kv tr.f td { text-align: left; padding: 6px 16px; }
.v3d-kv tr.d td, .v3d-kv tr.f td { color: var(--muted-foreground); }
.v3d-key .n { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
