/* ============================================================================
   refine.css · polish + visual-refresh layer for the ServiceLog design system
   ----------------------------------------------------------------------------
   Loaded AFTER style.css so these tokens and rules win without editing the
   3,300-line base.  Goal: keep the terminal/dark aesthetic exactly as-is, but
   sharpen the invisible details that make an interface feel intentional —
   custom easing, tactile press feedback, keyboard focus rings, a real
   elevation scale, dark-aware native controls, and a tasteful entrance.
   Everything here degrades gracefully and respects prefers-reduced-motion.
   ========================================================================== */

:root {
  /* ── Motion · strong custom curves (the built-in CSS easings are too weak) ── */
  --ease-out:    cubic-bezier(0.22, 1, 0.36, 1);     /* entrances · snappy, settles soft */
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);     /* on-screen movement */
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);  /* playful overshoot · sparingly */
  --dur-fast:    120ms;   /* button press / hover */
  --dur:         180ms;   /* tiles, cards, popovers */
  --dur-slow:    260ms;   /* larger surfaces */

  /* ── Elevation · dark-room shadows (low alpha, generous spread) ──────────── */
  --shadow-1: 0 1px 2px rgba(0,0,0,.30);
  --shadow-2: 0 4px 14px rgba(0,0,0,.40);
  --shadow-3: 0 12px 32px rgba(0,0,0,.55);

  /* ── Spacing rhythm · 4/8 base, documented for consistent future use ─────── */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px;  --sp-4: 16px;  --sp-5: 24px;  --sp-6: 32px;

  /* Native controls (checkbox, radio, range, progress) inherit the brand ↓ */
  color-scheme: dark;
  accent-color: var(--amber);
}

html[data-theme="light"] {
  color-scheme: light;
  --shadow-1: 0 1px 2px rgba(43,59,72,.10);
  --shadow-2: 0 4px 14px rgba(43,59,72,.12);
  --shadow-3: 0 12px 32px rgba(43,59,72,.16);
}

/* Text selection · amber wash keeps the brand present even when highlighting. */
::selection      { background: rgba(245,166,35,.28); color: #fff; }
::-moz-selection { background: rgba(245,166,35,.28); color: #fff; }

/* ── Themed scrollbar · thin + dark so it stops looking like a default OS bar.
   (Lists that intentionally hide their bar already set scrollbar-width:none and
   are unaffected — this targets the document/long surfaces only.) ─────────── */
html { scrollbar-width: thin; scrollbar-color: var(--border-2) transparent; }
body::-webkit-scrollbar              { width: 11px; height: 11px; }
body::-webkit-scrollbar-thumb        { background: var(--border-2); border-radius: 6px;
                                       border: 3px solid var(--bg); }
body::-webkit-scrollbar-thumb:hover  { background: #3c4566; }
body::-webkit-scrollbar-track        { background: transparent; }

/* ============================================================================
   Keyboard focus · one visible, on-brand ring for everyone tabbing through.
   Mouse users never see it (:focus-visible), so it adds zero visual noise.
   ========================================================================== */
a:focus-visible,
button:focus-visible,
[role="button"]:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
.btn:focus-visible,
.tab:focus-visible,
.app-tile:focus-visible,
.apps-popover-tile:focus-visible {
  outline: 2px solid var(--amber);
  outline-offset: 2px;
  border-radius: var(--radius);
}

/* ============================================================================
   Tactile press feedback · nothing in the real world responds without moving.
   A subtle scale on :active confirms the UI heard the tap.  Large surfaces
   scale less than small ones so the motion reads as "press", not "shrink".
   ========================================================================== */
.btn, .btn-cmd, .apps-btn, .brand-link, .brand-logout,
.tab, .pill, .dash-pill {
  transition: background var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}
.btn:active           { transform: scale(.975); }
.btn-cmd:active       { transform: scale(.99); }
.apps-btn:active,
.brand-link:active,
.brand-logout:active  { transform: scale(.96); }

/* Primary action earns a faint glow so the one CTA per screen stands out. */
.btn-primary {
  box-shadow: 0 1px 0 rgba(255,255,255,.08) inset, var(--shadow-1);
}
.btn-primary:hover {
  box-shadow: 0 0 0 1px rgba(245,166,35,.35), 0 4px 14px rgba(245,166,35,.18);
}

/* ============================================================================
   Cards & app tiles · gentle hover lift + real elevation.  Interruptible CSS
   transitions (not keyframes) so rapid hover in/out stays smooth.
   ========================================================================== */
.app-tile {
  transition: border-color var(--dur) var(--ease-out),
              transform var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease-out),
              background var(--dur) var(--ease-out);
  will-change: transform;
}
.app-tile:hover  { transform: translateY(-2px); box-shadow: var(--shadow-2); }
.app-tile:active { transform: translateY(0) scale(.995); box-shadow: var(--shadow-1); }
.app-tile.disabled:hover { transform: none; box-shadow: none; }

.card {
  transition: border-color var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease-out);
}

/* Popover tiles · scale-from-origin already handled by base; add easing + press. */
.apps-popover-tile {
  transition: background var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.apps-popover-tile:active { transform: scale(.985); }

/* ============================================================================
   Form fields · clearer focus affordance (amber border + soft ring) so the
   active input is obvious without shouting.
   ========================================================================== */
.field:focus,
input[type="text"]:focus, input[type="email"]:focus,
input[type="password"]:focus, input[type="number"]:focus,
input[type="search"]:focus, input[type="date"]:focus,
select:focus, textarea:focus {
  border-color: var(--amber-dim);
  box-shadow: 0 0 0 3px rgba(245,166,35,.12);
  outline: none;
}

/* ============================================================================
   Toasts · enter from below with a strong ease-out so they feel responsive,
   and stack with a little breathing room.  (Dismiss timing stays in app.js.)
   ========================================================================== */
.toasts { display: flex; flex-direction: column; gap: 8px; }
.toast {
  animation: toast-in var(--dur-slow) var(--ease-out) both;
  box-shadow: var(--shadow-2);
}
@keyframes toast-in {
  from { opacity: 0; transform: translateY(12px) scale(.98); }
  to   { opacity: 1; transform: translateY(0)    scale(1);   }
}

/* ============================================================================
   Entrance · launcher/app tiles fade up in a quick stagger on first paint.
   Decorative only — never blocks interaction, and fully removed under
   reduced-motion below.  Cap the stagger early so long grids don't feel slow.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  .app-tile {
    animation: tile-rise var(--dur-slow) var(--ease-out) both;
  }
  .app-tile:nth-child(1) { animation-delay: 0ms;   }
  .app-tile:nth-child(2) { animation-delay: 45ms;  }
  .app-tile:nth-child(3) { animation-delay: 90ms;  }
  .app-tile:nth-child(4) { animation-delay: 135ms; }
  .app-tile:nth-child(5) { animation-delay: 180ms; }
  .app-tile:nth-child(6) { animation-delay: 210ms; }
  .app-tile:nth-child(n+7) { animation-delay: 240ms; }  /* cap · no slow tail */
}
@keyframes tile-rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0);    }
}

