/* ===========================================================================
   The customer account area.
   ===========================================================================

   # Whose colour this is

   The house palette, not the product's. Lime belongs to Multistage Sidechain —
   site.config.js says so explicitly: "no debe aparecer en el header, el footer,
   la home ni /studio/" — and an account will hold more than one product. Painting
   the whole shell in one product's accent would brand somebody's library with
   whichever plugin happened to be first.

   So the shell is the cold Hakuna palette, exactly as the panel is, and a
   product's own accent appears only inside that product's card, from
   `--product-accent` set per card. A second product with a different colour then
   needs no new stylesheet.

   # No build

   Same reason as the panel: four files served as static. A framework here would
   add a node_modules and a build step to five screens.
   =========================================================================== */

@font-face {
  font-family: 'Noto Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/noto-sans-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Noto Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/noto-sans-latin-600-normal.woff2') format('woff2');
}

:root {
  --void: #050607;
  --bg: #080a0c;
  --surface: #0d1013;
  --raised: #11151a;
  --titanium: #171b20;

  /* White at low opacity, never opaque grey. An opaque border weighs the same on
     black as on graphite, so it either looks crude on one or vanishes on the
     other. This leans on whatever is underneath it. */
  --line: rgb(255 255 255 / 0.09);
  --line-soft: rgb(255 255 255 / 0.05);
  --line-bright: rgb(255 255 255 / 0.16);

  --ink: #f3f4f4;
  --muted: #a7adb3;
  --dim: #848b93;
  --faint: #7d848c;

  /* The house's cold reflection. Focus and selection, nothing else — the moment
     it fills something it stops reading as light. */
  --ice: #a9c2d6;

  --ok: #6ea86e;
  --warn: #e8b923;
  --error: #d0554a;

  --radius-sm: 4px;
  --radius-md: 7px;
  --radius-lg: 10px;

  --shadow-panel: 0 3px 14px rgb(0 0 0 / 0.46);
  --shadow-lift: 0 18px 50px rgb(0 0 0 / 0.55);

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --dur: 180ms;

  --mono: ui-monospace, 'Cascadia Mono', Consolas, monospace;

  /* Overridden per product card. Falls back to the house cold, so a product with
     no accent recorded looks deliberate rather than broken. */
  --product-accent: var(--ice);
}

* {
  box-sizing: border-box;
}

/* El atributo `hidden` sólo esconde algo mientras nadie le fije un `display`.
   La regla que lo oculta —`[hidden] { display: none }`— vive en la hoja del
   navegador, y CUALQUIER regla de autor la gana: `.btn` pone `inline-flex` y
   `.gate` pone `grid`, así que ambos seguían viéndose marcados como ocultos.

   Se vio en producción y de la peor manera: el botón de Google aparecía sin
   haber cliente OAuth configurado, y al pulsarlo devolvía un JSON de error en
   crudo. La lógica era correcta —`hidden` estaba puesto— y lo que fallaba era
   que el navegador tenía instrucciones de dibujarlo igualmente.

   El panel ya llevaba esta regla desde el principio; al traer sus tokens no me
   traje ésta. `!important` porque tiene que ganarle a cualquier `display` que
   venga después, que es justo lo que no hizo la del navegador. */
[hidden] {
  display: none !important;
}

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

