/* --------------------------------------------------------------------------
   Reset, primitives and shared components (buttons, fields, cards, toasts).
   Theme-neutral: the light app skin is app.css, the dark entry page is
   auth.css. Anything used by both lives here.

   Copied verbatim from tarang_website's own base.css -- nothing in this
   file names a product, so there is nothing here to structurally port.
   -------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: var(--t-md);
  line-height: 1.55;
  color: var(--ink);
  background: var(--page);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, p, figure { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
img, svg, canvas { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }
a { color: var(--primary); text-decoration: none; }
a:hover { text-decoration: underline; }

:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--primary) 55%, transparent);
  outline-offset: 2px;
  border-radius: 4px;
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Skip-link, so the dashboard's nav is not a keyboard trap. */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--primary); color: #fff; padding: 10px 16px;
  border-radius: 0 0 var(--r-sm) 0;
}
.skip:focus { left: 0; }

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
  --btn-bg: var(--primary);
  --btn-bg-hover: var(--primary-dk);
  --btn-fg: #fff;
  --btn-border: transparent;
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 38px;                       /* the launcher's CTRL_H */
  padding: 0 18px;
  border: 1px solid var(--btn-border);
  border-radius: var(--r-sm);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--font-mono);   /* DESIGN.md: mono carries buttons and nav too */
  font-size: var(--t-sm);
  font-weight: 600;
  letter-spacing: .01em;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  transition: background var(--dur-1) ease,
              transform var(--dur-2) var(--e-spring),
              box-shadow var(--dur-2) var(--e-out),
              opacity var(--dur-1) ease;
}
.btn:hover:not(:disabled) { background: var(--btn-bg-hover); text-decoration: none; }
.btn:active:not(:disabled) { transform: scale(.975); }
.btn:disabled { opacity: .55; cursor: not-allowed; }

/* Sheen that sweeps once on hover. Pure decoration; pointer-events off so it
   never eats the click. */
.btn::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(105deg, transparent 35%,
              rgba(255, 255, 255, .35) 50%, transparent 65%);
  transform: translateX(-120%);
  pointer-events: none;
}
.btn:hover:not(:disabled)::after { animation: sheen var(--dur-4) var(--e-out); }
@keyframes sheen { to { transform: translateX(120%); } }

.btn-lg  { min-height: 46px; padding: 0 26px; font-size: var(--t-lg); }
.btn-sm  { min-height: 30px; padding: 0 12px; font-size: var(--t-sm); }
.btn-block { width: 100%; }

