@font-face{font-family:'Oxanium';font-style:normal;font-weight:500 800;font-display:swap;src:url(/portal/fonts/oxanium.woff2) format('woff2');}
@font-face{font-family:'Saira';font-style:normal;font-weight:400 700;font-display:swap;src:url(/portal/fonts/saira.woff2) format('woff2');}
@font-face{font-family:'Share Tech Mono';font-style:normal;font-weight:400;font-display:swap;src:url(/portal/fonts/share-tech-mono.woff2) format('woff2');}

/*
 * Hangar Cloud — portal design system
 * ------------------------------------
 * Concept: an aircraft hangar at night, running a pre-flight checklist.
 * Dark "hangar at night" ground; one orange accent (--pista), used only for
 * the primary call-to-action and the single current checklist step, plus the
 * small static wordmark accent in the chrome (brand mark, not a CTA). Every
 * other surface is a quiet, flat panel: hairline borders, generous padding,
 * no gradients, no shadows beyond a hairline.
 *
 * No @import, no external fonts, no light mode — the portal is always dark.
 */

:root {
  /* ---- Hangar palette (gunmetal ground, orange action, steel-blue system) ---- */
  --noturno: #121316;       /* page background (canvas) */
  --fuselagem: #1a1c20;     /* panels (raised) */
  --fuselagem-2: #26282d;   /* raised/hover surfaces, hairline borders (overlay) */
  --concreto: #edeef0;      /* primary text */
  --concreto-dim: #b4b6bb;  /* muted text, pending state */
  --pista: #f26522;         /* THE single accent — CTA + current step ONLY (orange) */
  --pista-hot: #ff8000;     /* accent hover */
  --pista-glow: #ffbe1d;    /* accent highlight */
  --pista-deep: #c86400;    /* accent shadow / hazard */
  --system: #69aad7;        /* steel-blue "system voice": links, tenant domain, in-progress */
  /* --verde-pista and --alerta nudged lighter from the original #3daa6d/#e5533d —
     measured (WCAG relative-luminance formula): as chip text on their own
     rgba(…, 0.14) tinted fill, composited over the header's gradient top
     stop (#20242b, the palest real backdrop a chip renders on — see
     .app-header__status), the originals only hit 4.29:1 / 3.57:1, below the
     4.5:1 small-text floor. These nudges clear 4.5:1 against every real
     backdrop (fuselagem panels, header gradient top+bottom) with margin;
     see task-4-report.md for the full computed table. */
  --verde-pista: #4db179;   /* running / paid / active */
  --alerta: #ec806f;        /* failed / overdue / suspended */

  /* ---- rgb triples for tinted/translucent fills (kept in sync with the hexes above) ---- */
  --verde-pista-rgb: 77, 177, 121;
  --alerta-rgb: 236, 128, 111;
  --pista-rgb: 242, 101, 34;
  --system-rgb: 105, 170, 215;

  /* ---- structural scale (unchanged) ---- */
  --space-1: 0.25rem; --space-2: 0.5rem; --space-3: 0.75rem; --space-4: 1rem;
  --space-5: 1.5rem; --space-6: 2rem; --space-7: 3rem;
  --radius: 6px;
  --radius-pill: 999px;
  --hairline: 1px solid var(--fuselagem-2);
  --transition-fast: 120ms ease;
  --transition-slow: 1.6s ease-in-out;
  --font-display: 'Oxanium', system-ui, sans-serif;
  --font-ui: 'Saira', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono: 'Share Tech Mono', ui-monospace, 'Cascadia Code', Consolas, monospace;

  /* ---- self-contained textures (inline, no external assets) ---- */
  --tex-noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.035 0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
  --tex-sweep: linear-gradient(100deg,transparent 18%,rgba(255,255,255,.04) 36%,rgba(255,255,255,.10) 50%,rgba(255,255,255,.04) 64%,transparent 82%);
  --tex-hairlines: repeating-linear-gradient(180deg,rgba(255,255,255,.026) 0 1px,transparent 1px 3px,rgba(0,0,0,.05) 3px 4px,transparent 4px 7px);
  --tex-hazard: repeating-linear-gradient(-45deg,var(--pista-deep) 0 10px,#17130c 10px 20px);
}

/* ==================================================================
   Reset & base
   ================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
}

html {
  color-scheme: dark;
}

body {
  min-height: 100vh;
  background: var(--noturno);
  background-image: var(--tex-noise);
  color: var(--concreto);
  font-family: var(--font-ui);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1,
h2,
h3,
h4,
p,
ol,
ul,
figure {
  margin: 0;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: 0.01em;
}

ol,
ul {
  list-style: none;
  padding: 0;
}

a:not(.btn) {
  color: var(--system);
}

a:not(.btn):hover {
  color: #8ec4e6;
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

img,
svg {
  max-width: 100%;
  display: block;
}

/* All data — app names, ids, connection strings, logs, tokens — is mono.
   overflow-wrap lets an unbroken identifier (a 63-char db/app name, a token
   label) wrap inside its own table cell/panel instead of forcing the table
   or panel wider than the viewport (real risk at 360px in databases.tsx,
   access.tsx, apps-list.tsx). It's a no-op on `pre`, whose `white-space: pre`
   already suppresses wrapping — those get their own overflow-x fix below. */
.mono,
code,
pre,
kbd {
  font-family: var(--font-mono);
  font-size: 0.94em;
  overflow-wrap: anywhere;
}

/* Long single-line pre content — connection strings (databases.tsx),
   tokens/MCP command+JSON (access.tsx), build/runtime logs (app-detail.tsx)
   — must scroll within their own box rather than being silently clipped by
   the ancestor `.panel`'s `overflow: hidden`. That ancestor rule already
   keeps the *page* from ever scrolling sideways, but without this, the
   secret/log content past the panel edge would just be cut off and
   unreadable instead of reachable. */
pre {
  overflow-x: auto;
}

/* ==================================================================
   Accessibility floor: skip-link, focus-visible, reduced motion
   ================================================================== */

.skip-link {
  position: absolute;
  top: -3rem;
  left: var(--space-4);
  z-index: 100;
  background: var(--fuselagem-2);
  color: var(--concreto);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius);
  text-decoration: none;
  transition: top var(--transition-fast);
}

