/* Teragrid shell layout.
 *
 * The structural half of the ported design. `teragrid-theme.js` computes the
 * colour tokens; this file is the geometry that reads them.
 *
 * EVERY NUMBER HERE IS FROM THE PROTOTYPE, not chosen. The rail is 64px because
 * its layout maths subtracts exactly 64 when working out available room; the
 * side panel clamps to 196–400 because that is the drag range; the chat column
 * appears at 780px and the narrow breakpoint is 1180px. test_theme_tokens.py
 * asserts these against the prototype's own source, so a "tidied" number fails
 * a test rather than quietly reflowing the app.
 *
 * THE ONE IDEA THIS LAYOUT ENCODES
 * --------------------------------
 * The customer's system renders LIGHT inside Teragrid's dark chrome. "Your
 * system" and "our tool" must never read as one surface — so the system frame
 * takes its own token family (--k-sys*), tinted by the template it came from,
 * and never inherits the shell's palette.
 */

:root {
  /* Global icon rail. The layout maths subtracts exactly this. */
  --k-rail: 64px;
  /* Resizable side panel; the drag handler clamps to these. */
  --k-side: 244px;
  --k-side-min: 196px;
  --k-side-max: 400px;
  /* Build / Integrate panel beside the sandbox. */
  --k-panel: 348px;
  /* Chat column, present only above --k-bp-chat. */
  --k-chat: 420px;
  /* Breakpoints, named so the numbers are not repeated in media queries. */
  --k-bp-chat: 780px;
  --k-bp-narrow: 1180px;
  --k-gap: 12px;
  --k-pad: 14px;
  --k-radius: 20px;
}

/* The viewer's own theme decides nothing here: the portal is explicitly
   themed by teragrid-theme.js, so both colours are always painted rather
   than inherited from the host. */
/* The HTML `hidden` attribute must actually hide.
 *
 * A browser's built-in rule is `[hidden] { display: none }`, which any class
 * selector setting an explicit display beats on specificity. Every layout
 * class here sets one - .tg-main is flex, .mk-modal is grid - so `hidden`
 * silently did nothing and every view rendered at once, with the consent modal
 * permanently open on top of them.
 *
 * !important rather than raising specificity everywhere: `hidden` means hidden,
 * and there is no case in this app where a layout rule should win against it.
 */
[hidden] {
  display: none !important;
}

html, body {
  height: 100%;
  margin: 0;
  background: var(--k-bg, #EEF2FB);
  color: var(--k-text, #16224A);
}

/* Typography is part of the theme, not decoration. These are the prototype's
   exact declarations - "Figtree", system-ui, sans-serif at 13.5px with
   antialiasing, and IBM Plex Mono wherever it uses monospace. Substituting a
   system stack changes metrics, weight and rhythm on every screen, so it is
   not a detail that can be approximated. */
body {
  font-family: "Figtree", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  font-size: 13.5px;
}

code, kbd, samp, pre, .tg-mono {
  font-family: "IBM Plex Mono", monospace;
}

/* Ambient wash sits behind everything and must not intercept clicks. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  background: var(--k-ambient, none);
  pointer-events: none;
  z-index: 0;
}

.tg-shell {
  position: relative;
  z-index: 1;
  display: flex;
  height: 100vh;
  min-height: 0;
  overflow: hidden;
}

/* ── the global rail ──────────────────────────────────────────────────── */

.tg-rail {
  flex: 0 0 var(--k-rail);
  width: var(--k-rail);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 12px 0;
  min-height: 0;
}

.tg-rail__spacer { flex: 1 1 auto; }

.tg-rail__btn {
  width: 38px;
  height: 38px;
  flex: 0 0 38px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 12px;
  background: transparent;
  color: var(--k-muted, #6C7C9C);
  cursor: pointer;
  position: relative;
}

.tg-rail__btn:hover { background: var(--k-soft2, #F1F5FC); }

.tg-rail__btn[aria-current="page"] {
  background: var(--k-warmSoft, #FFF1E7);
  color: var(--k-accent, #F26A1B);
  box-shadow: var(--k-activeEdge, 0 2px 8px rgba(23, 49, 99, 0.08));
}

/* The update dot on Marketplace. Non-interactive so it cannot eat the click. */
.tg-rail__dot {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--k-accent, #F26A1B);
  pointer-events: none;
}

/* ── side panel, main column, right panel ─────────────────────────────── */

.tg-side {
  flex: 0 0 var(--k-side);
  width: var(--k-side);
  min-width: var(--k-side-min);
  max-width: var(--k-side-max);
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

.tg-main {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  padding: var(--k-pad) var(--k-pad) var(--k-pad) 0;
  gap: var(--k-gap);
  overflow: hidden;
}

/* Build / Integrate. Hidden below the narrow breakpoint rather than squeezed:
   a 348px panel and a usable system cannot both fit on a small screen. */
.tg-panel {
  flex: 0 0 var(--k-panel);
  width: var(--k-panel);
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

@media (max-width: 1180px) {
  .tg-panel { display: none; }
}

@media (max-width: 780px) {
  .tg-chat { display: none; }
  .tg-side { display: none; }
}

.tg-chat {
  flex: 0 0 var(--k-chat);
  width: var(--k-chat);
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/* ── surfaces ─────────────────────────────────────────────────────────── */

.tg-card {
  background: var(--k-surface, #FFFFFF);
  border-radius: var(--k-radius);
  box-shadow: var(--k-card, 0 4px 18px rgba(23, 49, 99, 0.07));
  backdrop-filter: var(--k-blur, none);
  -webkit-backdrop-filter: var(--k-blur, none);
  min-height: 0;
}

/* ── the customer's system: LIGHT inside our chrome ───────────────────── */

.tg-system {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  border-radius: var(--k-radius);
  /* --k-sys* deliberately, never the shell palette. This frame belongs to
     the customer's system and is tinted by the template it came from. */
  background: var(--k-sysSurface, #FFFFFF);
  box-shadow: inset 0 0 0 1px var(--k-sysLine, rgba(59, 107, 232, 0.13));
  color: #16224A;
}

.tg-system::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--k-sysAmbient, none);
  pointer-events: none;
}

.tg-system > * { position: relative; }

/* SANDBOX is a state the customer must never have to guess at — it is the
   difference between editing a copy and editing the live business. */
.tg-badge-sandbox {
  display: inline-block;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--k-warmText3, #B24E14);
  background: var(--k-warmSoft, #FFF1E7);
}

.tg-badge-live {
  display: inline-block;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  color: var(--k-greenText, #16A46B);
  background: var(--k-greenSoft, #E8F8F0);
}

/* Health, straight from /v1/health and _app_probe. */
.tg-health--healthy  { color: var(--k-greenText, #16A46B); }
.tg-health--degraded { color: var(--k-amberText, #A96412); }
.tg-health--stopped  { color: var(--k-muted, #6C7C9C); }

.tg-btn-primary {
  border: 0;
  border-radius: 12px;
  padding: 9px 16px;
  font-weight: 700;
  cursor: pointer;
  color: #FFFFFF;
  background: var(--k-accent, #F26A1B);
}

.tg-btn-primary:hover { background: var(--k-accentDeep, #CB5916); }

/* Respect the viewer's motion preference — the ambient wash and the orb both
   animate, and neither is worth a headache. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}