body {
  background: var(--bg);
  color: var(--ink);
  font-family: 'Noto Sans', ui-sans-serif, system-ui, sans-serif;
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3 {
  margin: 0;
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* Focus is visible everywhere and never removed. Offset, because most of these
   controls are filled and a ring drawn inside one disappears into it. */
:focus-visible {
  outline: 2px solid var(--ice);
  outline-offset: 2px;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 0.6rem 1rem;
  background: var(--raised);
  color: var(--ink);
  border-radius: var(--radius-md);
}
.skip:focus {
  left: 0.75rem;
  top: 0.75rem;
}

/* --- buttons -------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  /* Never below this: a control smaller than a fingertip is a control that gets
     missed on the device most of these people are holding. */
  min-height: 2.75rem;
  padding: 0 1rem;
  border: 1px solid var(--line-bright);
  border-radius: var(--radius-md);
  background: var(--raised);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
  transition:
    border-color var(--dur) var(--ease-out),
    background-color var(--dur) var(--ease-out);
}
.btn:hover:not(:disabled) {
  border-color: var(--ice);
}
.btn:disabled {
  opacity: 0.55;
  cursor: default;
}

.btn-primary {
  width: 100%;
  background: var(--ink);
  color: var(--void);
  border-color: var(--ink);
  font-weight: 600;
}
.btn-primary:hover:not(:disabled) {
  background: #fff;
  border-color: #fff;
}

.btn-google {
  width: 100%;
}

.btn-quiet {
  min-height: 2.25rem;
  background: transparent;
  color: var(--muted);
  border-color: var(--line);
}

/* Destructive actions look like what they are and never sit beside Download.
   Outlined rather than filled: a solid red button is an invitation. */
.btn-danger {
  border-color: color-mix(in srgb, var(--error) 55%, transparent);
  color: var(--error);
  background: transparent;
}
.btn-danger:hover:not(:disabled) {
  border-color: var(--error);
  background: color-mix(in srgb, var(--error) 12%, transparent);
}

.btn-sm {
  min-height: 2.25rem;
  padding: 0 0.7rem;
  font-size: 0.8125rem;
}

.linkish {
  border: 0;
  background: none;
  padding: 0.35rem 0;
  color: var(--muted);
  font: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.linkish:hover {
  color: var(--ink);
}

/* --- the door ------------------------------------------------------------- */

.gate {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 1.25rem;
}

.gate-card {
  width: 100%;
  max-width: 25rem;
  padding: 2rem 1.75rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lift);
  text-align: center;
}

.gate-mark {
  width: 40px;
  height: auto;
  margin-bottom: 1rem;
}

.gate-sub {
  margin: 0.15rem 0 1.5rem;
  color: var(--faint);
  font-size: 0.8125rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.gate-links {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  margin-top: 1.1rem;
}

.or {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 1rem 0;
  color: var(--faint);
  font-size: 0.8125rem;
}
.or::before,
.or::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--line);
}

.field {
  margin-bottom: 0.9rem;
  text-align: left;
}
.field label {
  display: block;
  margin-bottom: 0.3rem;
  color: var(--muted);
  font-size: 0.8125rem;
}
.field input {
  width: 100%;
  min-height: 2.75rem;
  padding: 0 0.75rem;
  background: var(--void);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  color: var(--ink);
  font: inherit;
}
.field input:focus {
  border-color: var(--ice);
}

.hint {
  margin: 0.35rem 0 0;
  color: var(--faint);
  font-size: 0.75rem;
}

.notice {
  margin-bottom: 1rem;
  padding: 0.7rem 0.85rem;
  border-radius: var(--radius-md);
  font-size: 0.875rem;
  text-align: left;
  border: 1px solid var(--line);
  background: var(--raised);
}
.notice-error {
  border-color: color-mix(in srgb, var(--error) 45%, transparent);
  color: #f0b3ac;
}
.notice-ok {
  border-color: color-mix(in srgb, var(--ok) 45%, transparent);
  color: #b9dcb9;
}

/* --- shell ---------------------------------------------------------------- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  height: 3.5rem;
  padding: 0 1rem;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line-soft);
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  color: var(--ink);
  text-decoration: none;
  font-weight: 600;
}
.brand img {
  width: 22px;
  height: auto;
}

.topbar-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.whoami {
  color: var(--faint);
  font-size: 0.8125rem;
  max-width: 14rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.iconbtn {
  display: none;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: transparent;
  cursor: pointer;
}
.burger,
.burger::before,
.burger::after {
  display: block;
  width: 16px;
  height: 1.5px;
  background: var(--ink);
  content: '';
}
.burger::before {
  transform: translateY(-5px);
}
.burger::after {
  transform: translateY(3.5px);
}

.nav {
  display: flex;
  gap: 0.25rem;
  padding: 0.5rem 1rem;
  border-bottom: 1px solid var(--line-soft);
  overflow-x: auto;
}
.nav a {
  padding: 0.5rem 0.85rem;
  border-radius: var(--radius-md);
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
}
.nav a:hover {
  color: var(--ink);
  background: var(--raised);
}
/* Selected is not colour alone: the weight and the surface change with it, so it
   survives being printed in grey or read by somebody who cannot separate the
   two tones. */
