/* dispatch_confirmation_html — the dispatch screen's own rules, kept here because
 * the Anvil server strips a template's <style> block.
 * Two hides sit in their own designer-gated rule, and the three rules at the
 * foot of this file carry what the format bans as markup attributes.
 *
 * ROOT. The form root is the .dc-wrapper div, so its rule stays BARE. It
 * declares neither height: 100% nor overflow-y: auto, like the other converted
 * screen roots (bagging_check_html.css, complaints_log_html.css,
 * auto_pmring_html.css and current_cycle_scripts.css). The scroller is main's
 * content mount, `.root-content-mount` in theme/assets/main/main.css
 * (height:100%; display:flex; flex-direction:column; overflow:auto), and
 * .dc-wrapper is a flex item directly inside it. A definite height there would
 * make the root its own scroller, which at <=768px (where the mount adds
 * padding-top: 60px) is two nested scrollbars on the tablet and kiosk dispatch
 * screen. The root is therefore sized by its content, and
 * dcGetScrollPosition / dcSetScrollPosition are no-ops (#dc-wrapper.scrollTop
 * is 0 on an auto-height box). No
 * flex: 1 0 auto is added, for bagging_check's reason: it would stretch
 * background: var(--px-bg-deep) down the page on a short screen. min-height:
 * 100vh IS set, and so are position, isolation and z-index, which the
 * pxShowLoading overlay is positioned against. .dc-wrapper.dc-mode-dashboard
 * keeps its own height: 100vh / min-height: unset / overflow: hidden unchanged:
 * that rule declares a definite height deliberately.
 *
 * SCOPING. :where(.dc-wrapper) adds zero specificity, so a scoped rule keeps
 * exactly the weight its bare selector had. A rule that ALREADY names the root
 * stays bare: .dc-wrapper.dc-mode-acute .dc-panel-active wrapped as
 * :where(.dc-wrapper) .dc-wrapper... would need a second wrapper inside the
 * wrapper and would never match. [data-theme="dark"] sits on <html>, an
 * ancestor of the root, so the scope goes AFTER it. #px-modal-portal
 * .dc-wrapper.dc-embedded stays bare too: its subject is this root and its
 * ancestor is the shell portal div, which is outside this form and is a
 * foundation-5.4 contract no section may touch.
 *
 * ORDER AUDIT. This asset is a head <link>, so it loads after
 * theme/assets/theme.css and before the dependency runtime theme injection.
 * ONE rule would tie with theme.css and so wins on specificity instead:
 * .px-page-title inside
 * @media (max-width: 600px), which theme.css declares once at :640 (0,1,0), is
 * written with the root as a REAL ancestor class, .dc-wrapper .px-page-title at
 * (0,2,0). The .px-btn-mode rule in the same block is NOT: theme.css declares
 * that class twice, :139 (0,1,0) and .px-btn.px-btn-mode :236 (0,2,0), and the
 * mode buttons carry both classes, so this rule loses on specificity and is
 * dead — it keeps :where() and stays dead (see the rule's own comment).
 * Neither class is declared anywhere in px-shared-dependencies-anvil.
 * .dc-wrapper.dc-embedded { display: none } and
 * #px-modal-portal .dc-wrapper.dc-embedded { display: flex } do NOT tie — the
 * id makes the second (1,2,0) against (0,2,0).
 * .themed-scrollbar sits on this root and nothing here declares a rule for it. The dashboard uncap keeps its (0,4,0) spelling, which each
 * card asset (0,3,0) re-assertion is written against. No @keyframes, no url(),
 * no @font-face, no :root and no html rule, so those rewrite steps have no work
 * here.
 *
 * DESIGNER GATE, html-free, on the root class .dc-live. Most hides are the
 * .dc-hidden state class, which the designer canvas loads with this asset, so
 * the canvas shows what first paint shows. FOUR RULES are gated instead:
 * .dc-panel { display: none } and .dc-checkin-bar { display: none } between
 * them hide
 * #dc-panel-monthly, #dc-panel-dashboard and the driver check-in bar — five of
 * the ten slots (monthly_scanner_slot, monthly_wedge_slot, monthly_cards_slot,
 * dashboard_acute_slot, dashboard_monthly_slot) and three of the five
 * anvil:name blocks (monthly_panel, dashboard_panel, driver_checkin_bar).
 * .dc-scanner-mount and .dc-queue-mount hide five dropzones between them
 * (scanner_slot, acute_wedge_slot, monthly_scanner_slot, monthly_wedge_slot,
 * acute_queue_slot); the owner ruling covers every dropzone, so those two are
 * gated as well. A head
 * link IS loaded by the designer, and the designer runs no Python, so ungated
 * those sections and every dropzone inside them measure 0 by 0 and staff cannot
 * reach two of the three modes at all. All four hides are therefore split into
 * their
 * own rule gated on .dc-live, which dc.mjs adds in initDispatch — the first
 * statement of form_show after its re-entry guard, before dcSwitchPanel and
 * before any data load — and removes in teardown. Both gated rules stay inside
 * :where() so they compute (0,1,0), exactly what they were: every reveal
 * (.dc-panel.dc-panel-active at (0,2,0), the check-in bar's inline display) is
 * heavier, so runtime is unchanged. The one canvas-only difference is that the
 * check-in bar flows as a block there: its display: flex was only ever the
 * inline value reconcileCheckinVisible writes, never a rule.
 * px-spoke-app 6c7c4fd is the shape.
 */