.skip-link:focus {
  top: var(--space-4);
}

:focus-visible {
  outline: 2px solid var(--pista);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ==================================================================
   Signage — tracked-uppercase section labels
   ================================================================== */

.signage {
  display: flex;
  align-items: center;
  gap: 0.6em;
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 0.72rem;
  color: var(--concreto-dim);
  font-weight: 600;
  margin-bottom: var(--space-3);
}

.signage::before {
  content: "";
  width: 5px;
  height: 5px;
  background: var(--system);
  transform: rotate(45deg);
  flex: none;
}

/* ==================================================================
   Page chrome: header, nav, main
   ================================================================== */

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.app-header {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3) var(--space-5);
  padding: var(--space-4) var(--space-4);
  background: linear-gradient(180deg, #20242b, #171a1f);
  border-bottom: 1px solid #000;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.08);
}

.app-header::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: var(--tex-hairlines); opacity: .7;
}

.app-header::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: var(--tex-sweep); mix-blend-mode: screen;
}

.app-header > * { position: relative; z-index: 1; }

.app-header__brand {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin-right: auto;
}

.wordmark {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.25rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--concreto);
  line-height: 1;
}

.wordmark__accent {
  color: var(--pista);
  font-weight: 800;
}

.app-header__tenant {
  font-family: var(--font-mono);
  color: var(--system);
}

.app-header__status {
  order: 0;
}

.app-header__logout {
  margin: 0;
}

.app-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  padding: 0 var(--space-3);
  background: #141619;
  border-bottom: 1px solid #000;
}

.app-nav a {
  font-family: var(--font-ui);
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: var(--space-3) var(--space-3);
  border-radius: 0;
  border-bottom: 2px solid transparent;
  text-decoration: none;
  color: var(--concreto-dim);
  transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
}

.app-nav a:hover {
  background: transparent;
  color: var(--concreto);
  border-bottom-color: var(--pista);
}

.app-main {
  flex: 1;
  width: 100%;
  padding: var(--space-5) var(--space-4) var(--space-7);
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

@media (min-width: 640px) {
  .app-header {
    flex-wrap: nowrap;
  }

  .app-main {
    padding: var(--space-6) var(--space-6) var(--space-7);
  }
}

@media (min-width: 960px) {
  .app-main {
    max-width: 72rem;
    margin: 0 auto;
    width: 100%;
  }
}

/* A grid of panels collapses to one column below ~560px automatically —
   no breakpoint needed, but the rule below documents the 360px floor
   explicitly per the design's quality bar. */
.panel-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: var(--space-5);
}