.btn-success { --btn-bg: var(--success); --btn-bg-hover: #37D89E; }
.btn-danger  { --btn-bg: var(--danger);  --btn-bg-hover: #F76A7B; }

/* Product-identity buttons -- DESIGN.md: "amber and astro are product
   identity colours ... never as general UI accents", so these three exist
   for the one legitimate use (a product's own CTA on its own page), not
   for generic emphasis. .btn-accent reads whichever --accent the page has
   set (dhara/dashboard.html, tarang/dashboard.html, a home.html section) --
   prefer it over naming a colour directly, so a card never goes stale if
   its product's accent is ever revisited. */
.btn-accent { --btn-bg: var(--accent, var(--primary)); --btn-bg-hover: var(--accent-bright, var(--primary-dk)); }
.btn-teal   { --btn-bg: var(--teal);   --btn-bg-hover: var(--teal-bright); }
.btn-amber  { --btn-bg: var(--amber);  --btn-bg-hover: var(--amber-bright); }
.btn-astro  { --btn-bg: var(--astro);  --btn-bg-hover: var(--astro-bright); }
.btn-violet { --btn-bg: var(--violet); --btn-bg-hover: var(--violet-bright); }

.btn-light {
  --btn-bg: var(--raised); --btn-bg-hover: var(--line-bright);
  --btn-fg: var(--fog-100); --btn-border: var(--line);
}
.btn-outline {
  --btn-bg: transparent; --btn-bg-hover: var(--primary-100);
  --btn-fg: var(--primary); --btn-border: var(--primary);
}
.btn-ghost {
  --btn-bg: transparent; --btn-bg-hover: color-mix(in srgb, var(--primary) 12%, transparent);
  --btn-fg: var(--label); --btn-border: transparent;
}

/* ---- theme switch (sliding, click to flip) --------------------------------
   Lives in base.css, not app.css: theme.js's themeToggleButton() is used
   by both the shell (app.css pages) and index.html (auth.css only, no
   app.css) -- base.css is the one stylesheet every page actually loads. */
.theme-switch {
  border: 0; background: none; padding: 0; margin-left: var(--sp-2);
  cursor: pointer; border-radius: var(--r-pill); flex: none;
}
.theme-switch-track {
  position: relative; display: flex; align-items: center; justify-content: space-between;
  width: 50px; height: 27px; padding: 0 6px; box-sizing: border-box;
  border-radius: var(--r-pill);
  background: var(--raised); border: 1px solid var(--border);
  transition: background var(--dur-2) ease-out, border-color var(--dur-2) ease-out;
}
.theme-switch-ico {
  display: grid; place-items: center; width: 14px; height: 14px;
  position: relative; z-index: 1; color: var(--fog-600);
  transition: color var(--dur-2) ease-out;
}
.theme-switch-thumb {
  position: absolute; top: 2.5px; left: 2.5px;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--card); box-shadow: var(--shadow-2);
  transition: transform var(--dur-3) var(--e-spring);
}
.theme-switch.is-dark .theme-switch-thumb { transform: translateX(23px); }
.theme-switch.is-dark .theme-switch-track { background: var(--fog-100); border-color: var(--line-bright); }
.theme-switch:not(.is-dark) .theme-switch-ico.sun { color: var(--warn); }
.theme-switch.is-dark .theme-switch-ico.moon { color: var(--warn-text); }
.theme-switch:active .theme-switch-track { filter: brightness(.96); }
.theme-switch:focus-visible { outline: 3px solid color-mix(in srgb, var(--primary) 55%, transparent); outline-offset: 2px; }

/* Loading state: label slides out, spinner takes the middle. Width is held by
   the label still occupying the box, so the button does not jump. */
.btn.is-busy { pointer-events: none; }
.btn.is-busy .btn-label { opacity: 0; transform: translateY(6px); }
.btn .btn-label {
  display: inline-flex; align-items: center; gap: 8px;
  transition: opacity var(--dur-1) ease, transform var(--dur-2) var(--e-out);
}
.btn .spinner { position: absolute; opacity: 0; }
.btn.is-busy .spinner { opacity: 1; }

.spinner {
  width: 17px; height: 17px; border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, .32);
  border-top-color: currentColor;
  animation: spin .7s linear infinite;
}
.spinner-dark { border-color: rgba(0, 0, 0, .15); border-top-color: var(--primary); }
@keyframes spin { to { transform: rotate(360deg); } }

/* ==========================================================================
   Fields
   ========================================================================== */

.field { position: relative; margin-bottom: var(--sp-4); }

.field input,
.field select,
.field textarea {
  width: 100%;
  min-height: 46px;
  padding: 20px 14px 6px;               /* room for the floating label */
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--card);
  transition: border-color var(--dur-1) ease, box-shadow var(--dur-2) var(--e-out),
              background var(--dur-1) ease;
}
.field textarea { min-height: 104px; padding-top: 24px; resize: vertical; }

.field label {
  position: absolute; left: 15px; top: 13px;
  font-size: var(--t-md); color: var(--muted);
  pointer-events: none;
  transform-origin: 0 0;
  transition: transform var(--dur-2) var(--e-out), color var(--dur-2) ease;
}
.field input:focus + label,
.field input:not(:placeholder-shown) + label,
.field textarea:focus + label,
.field textarea:not(:placeholder-shown) + label,
.field select + label {
  transform: translateY(-9px) scale(.78);
  color: var(--primary);
}
.field input:not(:focus):not(:placeholder-shown) + label,
.field textarea:not(:focus):not(:placeholder-shown) + label { color: var(--muted); }