/* ========================================
   BASE STYLES
   ======================================== */
.dc-wrapper {
  font-family: var(--px-font);
  color: var(--px-text-primary);
  background: var(--px-bg-deep);
  min-height: 100vh;
  position: relative;
  isolation: isolate;
  z-index: 0;
  transition: background 0.3s ease;
  display: flex;
  flex-direction: column;
}

.dc-wrapper.dc-mode-acute {
  --accent: #22c55e; --accent-hover: #16a34a;
  --accent-subtle: rgba(34,197,94,0.1); --px-loading-accent: #22c55e;
}
.dc-wrapper.dc-mode-monthly {
  --accent: #fbbf24; --accent-hover: #f59e0b; --accent-text: #422006;
  --accent-subtle: rgba(251,191,36,0.1); --px-loading-accent: #fbbf24;
}
.dc-wrapper.dc-mode-dashboard {
  --accent: #64748b; --accent-hover: #475569;
  --accent-subtle: rgba(100,116,139,0.1); --px-loading-accent: #64748b;
  height: 100vh;
  min-height: unset;
  overflow: hidden;
}

:where(.dc-wrapper) .dc-container {
  padding: 16px 24px;
  flex: 1;
  display: flex;
  flex-direction: column;
}

/* ========================================
   POLLING RECOVERY BANNER (§6.1.E)
   ======================================== */
:where(.dc-wrapper) .dc-polling-paused {
  display: none;
  margin: 0 24px 8px 24px;
  padding: 8px 12px;
  background: var(--px-warning-soft, rgba(251, 191, 36, 0.18));
  color: var(--px-warning);
  border: 1px solid var(--px-warning);
  border-radius: var(--px-radius);
  font-size: 13px;
  text-align: center;
}
:where(.dc-wrapper) .dc-polling-paused.active { display: block; }

/* ========================================
   HEADER
   ======================================== */
:where(.dc-wrapper) .dc-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
  flex-wrap: wrap;
  gap: 12px;
}

:where(.dc-wrapper) .dc-header-left {
  display: flex;
  align-items: center;
  gap: 16px;
}

:where(.dc-wrapper) .dc-header-right {
  display: flex;
  align-items: center;
  gap: 12px;
}

:where(.dc-wrapper) .dc-title-block { display: flex; flex-direction: column; }

/* ========================================
   MODE BUTTONS
   ======================================== */
:where(.dc-wrapper) .dc-mode-buttons {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

/* ========================================
   CONTENT PANELS
   ======================================== */
:where(.dc-wrapper.dc-live) .dc-panel {
  display: none;
}

:where(.dc-wrapper) .dc-panel.dc-panel-active {
  display: block;
  flex: 1;
}

:where(.dc-wrapper) #dc-panel-dashboard.dc-panel-active {
  display: flex;
  flex-direction: column;
}