/* ============================================================================
   Accessibility capstone · honor prefers-reduced-motion globally.
   Reduced motion means *gentler*, not broken: we strip movement and transforms
   but keep instant state changes legible.  This also overrides base pulses.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .app-tile:hover  { transform: none; }
  .btn:active, .app-tile:active, .apps-btn:active,
  .brand-link:active, .apps-popover-tile:active { transform: none; }
  /* Keep the busy spinner from animating; the "Working…" label still reads. */
  .btn.is-busy::before { animation: none !important; }
}

/* ============================================================================
   Busy state · a submit button locks into "Working…" with an inline spinner
   after the form is sent (wired in app.js). Gives a long save/upload feedback
   and prevents a double-submit.  Sits on .btn so it inherits brand sizing.
   ========================================================================== */
.btn.is-busy {
  position: relative;
  cursor: progress;
  opacity: .9;
  /* keep the disabled look from washing the label out completely */
  color: var(--text);
}
.btn.is-busy::before {
  content: "";
  display: inline-block;
  width: .85em; height: .85em;
  margin-right: .5em;
  vertical-align: -.1em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: btn-spin .6s linear infinite;
}
.btn-primary.is-busy::before { border-color: #000; border-right-color: transparent; }
@keyframes btn-spin { to { transform: rotate(360deg); } }

/* ============================================================================
   Toasts · room for a manual close button (injected in app.js) and a clearer
   pointer affordance.  The × is muted until hovered so it never competes with
   the message text.
   ========================================================================== */
.toast { position: relative; padding-right: 2rem; }
.toast-close {
  position: absolute;
  top: 4px; right: 6px;
  width: 1.4rem; height: 1.4rem;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent;
  border: 0;
  border-radius: var(--radius);
  color: var(--muted);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.toast-close:hover { color: var(--text); background: rgba(255,255,255,.06); }

/* ============================================================================
   Contrast · the base placeholder (#4a5068 on the dark field) lands near
   2.5:1 — below WCAG.  Nudge placeholders and the dimmest helper text up to a
   legible value without changing the palette's character.
   ========================================================================== */
::placeholder { color: #6b7390; opacity: 1; }
input::placeholder, textarea::placeholder { color: #6b7390; }
