/* shell_html - the analytics dashboard SHELL.
 *
 * Moved verbatim out of the form's template <style> block: the Anvil server
 * strips the text out of a <style> in a template, so the rules have to be a
 * head-linked asset instead. Every declaration, comment and @keyframes body
 * below is byte for byte what the template carried, and NOT ONE SELECTOR
 * PRELUDE CHANGED - which is the whole point of this file's shape.
 *
 * NOTHING HERE IS :where()-SCOPED, and that is forced rather than chosen.
 * The template's root is one wrapper div, .ap-shell-root, holding the two
 * boxes the screen is made of (.dashboard-container, and #ap-home-modal,
 * which pxShowOverlay portals out of the form while it is open). That wrapper
 * exists to be REACHED, not to scope on: it carries exactly one rule near the
 * foot of this file, supplying the height chain px-internal's content area
 * needs. Every other subject below is either
 * id-led (#dashboard-content, #ap-home-modal, #ap-page-loading,
 * #kiosk-controls) or a private class this form alone declares and renders
 * (.dashboard-container, .dashboard-header, .dashboard-btn, .btn-planner,
 * .btn-sla, .dashboard-view-slot, .dashboard-loading, .loading-pulse,
 * .loading-dots).
 * None of those names, .ap-shell-root included, is declared anywhere else in
 * the estate, so no rule here can reach another form's DOM and no
 * other sheet can tie with one of these.
 *
 * THE CSS-ORDER AUDIT. These rules are a head link, so they lose every
 * specificity TIE on document order.
 * Checked against px_theme/_px_theme_css.py, mar_editor/_pxmar_core_js.py
 * (PXM_SHARED_CSS) and the four host theme assets: not one of the subjects
 * above appears in any of them, so there is no tie to lose. The two toolkit
 * classes this sheet does reach, .px-modal and .px-modal-body, are reached
 * only through #ap-home-modal, which is (1,1,0) against the toolkit's (0,1,0)
 * - specificity, not order. The host's .px-kiosk-controls { display: flex }
 * (px-internal theme.css) loses to #kiosk-controls the same way.
 *
 * TWO KNOWN DEFECTS, LEFT AS THEY ARE because either fix would be a visible
 * change needing an owner ruling:
 *
 *  1. THE RESPONSIVE-HEADER @media BLOCK BELOW IS NEVER CLOSED. It opens
 *     @media (max-width: 600px) and no closing brace ever matches it - the
 *     file has exactly one more opening brace than closing ones (48 to 47 at
 *     the time of writing; the count moves with every rule added above the
 *     block, the imbalance does not). Every rule after it,
 *     INCLUDING the two #ap-home-modal sizing rules, is therefore inside that
 *     media query and applies only at 600px and under; the parser auto-closes
 *     the block at the end of the sheet.
 *     ANYTHING APPENDED TO THIS FILE LANDS INSIDE THAT MEDIA QUERY - add new
 *     rules ABOVE the block, never at the foot.
 *  2. .dashboard-loading, .loading-pulse and .loading-dots (and the dotPulse
 *     and loadingPulse keyframes they drive) are DEAD. No markup in this
 *     template, no string this form's Python builds and no host renders any of
 *     them (grepped every worktree). They move across as they are.
 *
 * The three @keyframes idents (dashboardReveal, loadingPulse, dotPulse) are
 * NOT per-screen prefixed, which the guide asks for because @keyframes is
 * global. Grepped: no other asset, template or host declares any of the three,
 * so they carry across unrenamed - renaming an ident means rewriting the
 * animation shorthand that references it, which is a change with no gain here.
 * Recorded so the next form added to this section checks the same names.
 *
 * No url(), no @font-face, no var() fallback and no classed <svg> anywhere in
 * the block.
 */