.dc-wrapper.dc-mode-acute .dc-panel-active {
  background: #D4EDDA;
  border-radius: var(--px-radius);
  padding: 16px;
}
.dc-wrapper.dc-mode-monthly .dc-panel-active {
  background: #FFF9E1;
  border-radius: var(--px-radius);
  padding: 16px;
}
[data-theme="dark"] .dc-wrapper.dc-mode-acute .dc-panel-active { background: #1a3a24; }
[data-theme="dark"] .dc-wrapper.dc-mode-monthly .dc-panel-active { background: #423a1d; }

:where(.dc-wrapper) .dc-panel-header {
  text-align: center;
  margin-bottom: 16px;
}

:where(.dc-wrapper) .dc-panel-title {
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--px-text-primary);
  margin: 0 0 8px 0;
  text-decoration: underline;
}

/* ========================================
   CARDS FLOW PANEL
   ======================================== */
:where(.dc-wrapper) .dc-cards-container {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  justify-content: center;
  padding: 8px 0;
}

:where(.dc-wrapper) .dc-monthly-empty {
  text-align: center;
  color: var(--px-text-muted);
  font-size: 15px;
  padding: 32px 16px;
}

/* ========================================
   SCANNER SECTION
   ======================================== */
:where(.dc-wrapper) .dc-scanner-section {
  margin: 8px 0 16px;
}

/* Embedded (manager "view remaining dispatches" modal): interactive
   cards but no scanner and no driver check-in bar. */
.dc-wrapper.dc-embedded .dc-scanner-section,
.dc-wrapper.dc-embedded .dc-checkin-bar,
.dc-wrapper.dc-embedded .dc-scanner-toggle,
.dc-wrapper.dc-embedded .dc-scan-history { display: none !important; }
/* px_form_alert mounts the form into the page content slot and the form's
   show event blocking-loads its cards THERE before the node is moved into
   the modal. Stay hidden until we're actually inside the modal portal, so
   that full-page load never flashes inline below the approve table. */
.dc-wrapper.dc-embedded { display: none; }
#px-modal-portal .dc-wrapper.dc-embedded { display: flex; min-height: 0; }

:where(.dc-wrapper) .dc-scan-history {
  padding: 12px;
  background: var(--px-bg-card);
  border-radius: 8px;
  margin-top: 12px;
  min-height: 40px;
}

:where(.dc-wrapper) .dc-scan-history-empty {
  color: var(--px-text-muted);
  text-align: center;
  font-style: italic;
}

/* ========================================
   DASHBOARD MODE
   ======================================== */
:where(.dc-wrapper) .dc-dashboard-flow {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 0;
  overflow: hidden;
}

:where(.dc-wrapper) .dc-dashboard-section {
  border-radius: 12px;
  padding: 8px 12px;
  overflow: hidden;
  min-height: 0;
}

:where(.dc-wrapper) .dc-dashboard-section-acute { background: #D4EDDA; }
:where(.dc-wrapper) .dc-dashboard-section-monthly { background: #FFF9E1; }
[data-theme="dark"] :where(.dc-wrapper) .dc-dashboard-section-acute { background: #1a3a24; }
[data-theme="dark"] :where(.dc-wrapper) .dc-dashboard-section-monthly { background: #423a1d; }

:where(.dc-wrapper) .dc-dashboard-section-title {
  font-size: 0.8rem;
  font-weight: 600;
  text-align: center;
  color: var(--px-text-primary);
  margin: 0 0 4px 0;
}

:where(.dc-wrapper) .dc-dashboard-section .dc-cards-container {
  display: flex !important;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
  align-items: flex-start;
  padding: 0;
}

/* (0,4,0), not (0,2,0). Each card asset re-asserts its own max-width
   at (0,3,0) so theme.css's `.px-anvil-reset .px-flow-container>*`
   cannot uncap it once the converted card root holds the slot's
   direct-child place; the dashboard uncap has to outrank that
   re-assertion rather than tie with it. */
.px-anvil-reset .dc-dashboard-section .dca-card.px-anvil-reset,
.px-anvil-reset .dc-dashboard-section .dcm-card.px-anvil-reset {
  min-width: unset !important;
  max-width: unset !important;
  cursor: default;
  pointer-events: none;
}

:where(.dc-wrapper) .dc-dashboard-section .dcm-button-row {
  display: none;
}

/* Names the card, not the container's direct child. At the shell's
   conversion an <anvil-dropzone> whose computed display is `contents`
   sits between the container and the card, and a `display: contents`
   box generates nothing to zoom (guide, the `.rc-split-grid > div`
   trap). Same subject either way today. */
:where(.dc-wrapper) .dc-dashboard-section-acute .dc-cards-container .dca-card {
  zoom: var(--dc-acute-zoom, 1);
}

:where(.dc-wrapper) .dc-dashboard-section-monthly .dc-cards-container .dcm-card {
  zoom: var(--dc-monthly-zoom, 1);
}

/* ========================================
   CONFIRM BUTTON
   ======================================== */
:where(.dc-wrapper) .dc-confirm-section {
  text-align: center;
  margin-top: 24px;
}

/* Kiosk chrome: visual styles live in theme.css (.px-kiosk-*); only positioning here. */
:where(.dc-wrapper) #dc-kiosk-controls {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 1000;
}

/* ========================================
   SLOTS
   ======================================== */
:where(.dc-wrapper) .dc-scanner-slot-mount {
  display: block;
}

/* Parent-screen scanner mode toggle. Pre-mount both camera + wedge
   so a denied/broken camera doesn't lock the user out of starting a
   dispatch. The .dc-active class controls visibility. */
:where(.dc-wrapper) .dc-scanner-toggle {
  display: flex;
  gap: 6px;
  margin: 0 0 8px 0;
}
:where(.dc-wrapper) .dc-scan-mode-btn {
  padding: 4px 12px;
  font-size: 0.85rem;
}
:where(.dc-wrapper) .dc-scan-mode-btn.dc-active {
  background: var(--accent);
  color: var(--accent-on);
}
:where(.dc-wrapper) .dc-scanner-mount {
  /* The open state. The hide is the gated rule below: this div holds the
     camera and wedge dropzones (scanner_slot, acute_wedge_slot,
     monthly_scanner_slot, monthly_wedge_slot) and a hidden dropzone measures
     0 by 0 on the designer canvas. */
  display: block;
}
/* DESIGNER GATE. See the header. */
:where(.dc-wrapper.dc-live) .dc-scanner-mount {
  display: none;
}
:where(.dc-wrapper) .dc-scanner-mount.dc-active {
  display: block;
}

/* Card slots use px-flow-container (theme.css) to override
   the px-anvil-reset width:100% on Anvil wrappers. */

/* ========================================
   DRIVER CHECK-IN BAR
   Driver requests a duty-manager check-in before leaving on a run,
   then scans the manager's approval DataMatrix here. Hidden in
   team-view/kiosk (shared screen performs no DB-writing actions) and
   in dashboard mode. See dcReconcileCheckinVisible().
   ======================================== */
:where(.dc-wrapper) .dc-checkin-bar {
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  margin: 0 0 12px;
  padding: 10px 14px;
  background: var(--px-bg-card);
  border: 1px solid var(--px-border);
  border-radius: var(--px-radius);
}
/* Designer gate, split out of the rule above. reconcileCheckinVisible writes
   this bar's display INLINE on every dcSwitchPanel, so at runtime the gated
   hide is only ever the pre-switch state it always was; on the canvas, where no
   Python runs, the bar and its named block stay visible and editable. */
:where(.dc-wrapper.dc-live) .dc-checkin-bar {
  display: none;
}
:where(.dc-wrapper) .dc-checkin-status { display: flex; align-items: center; gap: 8px; }
:where(.dc-wrapper) .dc-checkin-label {
  font-weight: 600;
  color: var(--px-text-secondary);
  font-size: 0.9rem;
}
:where(.dc-wrapper) .dc-checkin-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 0.82rem;
  font-weight: 600;
}
:where(.dc-wrapper) .dc-checkin-chip-none { background: rgba(100,116,139,0.15); color: #475569; }
:where(.dc-wrapper) .dc-checkin-chip-pending { background: rgba(251,191,36,0.18); color: #b45309; }
:where(.dc-wrapper) .dc-checkin-chip-approved { background: rgba(34,197,94,0.18); color: #15803d; }
:where(.dc-wrapper) .dc-checkin-chip-missed { background: rgba(239,68,68,0.18); color: #b91c1c; }
[data-theme="dark"] :where(.dc-wrapper) .dc-checkin-chip-none { background: rgba(100,116,139,0.25); color: #cbd5e1; }
[data-theme="dark"] :where(.dc-wrapper) .dc-checkin-chip-pending { background: rgba(251,191,36,0.22); color: #fcd34d; }
[data-theme="dark"] :where(.dc-wrapper) .dc-checkin-chip-approved { background: rgba(34,197,94,0.22); color: #86efac; }
[data-theme="dark"] :where(.dc-wrapper) .dc-checkin-chip-missed { background: rgba(239,68,68,0.22); color: #fca5a5; }
:where(.dc-wrapper) .dc-checkin-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-left: auto;
}
:where(.dc-wrapper) .dc-checkin-note {
  padding: 6px 10px;
  font-size: 0.85rem;
  border: 1px solid var(--px-border);
  border-radius: var(--px-radius);
  background: var(--px-bg-input);
  color: var(--px-text-primary);
  min-width: 220px;
}
/* Closed-block note. Hidden by default; dcSetCheckinBlockOpen(false)
   reveals it (and hides the note/request controls). */
:where(.dc-wrapper) .dc-checkin-closed-note {
  display: none;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--px-text-secondary);
}

/* ========================================
   RESPONSIVE
   ======================================== */
@media (max-width: 900px) {
  :where(.dc-wrapper) .dc-header {
    flex-direction: column;
    align-items: flex-start;
  }

  :where(.dc-wrapper) .dc-mode-buttons {
    width: 100%;
    justify-content: center;
  }
}

@media (max-width: 600px) {
  :where(.dc-wrapper) .dc-container {
    padding: 12px;
  }

  /* STAYS :where(), STAYS DEAD. theme.css declares this class twice, .px-btn-mode
     at :139 (0,1,0) and .px-btn.px-btn-mode at :236 (0,2,0) with padding: 10px
     20px; font-size: 0.9rem, and all three mode buttons carry both classes, so
     this rule at (0,1,0) loses to :236 on specificity whatever the order and
     never applies. Spelled .dc-wrapper .px-btn-mode it would reach
     (0,2,0), tie with :236 and win that tie on this link's later position,
     shrinking the three mode buttons at <=600px. :where()
     keeps it at (0,1,0) and so keeps it dead, which is what it was. */
  :where(.dc-wrapper) .px-btn-mode { padding: 8px 14px; font-size: 0.8rem; }
  /* .px-page-title DOES need the real ancestor class: theme.css declares it once,
     at :640 (0,1,0), so this rule won on order before and wins on specificity
     now. No dependency rule competes for either class. */
  .dc-wrapper .px-page-title { font-size: 1.25rem; }
}

/* ========================================
   THE MARKUP ATTRIBUTES THE FORMAT BANS, AS CLASSES
   ======================================== */

/* The acute rapid-scan queue mount div carried style="display:none":
   scan_queue is an invisible component and its mount must generate no box.
   DESIGNER GATE on .dc-live all the same, because the div holds the
   acute_queue_slot dropzone and staff cannot drop into a box that is not
   there. See the header. */
:where(.dc-wrapper.dc-live) .dc-queue-mount { display: none; }

/* The three remaining initial hides: #dc-monthly-empty and
   #dc-dashboard-monthly-empty (dcSetMonthlyEmptyById),
   #dc-monthly-confirm-section (dcSetMonthlyAdminVisible) and
   #dc-kiosk-controls. The first three are TOGGLED by the module through
   this class, not an inline display: clearing element.style.display against
   a class-based hide would leave the element hidden with no error. .dc-confirm-section and
   .dc-monthly-empty declare no display of their own, so a lone .dc-hidden ties
   with nothing. */
:where(.dc-wrapper) .dc-hidden { display: none; }

/* .px-kiosk-controls DOES declare display: flex (theme.css) at (0,1,0),
   so its hide is a compound that wins on specificity rather than on this
   file position. pxKioskMountChrome writes an inline display: flex when the
   kiosk chrome mounts and dcSetKioskMode writes an inline display: none when
   it does not, and inline beats both, so this class is never removed. */
:where(.dc-wrapper) .px-kiosk-controls.dc-hidden { display: none; }