.field input:focus, .field textarea:focus, .field select:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--primary) 16%, transparent);
}
.field input:disabled, .field.is-locked input {
  background: var(--border-soft); color: var(--muted); cursor: not-allowed;
}

.field.is-bad input, .field.is-bad textarea { border-color: var(--danger); }
.field.is-bad input:focus, .field.is-bad textarea:focus {
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--danger) 16%, transparent);
}
.field-msg {
  display: block; min-height: 17px; margin-top: 5px; padding-left: 3px;
  font-size: var(--t-xs); color: var(--danger);
  opacity: 0; transform: translateY(-4px);
  transition: opacity var(--dur-2) ease, transform var(--dur-2) var(--e-out);
}
.field.is-bad .field-msg { opacity: 1; transform: none; }

.field-hint { margin-top: 5px; padding-left: 3px; font-size: var(--t-xs); color: var(--muted); }

/* Reveal / hide password */
.field .peek {
  position: absolute; right: 6px; top: 5px;
  width: 36px; height: 36px; display: grid; place-items: center;
  border: 0; background: none; color: var(--muted); cursor: pointer;
  border-radius: var(--r-sm);
}
.field .peek:hover { color: var(--ink); background: var(--border-soft); }

/* ==========================================================================
   Badges, pills, cards
   ========================================================================== */

.pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px; border-radius: var(--r-pill);
  font-size: var(--t-xs); font-weight: 600; letter-spacing: .02em;
  white-space: nowrap;
}
.pill-ok    { background: var(--success-100); color: var(--success-text); }
.pill-off   { background: var(--border-soft); color: var(--muted); }
.pill-warn  { background: var(--amber-100);   color: var(--warn-text); }
.pill-bad   { background: var(--danger-100);  color: var(--danger-text); }
.pill-trial { background: color-mix(in srgb, var(--violet) 18%, var(--panel)); color: var(--violet-text); }

.dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }
.dot-live { position: relative; }
.dot-live::after {
  content: ""; position: absolute; inset: -3px; border-radius: 50%;
  border: 2px solid currentColor; opacity: .5;
  animation: ping 2s var(--e-out) infinite;
}
@keyframes ping {
  0%   { transform: scale(.7); opacity: .6; }
  70%  { transform: scale(1.9); opacity: 0; }
  100% { opacity: 0; }
}

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
}
.card-head {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--border-soft);
  background: var(--header);
  border-radius: var(--r-md) var(--r-md) 0 0;
}
.card-head h2 { font-size: var(--t-lg); font-weight: 700; letter-spacing: -.01em; }
.card-body { padding: var(--sp-5); }

/* ==========================================================================
   Entrance choreography
   ui.js adds .in to .rise elements in document order, staggering them so the
   page assembles rather than appearing all at once. Crucially, .rise on its
   own renders normally -- the animation is additive, never load-bearing.
   ========================================================================== */

/* The resting state is VISIBLE, and .in only replays an entrance animation.
 *
 * This used to be the other way round -- .rise was opacity:0 and only became
 * visible once JS added .in -- which meant any element whose reveal never ran
 * was invisible for ever. That is a terrible failure mode: it hid the very
 * error panel that explains why a page failed to load, so a broken dashboard
 * looked like an empty one.
 *
 * ui.js adds .in synchronously in the same task as insertion, so the
 * un-animated state is never painted and there is no flash. `both` fill makes
 * each element hold the invisible `from` state through its stagger delay. */
.rise.in { animation: rise-in var(--dur-3) var(--e-out) both; }

@keyframes rise-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes pop-in {
  from { opacity: 0; transform: translateY(10px) scale(.97); }
  to   { opacity: 1; transform: none; }
}