.nav a[aria-current='page'] {
  color: var(--ink);
  background: var(--titanium);
  font-weight: 600;
}

.main {
  /* Not edge to edge. A dashboard stretched across an ultrawide monitor is a
     dashboard nobody can read a row of. */
  max-width: 60rem;
  margin: 0 auto;
  padding: 1.5rem 1rem 4rem;
}
.main:focus {
  outline: none;
}

/* --- sections and cards --------------------------------------------------- */

.page-title {
  margin-bottom: 0.35rem;
  font-size: 1.5rem;
}
.page-sub {
  margin: 0 0 1.75rem;
  color: var(--faint);
}

.section {
  margin-bottom: 2.25rem;
}
.section-title {
  margin-bottom: 0.85rem;
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--faint);
}

.card {
  padding: 1.15rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-panel);
}

.stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.75rem;
}
.stat {
  padding: 1rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
}
.stat-value {
  font-size: 1.75rem;
  font-weight: 600;
  line-height: 1.1;
}
.stat-label {
  margin-top: 0.2rem;
  color: var(--faint);
  font-size: 0.8125rem;
}

/* --- product ------------------------------------------------------------- */

.product {
  padding: 1.25rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-panel);
  margin-bottom: 1rem;
  /* The one place a product's own colour appears. */
  border-left: 3px solid var(--product-accent);
}
.product-head {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}
.product-name {
  font-size: 1.125rem;
}
.product-meta {
  margin-top: 0.15rem;
  color: var(--faint);
  font-size: 0.8125rem;
}

.rows {
  display: grid;
  gap: 0.85rem;
}
.row {
  display: grid;
  grid-template-columns: 9rem 1fr;
  gap: 0.75rem;
  align-items: start;
  padding-top: 0.85rem;
  border-top: 1px solid var(--line-soft);
}
.row-label {
  color: var(--faint);
  font-size: 0.8125rem;
}
.row-value {
  min-width: 0;
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* --- badges --------------------------------------------------------------- */

/* Never colour alone — every badge carries readable words as well as a tint. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.2rem 0.55rem;
  border: 1px solid var(--line-bright);
  border-radius: 999px;
  font-size: 0.75rem;
  color: var(--muted);
  white-space: nowrap;
}
.badge-ok {
  border-color: color-mix(in srgb, var(--ok) 50%, transparent);
  color: #b9dcb9;
}
.badge-warn {
  border-color: color-mix(in srgb, var(--warn) 50%, transparent);
  color: #e8cf8a;
}
.badge-error {
  border-color: color-mix(in srgb, var(--error) 50%, transparent);
  color: #f0b3ac;
}

/* --- licence key ---------------------------------------------------------- */

.keyline {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.keyval {
  padding: 0.4rem 0.6rem;
  background: var(--void);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-family: var(--mono);
  font-size: 0.875rem;
  letter-spacing: 0.04em;
  word-break: break-all;
}

/* --- machines ------------------------------------------------------------- */

.machine {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  padding: 0.6rem 0;
  border-top: 1px solid var(--line-soft);
  font-size: 0.875rem;
}
.machine:first-child {
  border-top: 0;
}
.machine-when {
  color: var(--faint);
  font-size: 0.8125rem;
}
.machine .btn {
  margin-left: auto;
}

/* --- attention ------------------------------------------------------------ */

.attn {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 0.9rem 1rem;
  margin-bottom: 0.6rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--warn);
  border-radius: var(--radius-md);
}
.attn p {
  margin: 0;
}
.attn .btn {
  margin-left: auto;
}

/* --- empty and error ------------------------------------------------------ */

.empty {
  padding: 2.5rem 1.25rem;
  text-align: center;
  background: var(--surface);
  border: 1px dashed var(--line-bright);
  border-radius: var(--radius-lg);
}
.empty h3 {
  margin-bottom: 0.4rem;
}
.empty p {
  margin: 0 0 1.1rem;
  color: var(--faint);
}

/* --- loading -------------------------------------------------------------- */

/* Shapes the size of what is coming, so the page does not jump when it lands.
   Deliberately not fake numbers: a skeleton says "loading", a placeholder value
   says something untrue. */
.skeleton {
  background: linear-gradient(90deg, var(--surface), var(--raised), var(--surface));
  background-size: 200% 100%;
  border-radius: var(--radius-md);
  animation: shimmer 1.4s linear infinite;
}
.skeleton-line {
  height: 0.85rem;
  margin-bottom: 0.6rem;
}
.skeleton-card {
  height: 8.5rem;
  margin-bottom: 1rem;
}
@keyframes shimmer {
  to {
    background-position: -200% 0;
  }
}

/* --- toast ---------------------------------------------------------------- */

.toast {
  position: fixed;
  left: 50%;
  bottom: 1.25rem;
  transform: translate(-50%, 1rem);
  padding: 0.65rem 1rem;
  background: var(--titanium);
  border: 1px solid var(--line-bright);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lift);
  font-size: 0.875rem;
  opacity: 0;
  pointer-events: none;
  transition:
    opacity var(--dur) var(--ease-out),
    transform var(--dur) var(--ease-out);
}
.toast.is-on {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* --- settings ------------------------------------------------------------- */

.setting {
  padding: 1.15rem 0;
  border-top: 1px solid var(--line-soft);
}
.setting:first-child {
  border-top: 0;
  padding-top: 0;
}
.setting h3 {
  font-size: 0.9375rem;
  margin-bottom: 0.25rem;
}
.setting p {
  margin: 0 0 0.85rem;
  color: var(--faint);
  font-size: 0.875rem;
}
.setting form {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  align-items: flex-end;
}
.setting .field {
  flex: 1 1 14rem;
  margin-bottom: 0;
}

.emails {
  display: grid;
  gap: 0.5rem;
  margin-bottom: 0.85rem;
}
.email-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  padding: 0.6rem 0.75rem;
  background: var(--void);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-md);
  font-size: 0.875rem;
}
.email-row .btn {
  margin-left: auto;
}