/* Wide-content panels (tables, MCP command/JSON blocks) span the full row —
   the auto-fit card columns crush them into one-word-per-line wrapping. */
.panel--wide {
  grid-column: 1 / -1;
}

@media (max-width: 359.98px) {
  .panel-grid {
    grid-template-columns: 1fr;
  }

  .app-header {
    flex-direction: column;
    align-items: flex-start;
  }

  .app-header__logout {
    align-self: stretch;
  }

  .app-header__logout .btn {
    width: 100%;
  }
}

/* ==================================================================
   Panel — the quiet flat surface
   ================================================================== */

.panel {
  position: relative;
  background: var(--fuselagem);
  border: var(--hairline);
  border-radius: var(--radius);
  padding: var(--space-5);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.03);
  overflow: hidden;
}

.panel::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--tex-noise);
  opacity: .6;
  pointer-events: none;
}

.panel > * {
  position: relative;
}

.panel__body {
  color: var(--concreto);
}

/* ==================================================================
   Chip — status pill. Color communicates state; orange is reserved for CTAs and the current step.
   ================================================================== */

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  padding: 0.32em 0.75em;
  border-radius: var(--radius-pill);
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
}

.chip__dot {
  width: 0.5em;
  height: 0.5em;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

.chip--ok {
  color: var(--verde-pista);
  background: rgba(var(--verde-pista-rgb), 0.14);
}

.chip--bad {
  color: var(--alerta);
  background: rgba(var(--alerta-rgb), 0.14);
}

.chip--muted {
  color: var(--concreto-dim);
  background: var(--fuselagem-2);
}

/* "warn" = transitional / in-progress. Signalled by motion, not by the
   orange accent (--pista), which stays reserved for the primary CTA + current step. */
.chip--warn {
  color: var(--concreto);
  background: var(--fuselagem-2);
}

.chip--warn .chip__dot {
  animation: chip-pulse var(--transition-slow) infinite;
}

@keyframes chip-pulse {
  0%,
  100% {
    opacity: 0.35;
  }
  50% {
    opacity: 1;
  }
}

/* ==================================================================
   Buttons — one primary (orange) CTA style, everything else quiet
   ================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 0.6em 1.1em;
  border-radius: var(--radius);
  border: var(--hairline);
  background: transparent;
  color: var(--concreto);
  font-size: 0.94rem;
  font-weight: 600;
  cursor: pointer;
  transition: background var(--transition-fast), border-color var(--transition-fast),
    color var(--transition-fast);
}

.btn--ghost:hover {
  background: var(--fuselagem-2);
}

/* The primary CTA. Use at most one visible at a time per view — see the
   checklist rule below. */
.btn--primary {
  background: var(--pista);
  border-color: var(--pista);
  color: var(--noturno);
}

.btn--primary:hover {
  background: color-mix(in srgb, var(--pista) 85%, white);
  border-color: color-mix(in srgb, var(--pista) 85%, white);
}

.btn--danger {
  border-color: var(--alerta);
  color: var(--alerta);
}

.btn--danger:hover {
  background: rgba(var(--alerta-rgb), 0.12);
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ==================================================================
   Forms
   ================================================================== */

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.field label {
  font-size: 0.88rem;
  color: var(--concreto-dim);
}

/* width: 100% is a no-op where .field already fills its container via flex
   stretch (login, deploy, "criar banco"/"emitir token" forms). It's load-
   bearing in databases.tsx: each row's delete-confirm <input> sits inside a
   <table class="table"><td>, a non-flex context, where an unsized <input>'s
   native ~20-char preferred width would count toward that column's
   auto-layout sizing and could push the table past the panel at 360px. A
   percentage width resolves against the cell instead, letting the column
   (and the table) shrink to fit. */
.field input,
.field select,
.field textarea {
  width: 100%;
  background: var(--noturno);
  border: var(--hairline);
  border-radius: var(--radius);
  padding: 0.55em 0.8em;
  color: var(--concreto);
}

.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
  border-color: var(--fuselagem-2);
}

/* ==================================================================
   Table — for lists of apps, databases, invoices...
   ================================================================== */

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.92rem;
}