.dashboard-container {
  --ap-planner-accent: #2196F3;
  --ap-planner-accent-hover: #42a5f5;
  --ap-planner-dark: #1976D2;
  --ap-planner-dark-hover: #1e88e5;
  --ap-sla-accent: #FF9800;
  --ap-sla-accent-hover: #ffab40;
  --ap-sla-dark: #F57C00;
  --ap-sla-dark-hover: #ff9100;
  --ap-toggle-bg: #f1f5f9;
  --ap-toggle-border: #94a3b8;
  --ap-toggle-knob: #ffffff;
  --ap-toggle-active-border: #3b82f6;
  --accent: var(--ap-planner-accent);
  --accent-hover: var(--ap-planner-accent-hover);
  --accent-subtle: rgba(33, 150, 243, 0.12);
  isolation: isolate;
  position: relative;
  z-index: 0;
  background: var(--px-bg-deep);
  display: flex;
  flex-direction: column;
  min-height: 100%;
}

[data-theme="dark"] .dashboard-container {
  --ap-toggle-bg: #1e293b;
  --ap-toggle-border: #3b82f6;
  --ap-toggle-knob: #334155;
}

.dashboard-header {
  display: flex;
  justify-content: center;
  padding: 12px 20px;
  background: linear-gradient(180deg, var(--px-bg-card) 0%, var(--px-bg-elevated) 100%);
  border-bottom: 1px solid var(--px-border);
  position: relative;
  z-index: 10;
}

.dashboard-btn {
  padding: 12px 28px;
  margin: 0 8px;
  border: none;
  border-radius: 10px;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.3px;
  cursor: pointer;
  transition: opacity 0.25s cubic-bezier(0.4, 0, 0.2, 1), transform 0.25s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.25s cubic-bezier(0.4, 0, 0.2, 1), color 0.25s cubic-bezier(0.4, 0, 0.2, 1), border-color 0.25s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.25s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 0 2px 8px rgba(0,0,0,0.08), 0 1px 2px rgba(0,0,0,0.06);
  position: relative;
  overflow: hidden;
}

.dashboard-btn::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(255,255,255,0.15) 0%, transparent 50%);
  pointer-events: none;
}

.dashboard-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 20px rgba(0,0,0,0.12), 0 2px 6px rgba(0,0,0,0.08);
}

.dashboard-btn:active {
  transform: translateY(0);
  box-shadow: 0 2px 6px rgba(0,0,0,0.1);
}

.dashboard-btn.loading {
  pointer-events: none;
  opacity: 0.7;
}

.btn-planner {
  background: linear-gradient(135deg, var(--ap-planner-accent) 0%, var(--ap-planner-dark) 100%);
  color: white;
}

.btn-planner:hover {
  background: linear-gradient(135deg, var(--ap-planner-accent-hover) 0%, var(--ap-planner-dark-hover) 100%);
}

.btn-sla {
  background: linear-gradient(135deg, var(--ap-sla-accent) 0%, var(--ap-sla-dark) 100%);
  color: white;
}

.btn-sla:hover {
  background: linear-gradient(135deg, var(--ap-sla-accent-hover) 0%, var(--ap-sla-dark-hover) 100%);
}

/* Dashboard content container with transition support */
#dashboard-content {
  width: 100%;
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  transition: opacity 0.2s ease-out, transform 0.2s ease-out, filter 0.2s ease-out;
}

/* Hide dashboard-content when empty (for SLA Stats view) */
#dashboard-content:empty {
  display: none;
}

#dashboard-content.transitioning-out {
  opacity: 0;
  transform: scale(0.985);
  filter: blur(4px);
  pointer-events: none;
}

#dashboard-content.transitioning-in {
  opacity: 0;
  transform: translateY(12px);
}

#dashboard-content.reveal {
  animation: dashboardReveal 0.35s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