/* ===========================================================================
   Narrow screens

   Not a shrunk desktop. The two things that actually break are the navigation
   and any row that assumes horizontal room — so the nav becomes a drawer and
   every label/value pair stacks. There is no table anywhere in this app for
   exactly this reason: a licence table on a phone is a horizontal scroll, and a
   horizontal scroll is a feature nobody finds.
   =========================================================================== */

@media (width < 46rem) {
  .iconbtn {
    display: inline-flex;
  }

  .nav {
    display: none;
    flex-direction: column;
    gap: 0.15rem;
    padding: 0.75rem 1rem 1rem;
  }
  .nav.is-open {
    display: flex;
  }
  .nav a {
    padding: 0.75rem 0.85rem;
  }

  .whoami {
    display: none;
  }

  .stats {
    grid-template-columns: 1fr;
  }

  /* The stacking that matters. Every row becomes label above value, so nothing
     needs width it does not have. */
  .row {
    grid-template-columns: 1fr;
    gap: 0.3rem;
  }

  .machine .btn,
  .attn .btn,
  .email-row .btn {
    margin-left: 0;
    width: 100%;
  }

  .setting form {
    flex-direction: column;
    align-items: stretch;
  }
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---------------------------------------------------------------------------
   Utility classes that exist because the production CSP forbids inline styles.

   `style-src 'self'` with no 'unsafe-inline' — the same line the panel carries —
   blocks a `style=` attribute outright. It is what turns an injected script from
   "steals a session" into "does not run", and it is worth more than the
   convenience of a one-off style. These four are what the generated markup
   needed, and they were found by the CSP rejecting them rather than by review.
   --------------------------------------------------------------------------- */

.btn-narrow {
  max-width: 16rem;
  margin-inline: auto;
}

.muted-note {
  color: var(--faint);
}

.flush {
  margin: 0;
}

.seatline {
  margin: 0 0 0.5rem;
}

.badge-inline {
  margin-left: 0.4rem;
}

.skeleton-short {
  width: 40%;
}