.table th {
  text-align: left;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 0.72rem;
  color: var(--concreto-dim);
  font-weight: 600;
  padding: var(--space-2) var(--space-3);
  border-bottom: var(--hairline);
}

.table td {
  padding: var(--space-3);
  border-bottom: var(--hairline);
  vertical-align: middle;
}

.table tr:last-child td {
  border-bottom: none;
}

/* ==================================================================
   Preflight checklist — checklist de decolagem
   The one ornamented element in the system. Six provisioning steps:
   done = checkmark + steel-blue; current = pista orange + indicator;
   pending = concreto-dim; failed = alerta red (never orange).
   ================================================================== */

.checklist {
  display: flex;
  flex-direction: column;
  counter-reset: step;
}

.checklist__item {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  counter-increment: step;
}

/* connecting line between markers */
.checklist__item:not(:last-child)::before {
  content: "";
  position: absolute;
  left: 0.6rem;
  top: 2rem;
  bottom: -0.5rem;
  width: 1px;
  background: var(--fuselagem-2);
}

.checklist__marker {
  position: relative;
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  margin-top: 0.15rem;
  border-radius: 50%;
  border: 2px solid var(--concreto-dim);
  background: var(--noturno);
  z-index: 1;
}

.checklist__label {
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 0.98rem;
  color: var(--concreto-dim);
  padding-top: 0.1rem;
}

.checklist__label::before {
  content: counter(step, decimal-leading-zero) "  ";
  color: var(--concreto-dim);
  opacity: .7;
}

/* done → steel-blue instrument tick (keep verde-pista for the "running" chip, not here) */
.checklist__item--done .checklist__marker {
  border-color: var(--system);
  background: var(--system);
}

.checklist__item--done .checklist__marker::after {
  content: "";
  position: absolute;
  left: 0.32rem;
  top: 0.16rem;
  width: 0.4rem;
  height: 0.68rem;
  border-right: 2px solid var(--noturno);
  border-bottom: 2px solid var(--noturno);
  transform: rotate(45deg);
}

.checklist__item--done .checklist__label {
  color: var(--concreto);
}

/* current: THE orange moment. Exactly one step is ever "current". */
.checklist__item--current .checklist__marker {
  border-color: var(--pista);
  background: var(--pista);
  box-shadow: 0 0 0 4px rgba(var(--pista-rgb), 0.22);
  animation: checklist-current-pulse 1.8s ease-in-out infinite;
}

.checklist__item--current .checklist__label {
  color: var(--concreto);
  font-weight: 600;
}

@keyframes checklist-current-pulse {
  0%,
  100% {
    box-shadow: 0 0 0 4px rgba(var(--pista-rgb), 0.22);
  }
  50% {
    box-shadow: 0 0 0 7px rgba(var(--pista-rgb), 0.12);
  }
}

/* pending: quiet, dim, nothing to look at yet */
.checklist__item--pending .checklist__marker {
  border-color: var(--concreto-dim);
  background: transparent;
}

.checklist__item--pending .checklist__label {
  color: var(--concreto-dim);
}

/* failed: distinct from both done and pending, red --alerta — never orange.
   Marks exactly where a broken provision stopped. */
.checklist__item--failed .checklist__marker {
  border-color: var(--alerta);
  background: var(--alerta);
}

.checklist__item--failed .checklist__marker::before,
.checklist__item--failed .checklist__marker::after {
  content: "";
  position: absolute;
  left: 0.22rem;
  top: 0.54rem;
  width: 0.78rem;
  height: 2px;
  background: var(--noturno);
}

.checklist__item--failed .checklist__marker::before {
  transform: rotate(45deg);
}

.checklist__item--failed .checklist__marker::after {
  transform: rotate(-45deg);
}

.checklist__item--failed .checklist__label {
  color: var(--alerta);
  font-weight: 600;
}

.checklist__item--failed .checklist__failed-marker {
  font-weight: 600;
}

/* ==================================================================
   Login page — direct-child selectors for hazard cap and big wordmark
   ================================================================== */

.app-main > .wordmark {
  font-size: 2rem;
  display: block;
  margin-bottom: var(--space-2);
}

/* login only: the wordmark directly precedes the login card — no other page
   has a .wordmark inside .app-main (deploy renders a bare direct-child panel). */
.app-main > .wordmark + .panel {
  position: relative;
}

.app-main > .wordmark + .panel::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--tex-hazard);
  opacity: .85;
  pointer-events: none;
}