/* ==========================================================================
   Toasts
   ========================================================================== */

#toasts {
  position: fixed; right: 20px; bottom: 20px; z-index: 120;
  display: flex; flex-direction: column; gap: 10px; align-items: flex-end;
  pointer-events: none;
}
.toast {
  display: flex; align-items: center; gap: 10px;
  max-width: min(420px, calc(100vw - 40px));
  padding: 11px 16px;
  border-radius: var(--r-sm);
  background: #212b36;                    /* the launcher's terminal bg */
  color: #dee2e6;
  font-size: var(--t-sm);
  box-shadow: var(--shadow-3);
  pointer-events: auto;
  animation: toast-in var(--dur-3) var(--e-spring);
}
.toast.out { animation: toast-out var(--dur-2) var(--e-in-out) forwards; }
.toast .ico { flex: none; }
.toast-ok  .ico { color: #75b798; }
.toast-bad .ico { color: #ea868f; }
.toast-info .ico { color: #6ea8fe; }
@keyframes toast-in  { from { opacity: 0; transform: translateY(16px) scale(.96); } }
@keyframes toast-out { to   { opacity: 0; transform: translateY(8px) scale(.98); } }

/* ==========================================================================
   Modal
   ========================================================================== */

.modal-back {
  position: fixed; inset: 0; z-index: 130;
  display: grid; place-items: center;
  padding: var(--sp-4);
  background: rgba(10, 22, 30, .55);
  backdrop-filter: blur(4px);
  animation: fade-in var(--dur-2) ease;
}
.modal {
  width: min(560px, 100%);
  max-height: calc(100vh - 48px);
  overflow: auto;
  background: var(--card);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-4);
  animation: modal-in var(--dur-3) var(--e-spring);
}
@keyframes modal-in { from { opacity: 0; transform: translateY(24px) scale(.96); } }
.modal-head {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-5) var(--sp-5) var(--sp-3);
}
.modal-head h2 { font-size: var(--t-xl); font-weight: 700; letter-spacing: -.02em; }
.modal-head p { color: var(--muted); font-size: var(--t-sm); margin-top: 3px; }
.modal-body { padding: 0 var(--sp-5) var(--sp-3); }
.modal-foot {
  display: flex; justify-content: flex-end; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-top: 1px solid var(--border-soft);
  background: var(--header);
  border-radius: 0 0 var(--r-lg) var(--r-lg);
}
.x-btn {
  margin-left: auto; width: 34px; height: 34px; flex: none;
  display: grid; place-items: center;
  border: 0; border-radius: var(--r-sm); background: none;
  color: var(--muted); cursor: pointer;
  transition: background var(--dur-1) ease, color var(--dur-1) ease,
              transform var(--dur-2) var(--e-spring);
}
.x-btn:hover { background: var(--border-soft); color: var(--ink); transform: rotate(90deg); }

/* ==========================================================================
   Skeletons
   ========================================================================== */

.sk {
  border-radius: var(--r-sm);
  background: linear-gradient(100deg, var(--border-soft) 30%, var(--line-bright) 50%,
              var(--border-soft) 70%);
  background-size: 220% 100%;
  animation: sk 1.3s ease-in-out infinite;
}
@keyframes sk { to { background-position: -220% 0; } }

/* ==========================================================================
   Utilities
   ========================================================================== */

.row  { display: flex; align-items: center; gap: var(--sp-3); }
.between { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.wrap { flex-wrap: wrap; }
.grow { flex: 1 1 auto; min-width: 0; }
.stack > * + * { margin-top: var(--sp-3); }
.muted { color: var(--muted); }
.small { font-size: var(--t-sm); }
.xsmall { font-size: var(--t-xs); }
.mono { font-family: var(--mono); }
.nowrap { white-space: nowrap; }
.center { text-align: center; }
.hidden { display: none !important; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}