@keyframes dashboardReveal {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Subtle loading indicator */
.dashboard-loading {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.loading-pulse {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: linear-gradient(135deg, rgba(33, 150, 243, 0.15) 0%, rgba(255, 152, 0, 0.15) 100%);
  animation: loadingPulse 1.2s ease-in-out infinite;
}

.loading-dots {
  display: flex;
  gap: 6px;
}

.loading-dots span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--px-text-muted);
  animation: dotPulse 1s ease-in-out infinite;
}

.loading-dots span:nth-child(2) { animation-delay: 0.15s; }
.loading-dots span:nth-child(3) { animation-delay: 0.3s; }

@keyframes loadingPulse {
  0%, 100% { transform: scale(1); opacity: 0.6; }
  50% { transform: scale(1.15); opacity: 1; }
}

@keyframes dotPulse {
  0%, 100% { opacity: 0.3; transform: scale(0.8); }
  50% { opacity: 1; transform: scale(1); }
}

.dashboard-view-slot {
  width: 100%;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.dashboard-view-slot > * {
  flex: 1 1 auto;
  min-height: 0;
}

.dashboard-view-slot > * > * {
  flex: 1 1 auto;
  min-height: 0;
}

/* Dark mode button shadows */
[data-theme="dark"] .btn-planner {
  box-shadow: 0 2px 8px rgba(33, 150, 243, 0.3), 0 1px 2px rgba(0,0,0,0.2);
}

[data-theme="dark"] .btn-sla {
  box-shadow: 0 2px 8px rgba(255, 152, 0, 0.3), 0 1px 2px rgba(0,0,0,0.2);
}

/* Kiosk chrome: visual styles live in theme.css (.px-kiosk-*); only positioning here. */
#kiosk-controls {
  position: absolute;
  left: 16px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 10;
}

/* The element carried an inline display:none and a template may carry no
   inline style attribute, so the hidden state is a rule. It sits HERE, above
   the unterminated @media block described in the header, because a rule added
   at the foot of this file would apply only at 600px and under.
   pxKioskMountChrome sets the element's inline display to flex when a kiosk
   session mounts, and an inline declaration beats a head-linked rule, so the
   reveal is unchanged. */
#kiosk-controls {
  display: none;
}

/* The form root, and the ONE rule in this file that is neither id-led nor a
   private class of the markup below. An HTML form's root carries none of
   Anvil's own container classes, so px-internal's theme.css
   `.anvil-m3-content > .anvil-html-templated-panel` height rule does not reach
   it, and without this rule
   .dashboard-container's min-height:100% resolves against an indefinite
   height and the dashboard collapses to content height.

   Written with .anvil-m3-content, not bare: that class is internal's own
   Material 3 content area and no other host declares it, so management's
   sla_stats_html keeps an auto-height root. !important matches the host
   rule this stands in for.
   No host declares .ap-shell-root, so this dep sheet loading before the host
   sheet cannot lose a tie on it.

   ABOVE the unterminated @media block, like the #kiosk-controls rule and for
   the same reason. */
.anvil-m3-content > .ap-shell-root {
  height: 100% !important;
  display: flex !important;
  flex-direction: column !important;
  flex: 1 !important;
  min-height: 0 !important;
}

/* ========================================
   RESPONSIVE HEADER
   Container queries handle both real mobile
   (container is full-width) and Anvil IDE preview
   ======================================== */
@media (max-width: 600px) {
  .dashboard-header {
    flex-wrap: wrap;
    gap: 10px;
    padding: 12px 80px;
  }
  .dashboard-btn {
    padding: 10px 18px;
    font-size: 13px;
    margin: 0 4px;
  }


/* ========================================
   HOME DETAIL MODAL (replaces anvil.alert)
   ======================================== */
#ap-home-modal .px-modal {
  width: 95vw;
  max-width: 1400px;
  max-height: 92vh;
}

#ap-home-modal .px-modal-body {
  padding: 0;
}

@media (max-width: 600px) {
  #ap-home-modal .px-modal {
    width: 100vw;
    max-height: 100vh;
    border-radius: 0;
  }
}
