/* ============================================================
   PrimeTable Dashboard — Production CSS v2
   Operational Premium: cockpit density, editorial restraint
   ============================================================ */

/* ── Design Tokens ─────────────────────────────────────────── */
:root {
  /* Sidebar — near-black chalkboard green, aged and confident */
  --sidebar-bg:      oklch(15% 0.055 158);
  --sidebar-hover:   oklch(21% 0.055 158);
  --sidebar-active:  oklch(24% 0.055 158);
  --sidebar-fg:      oklch(93% 0.004 80);
  --sidebar-fg-dim:  oklch(60% 0.012 80);
  --sidebar-border:  oklch(30% 0.040 158);
  --sidebar-accent:  oklch(66% 0.13 82);

  /* Working surface */
  --bg:              oklch(99% 0 0);
  --surface:         oklch(100% 0 0);
  --surface-muted:   oklch(97.5% 0.002 80);
  --border:          oklch(92.5% 0.002 80);

  /* Ink — warm near-black hierarchy */
  --ink:             oklch(17% 0.012 52);
  --ink-secondary:   oklch(44% 0.010 52);
  --ink-tertiary:    oklch(61% 0.007 52);

  /* Semantic aliases (used in Razor via var(...)) */
  --ink-muted:       var(--ink-secondary);
  --surface-raised:  var(--surface);

  /* Action accent — aged gold, used only where action required */
  --accent:          oklch(65% 0.13 82);
  --accent-hover:    oklch(60% 0.13 82);
  --accent-fg:       oklch(17% 0.02 52);

  /* Status palette — muted, informative, never decorative */
  --s-new:           oklch(49% 0.08 242);
  --s-new-bg:        oklch(97.5% 0.010 242);
  --s-prep:          oklch(62% 0.10 82);
  --s-prep-bg:       oklch(97.5% 0.014 82);
  --s-ready:         oklch(44% 0.09 155);
  --s-ready-bg:      oklch(97.5% 0.012 155);
  --s-danger:        oklch(45% 0.11 24);
  --s-danger-bg:     oklch(97.5% 0.012 24);
  --s-neutral:       oklch(52% 0.005 80);
  --s-neutral-bg:    oklch(96% 0.002 80);

  /* Semantic aliases for Razor C# inline styles */
  --success:         var(--s-ready);
  --success-tint:    var(--s-ready-bg);
  --warning:         var(--s-prep);
  --warning-tint:    var(--s-prep-bg);
  --danger:          var(--s-danger);
  --danger-tint:     var(--s-danger-bg);
  --info:            var(--s-new);
  --info-tint:       var(--s-new-bg);

  /* Typography */
  --font-display: 'Lora', Georgia, serif;
  --font-body:    'Nunito', system-ui, sans-serif;

  --text-2xs: 0.6875rem;
  --text-xs:  0.75rem;
  --text-sm:  0.875rem;
  --text-base: 0.9375rem;
  --text-md:  1.0625rem;
  --text-lg:  1.25rem;
  --text-xl:  1.625rem;
  --text-2xl: 2.125rem;
  --text-3xl: 2.75rem;

  /* Radii */
  --radius-sm: 5px;
  --radius-md: 8px;
  --radius-lg: 10px;
  --radius-xl: 14px;

  /* Elevation */
  --shadow-card:  0 1px 2px oklch(0% 0 0 / 0.04), 0 3px 10px oklch(0% 0 0 / 0.05);
  --shadow-hover: 0 2px 8px oklch(0% 0 0 / 0.06), 0 12px 32px oklch(0% 0 0 / 0.07);
  --shadow-panel: 0 8px 40px oklch(0% 0 0 / 0.16), 0 2px 8px oklch(0% 0 0 / 0.08);

  /* Motion */
  --ease:      cubic-bezier(0.2, 0, 0, 1);
  --dur-fast:  120ms;
  --dur-base:  150ms;
  --dur-panel: 200ms;
}

/* ── Reset ────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html {
  font-size: 16px;
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--ink);
  background: var(--bg);
  margin: 0;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ── Typography ───────────────────────────────────────────── */
h1, h2, h3 {
  font-family: var(--pt-font-display);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.015em;
  color: var(--pt-ink-900);
  margin-top: 0;
}

h1 { font-size: var(--text-2xl); }
h2 { font-size: var(--text-xl); }
h3 { font-size: var(--text-lg); }

h4, h5, h6 {
  font-family: var(--font-body);
  font-weight: 700;
  letter-spacing: -0.01em;
  margin-top: 0;
  color: var(--ink);
}

p { margin-top: 0; }
a { color: var(--accent); }
h1:focus { outline: none; }

/* Numbers are heroes on data pages */
.stat-card__value {
  font-variant-numeric: tabular-nums;
}

/* ── Layout ───────────────────────────────────────────────── */
.page {
  display: flex;
  flex-direction: row;
  /* This shell is sized in dvh deliberately (Task 4 rewrites this shell; it is not itself the
     overlay sizing contract): a phone's dynamic toolbar and its virtual keyboard both shrink
     the visible area below 100vh. The vh line above the dvh one is a fallback for engines
     older than 2022 — an unsupported unit drops the whole declaration rather than degrading,
     which would leave this layout with no height floor at all — and stays inert under the
     cascade wherever dvh is understood. */
  min-height: 100vh;
  min-height: 100dvh;
}

.sidebar {
  width: 240px;
  min-width: 240px;
  /* Same dvh-with-vh-fallback shape as .page above, and for the same reason: on desktop this
     rule is the sidebar's whole height constraint, so an unsupported dvh must not drop it. */
  height: 100vh;
  height: 100dvh;
  position: sticky;
  top: 0;
  overflow-y: auto;
  background: var(--sidebar-bg);
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
}

main {
  flex: 1;
  min-width: 0;
  background: var(--bg);
}

.content {
  padding: 2rem 2.5rem;
  min-height: 100%;
}

/* ── Page Header ─────────────────────────────────────────── */
.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 2rem;
  padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--border);
}

.page-header h1 { margin-bottom: 0; }

/* ── Cards ────────────────────────────────────────────────── */
.card {
  background: var(--surface) !important;
  border: 1px solid var(--border) !important;
  border-radius: var(--radius-lg) !important;
  box-shadow: var(--shadow-card);
}

.card-header {
  background: var(--surface-muted) !important;
  border-bottom: 1px solid var(--border) !important;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--text-sm);
  color: var(--ink-secondary);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0 !important;
  padding: 0.75rem 1rem;
}

.card-body { padding: 1rem; }

.card-footer {
  background: var(--surface-muted) !important;
  border-top: 1px solid var(--border) !important;
  font-size: var(--text-sm);
  color: var(--ink-secondary);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg) !important;
}

/* ── Buttons ──────────────────────────────────────────────── */
.btn {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--text-sm);
  border-radius: var(--radius-md);
  transition:
    background-color var(--dur-base) var(--ease),
    border-color     var(--dur-base) var(--ease),
    box-shadow       var(--dur-base) var(--ease);
  cursor: pointer;
}

.btn-primary {
  background: var(--accent) !important;
  color: var(--accent-fg) !important;
  border-color: var(--accent) !important;
}
.btn-primary:hover {
  background: var(--accent-hover) !important;
  border-color: var(--accent-hover) !important;
}

.btn-success {
  background: var(--s-ready) !important;
  color: white !important;
  border-color: var(--s-ready) !important;
}
.btn-success:hover { filter: brightness(1.1); }

.btn-danger {
  background: var(--s-danger) !important;
  color: white !important;
  border-color: var(--s-danger) !important;
}
.btn-danger:hover { filter: brightness(1.1); }

.btn-warning {
  background: var(--s-prep) !important;
  color: var(--accent-fg) !important;
  border-color: var(--s-prep) !important;
}
.btn-warning:hover { filter: brightness(1.08); }

.btn-secondary {
  background: var(--surface-muted) !important;
  color: var(--ink-secondary) !important;
  border-color: var(--border) !important;
}
.btn-secondary:hover {
  background: var(--border) !important;
  color: var(--ink) !important;
}

.btn-outline-secondary {
  background: transparent !important;
  color: var(--ink-secondary) !important;
  border-color: var(--border) !important;
}
.btn-outline-secondary:hover {
  background: var(--surface-muted) !important;
  color: var(--ink) !important;
}

.btn-outline-primary {
  background: transparent !important;
  color: var(--accent) !important;
  border: 1.5px solid var(--accent) !important;
}
.btn-outline-primary:hover { background: var(--s-prep-bg) !important; }

.btn-outline-danger {
  background: transparent !important;
  color: var(--s-danger) !important;
  border-color: var(--s-danger) !important;
}
.btn-outline-danger:hover { background: var(--s-danger-bg) !important; }

.btn-sm {
  padding: 0.3rem 0.85rem;
  font-size: var(--text-sm);
}

.btn-xs {
  padding: 0.2rem 0.6rem;
  font-size: var(--text-xs);
  border-radius: var(--radius-sm);
  min-height: 30px;
}

.btn:focus-visible,
.btn:active:focus,
.btn-link.nav-link:focus,
.form-control:focus,
.form-check-input:focus {
  outline: none;
  box-shadow: 0 0 0 3px oklch(65% 0.13 82 / 0.28);
}

/* ── Tables ───────────────────────────────────────────────── */
.table-responsive {
  border-radius: var(--radius-lg);
  overflow: hidden;
  overflow-x: auto;
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
}

.table {
  margin-bottom: 0;
  font-size: var(--text-base);
  background: var(--surface);
}

.table thead th {
  background: var(--surface-muted);
  color: var(--ink-tertiary);
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border-bottom: 1px solid var(--border);
  padding: 0.625rem 1rem;
  white-space: nowrap;
}

.table tbody tr {
  border-bottom: 1px solid var(--border);
  transition: background var(--dur-fast) var(--ease);
}
.table tbody tr:hover { background: var(--surface-muted); }

.table tbody td {
  padding: 0.75rem 1rem;
  vertical-align: middle;
  border-top: none;
  border-bottom: 1px solid var(--border);
  color: var(--ink);
}

.table-striped > tbody > tr:nth-of-type(odd) > * {
  background-color: transparent;
}

/* ── Badges ───────────────────────────────────────────────── */
.badge {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 600;
  padding: 0.15rem 0.5rem;
  border-radius: 4px;
  border: none !important;
  letter-spacing: 0.01em;
}

.bg-primary   { background: var(--s-new-bg) !important;     color: var(--s-new) !important; }
.bg-success   { background: var(--s-ready-bg) !important;   color: var(--s-ready) !important; }
.bg-warning   { background: var(--s-prep-bg) !important;    color: oklch(50% 0.10 78) !important; }
.bg-danger    { background: var(--s-danger-bg) !important;  color: var(--s-danger) !important; }
.bg-secondary { background: var(--s-neutral-bg) !important; color: var(--s-neutral) !important; }
.bg-info      { background: var(--s-new-bg) !important;     color: var(--s-new) !important; }
.bg-light     { background: var(--surface-muted) !important; color: var(--ink-secondary) !important; }

/* ── Forms ────────────────────────────────────────────────── */
label {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink);
}

.form-control,
.form-select {
  background: white;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.5rem 0.75rem;
  font-family: var(--font-body);
  font-size: var(--text-base);
  color: var(--ink);
  transition:
    border-color var(--dur-base) var(--ease),
    box-shadow   var(--dur-base) var(--ease);
}

.form-control:focus,
.form-select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px oklch(65% 0.13 82 / 0.18);
  outline: none;
}

.form-control.is-invalid,
.form-select.is-invalid { border-color: var(--s-danger); }

.invalid-feedback,
.validation-message { color: var(--s-danger); font-size: var(--text-sm); }

.valid.modified:not([type=checkbox]) { outline: 1px solid var(--s-ready); }
.invalid { outline: 1px solid var(--s-danger); }
.darker-border-checkbox.form-check-input { border-color: var(--border); }

/* ── Alerts ───────────────────────────────────────────────── */
.alert { border-radius: var(--radius-lg); font-size: var(--text-base); }

.alert-danger {
  background: var(--s-danger-bg) !important;
  border: 1px solid oklch(75% 0.06 24) !important;
  color: oklch(35% 0.10 24) !important;
}
.alert-warning {
  background: var(--s-prep-bg) !important;
  border: 1px solid oklch(80% 0.07 82) !important;
  color: oklch(42% 0.10 78) !important;
}
.alert-success {
  background: var(--s-ready-bg) !important;
  border: 1px solid oklch(78% 0.06 155) !important;
  color: oklch(32% 0.08 155) !important;
}

/* ── Bootstrap utility overrides ─────────────────────────── */
.text-muted    { color: var(--ink-secondary) !important; }
.text-danger   { color: var(--s-danger) !important; }
.text-success  { color: var(--s-ready) !important; }
.text-warning  { color: var(--s-prep) !important; }
.small         { font-size: var(--text-sm); }

/* ── Blazor Error UI ──────────────────────────────────────── */
.blazor-error-boundary {
  background: var(--s-danger-bg);
  border: 1px solid var(--s-danger);
  border-radius: var(--radius-lg);
  padding: 1rem 1rem 1rem 3.7rem;
  color: oklch(35% 0.10 24);
}
.blazor-error-boundary::after { content: "An error has occurred."; }

#blazor-error-ui {
  background: var(--pt-danger-surface);
  border-top: 1px solid var(--pt-danger);
  bottom: 0;
  box-shadow: 0 -1px 4px oklch(0% 0 0 / 0.12);
  display: none;
  left: 0;
  padding: 0.6rem 1.25rem 0.7rem;
  position: fixed;
  width: 100%;
  z-index: 1000;
  font-family: var(--pt-font-body);
  font-size: var(--text-sm);
  color: var(--pt-on-danger);
}
#blazor-error-ui .dismiss {
  cursor: pointer;
  position: absolute;
  right: 0.75rem;
  top: 0.5rem;
}

/* ── Pulse indicator ──────────────────────────────────────── */
.refresh-indicator {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--s-ready);
  animation: pulse 2s ease-in-out infinite;
  will-change: transform, opacity;
  flex-shrink: 0;
}

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

@media (prefers-reduced-motion: reduce) {
  .refresh-indicator { animation: none; }
}

/* ── Time filter (Analytics) ──────────────────────────────── */
.time-filter {
  display: flex;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--surface);
  box-shadow: var(--shadow-card);
}

.time-filter__btn {
  padding: 0.35rem 0.875rem;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  background: transparent;
  border: none;
  border-right: 1px solid var(--border);
  cursor: pointer;
  color: var(--ink-tertiary);
  transition:
    background var(--dur-fast) var(--ease),
    color      var(--dur-fast) var(--ease);
}
.time-filter__btn:last-child { border-right: none; }

.time-filter__btn--active {
  background: var(--sidebar-bg);
  color: var(--sidebar-fg);
}
.time-filter__btn:hover:not(.time-filter__btn--active) {
  background: var(--surface-muted);
  color: var(--ink);
}

/* ── Analytics stat row ───────────────────────────────────── */
/* ── Analytics charts ─────────────────────────────────────── */
/* ── Analytics tiles ──────────────────────────────────────── */
/* ── Home Dashboard Stat Cards ────────────────────────────── */
.stat-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.25rem;
  margin-bottom: 2.5rem;
}

.stat-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 1.5rem 1.5rem 1.25rem;
  box-shadow: var(--shadow-card);
}

.stat-card__icon {
  font-size: 1.125rem;
  color: var(--accent);
  margin-bottom: 0.75rem;
  opacity: 0.65;
}

.stat-card__label {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--ink-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  margin-bottom: 0.2rem;
}

.stat-card__value {
  font-family: var(--pt-font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  color: var(--ink);
  line-height: 1.05;
  letter-spacing: -0.02em;
}

/* ── Quick Nav ────────────────────────────────────────────── */
.quick-nav {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
  max-width: 600px;
  margin-top: 2rem;
}

.quick-nav--wide {
  grid-template-columns: repeat(3, 1fr);
  max-width: none;
}

.quick-nav-tile {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  padding: 1.375rem 1.5rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  text-decoration: none;
  color: var(--ink);
  transition:
    border-color var(--dur-base) var(--ease),
    box-shadow   var(--dur-base) var(--ease);
  box-shadow: var(--shadow-card);
}

.quick-nav-tile:hover {
  border-color: oklch(65% 0.13 82 / 0.5);
  box-shadow: var(--shadow-hover);
  color: var(--ink);
  text-decoration: none;
}

.quick-nav-tile__icon {
  font-size: 1.5rem;
  color: var(--accent);
  line-height: 1;
  margin-bottom: 0.25rem;
}

.quick-nav-tile__title {
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: 700;
  color: var(--ink);
}

.quick-nav-tile__desc {
  font-size: var(--text-sm);
  color: var(--ink-secondary);
  line-height: 1.45;
}

/* ── Settings ─────────────────────────────────────────────── */
.settings-tabs {
  display: flex;
  border-bottom: 1px solid var(--border);
  margin-bottom: 2rem;
}

.settings-tab-btn {
  padding: 0.625rem 1.5rem;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--text-base);
  color: var(--ink-tertiary);
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  cursor: pointer;
  transition:
    color        var(--dur-base) var(--ease),
    border-color var(--dur-base) var(--ease);
}
.settings-tab-btn:hover { color: var(--ink); }
.settings-tab-btn.active {
  color: var(--ink);
  border-bottom-color: var(--accent);
}

.settings-note {
  font-size: var(--text-sm);
  color: var(--ink-secondary);
  margin-top: 0.35rem;
}

/* One preference per row: what it does on the left, the control that changes it on the right.
   Unlike the rest of Settings there is no Save button here — the switch writes straight to the
   device, so the row has to carry its own affordance and read as already-applied. */
.setting-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 1.125rem 1.25rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
}

.setting-row__text { min-width: 0; }

.setting-row__label {
  display: block;
  font-family: var(--font-body);
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
}

.setting-row__control {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  flex: none;
  padding-top: 0.125rem;
}

.setting-row__state {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink-secondary);
  min-width: 1.75rem;
}

/* Connection indicator. Colour alone never carries the meaning — the word beside it does. */
.conn-dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  flex: none;
}
.conn-dot--up   { background: var(--success); }
.conn-dot--down { background: var(--ink-tertiary); }

/* Switch. The real checkbox sits transparent on top of the whole control, so keyboard focus,
   screen readers and the click target all come from the native element. */
.switch {
  position: relative;
  display: inline-flex;
  flex: none;
}

.switch input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.switch__track {
  display: flex;
  align-items: center;
  width: 2.75rem;
  height: 1.5rem;
  padding: 0.1875rem;
  border-radius: 999px;
  background: var(--border);
  transition: background var(--dur-base) var(--ease);
}

.switch__thumb {
  width: 1.125rem;
  height: 1.125rem;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: 0 1px 2px oklch(0% 0 0 / 0.25);
  transition: transform var(--dur-base) var(--ease);
}

.switch input:checked + .switch__track { background: var(--accent); }
.switch input:checked + .switch__track .switch__thumb { transform: translateX(1.25rem); }
.switch input:focus-visible + .switch__track {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .switch__track,
  .switch__thumb { transition: none; }
}

.image-preview {
  width: 80px;
  height: 80px;
  object-fit: cover;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  margin-top: 0.5rem;
  display: block;
}

.image-preview-wrapper {
  display: inline-flex;
  align-items: flex-end;
  gap: 0.5rem;
  margin-top: 0.5rem;
}

.image-preview-wrapper .image-preview {
  margin-top: 0;
}

.image-remove-btn {
  font-size: var(--text-xs);
  padding: 0.2rem 0.5rem;
  white-space: nowrap;
}

/* ── Dialog / Modal ───────────────────────────────────────── */
dialog {
  border: none;
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-panel);
  padding: 0;
  max-width: 520px;
  width: 100%;
}

dialog[open] {
  animation: dialog-in var(--dur-panel) var(--ease);
}

@keyframes dialog-in {
  from { opacity: 0; transform: translateY(-8px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  dialog[open] { animation: none; }
}

dialog::backdrop { background: oklch(0% 0 0 / 0.42); }

.dialog-header {
  padding: 1.375rem 1.5rem 1rem;
  border-bottom: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.dialog-header h2, .dialog-header h3 { margin: 0; font-size: var(--text-lg); }

.dialog-body { padding: 1.5rem; }

.dialog-footer {
  padding: 1rem 1.5rem;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: flex-end;
  gap: 0.75rem;
  background: var(--surface-muted);
  border-radius: 0 0 var(--radius-xl) var(--radius-xl);
}

.dialog-close {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 1.25rem;
  color: var(--ink-tertiary);
  padding: 0.25rem 0.4rem;
  border-radius: var(--radius-sm);
  line-height: 1;
  transition:
    color      var(--dur-fast) var(--ease),
    background var(--dur-fast) var(--ease);
}
.dialog-close:hover {
  color: var(--ink);
  background: var(--surface-muted);
}

/* The pre-Capy confirmation rules that used to live here were deleted, not left dormant: the
   confirmation is now dressed by the scoped ConfirmDialog.razor.css (Producto dress, --pt-* only)
   under its own class names. The generic dialog/.dialog-header/.dialog-body/.dialog-footer rules
   above stay — the screens' own unmigrated edit dialogs still use them. */

/* ── Drawer ───────────────────────────────────────────────── */
/* No padding, on any edge: this is a right-anchored, full-height drawer, not a centered sheet
   that wants breathing room. Horizontal padding parked the drawer's right edge inside the
   viewport with the shadow hanging in the gap. A bottom safe-area floor here would be equally
   inert — .drawer sets an explicit height (100dvh, see below) that already overflows this
   container's content box to reach the true viewport edges, so any padding-bottom here is never
   actually rendered. If this overlay ever stops being edge-to-edge, redo the sizing, don't just
   add padding back. */
.drawer-overlay {
  position: fixed;
  inset: 0;
  background: var(--pt-scrim);
  z-index: 300;
  display: flex;
  justify-content: flex-end;
  animation: overlay-in var(--dur-base) var(--ease);
}

@keyframes overlay-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.drawer {
  background: var(--pt-surface);
  width: min(480px, 96vw);
  /* dvh, not vh: a phone's dynamic toolbar and its virtual keyboard both shrink the visible
     area below 100vh, which put this panel's footer — and its primary action — out of reach. */
  height: 100dvh;
  overflow: hidden;
  box-shadow: -6px 0 40px oklch(0% 0 0 / 0.16);
  display: flex;
  flex-direction: column;
  animation: drawer-in var(--dur-panel) var(--ease);
}

@keyframes drawer-in {
  from { transform: translateX(100%); }
  to   { transform: translateX(0); }
}

@media (prefers-reduced-motion: reduce) {
  .drawer-overlay { animation: none; }
  .drawer { animation: none; }
}

.drawer__header {
  padding: 1.375rem 1.5rem 1rem;
  border-bottom: 1px solid var(--pt-line-200);
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  flex-shrink: 0;
  gap: 1rem;
}
.drawer__header h3 { margin: 0; }

.drawer__body {
  padding: 1.5rem;
  flex: 1;
  overflow-y: auto;
}

.drawer__footer {
  padding: 1rem 1.5rem;
  border-top: 1px solid var(--pt-line-200);
  display: flex;
  justify-content: flex-end;
  gap: 0.75rem;
  background: var(--pt-app-bg);
  flex-shrink: 0;
}

.drawer--full {
  width: min(1100px, 96vw);
  max-width: 96vw;
}

/* ── Drawer sections (photo, options) ──────────────────────── */
.drawer-section {
  margin-top: 1.25rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--pt-line-200);
}
.drawer-section .form-label {
  font-weight: 600;
  margin-bottom: 0.5rem;
}
.drawer-photo-preview {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
}
.pending-option-group {
  font-size: var(--text-sm);
}
.pending-option-group table {
  margin-bottom: 0;
}

/* Orders (Pedidos) is fully owned by the Capy scoped stylesheet, Orders.razor.css — the
   pre-Capy .order-tabs/.order-tab-btn/.order-status-group*/.live-order-grid/.live-order-card*/
   .history-filters* rules that used to live here were deleted rather than left dormant (P14
   Task 5 Step 3), same as the Menu cleanup note below: none of them are referenced by any
   .razor or .razor.css file in this project any more, and none share a class name with another
   screen's markup. .order-card (Home/Menu/QrCodes/Waiter/ErrorPanel's own scoped classes) and
   generic classes the old screen also used — .drawer*, .empty-state*, .page-header,
   .refresh-indicator, .dialog-close — are untouched: other, still-unmigrated screens use them. */

/* Menu (two-panel, sections, dish rows) is fully owned by the Capy scoped stylesheets:
   MenuCategories.razor.css, MenuCategoryHeader.razor.css and MenuItemRow.razor.css.
   The pre-Capy rules that used to live here were deleted rather than left dormant — they
   shared class names with the migrated markup and silently overrode it. */

/* ── Team ─────────────────────────────────────────────────── */
.role-badge {
  display: inline-flex;
  align-items: center;
  padding: 0.15rem 0.6rem;
  border-radius: 4px;
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.role-badge--owner   { background: var(--s-prep-bg);    color: oklch(42% 0.10 78); }
.role-badge--waiter  { background: var(--s-new-bg);     color: var(--s-new); }
.role-badge--kitchen { background: var(--s-ready-bg);   color: var(--s-ready); }

/* ── Misc utilities ───────────────────────────────────────── */
.form-hint {
  font-size: var(--text-sm);
  color: var(--ink-secondary);
  margin-top: 0.3rem;
}

.divider {
  border: none;
  border-top: 1px solid var(--border);
  margin: 2rem 0;
}

.feedback-inline {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: var(--text-sm);
  font-weight: 600;
  padding: 0.35rem 0.75rem;
  border-radius: var(--radius-md);
}
.feedback-inline--success { background: var(--s-ready-bg); color: var(--s-ready); }
.feedback-inline--error   { background: var(--s-danger-bg); color: var(--s-danger); }

/* ── Tip Banner ───────────────────────────────────────────── */
.tip-banner {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 0.75rem 1rem;
  background: var(--s-new-bg);
  border: 1px solid oklch(88% 0.025 242);
  border-radius: var(--radius-md);
  margin-bottom: 1.5rem;
  font-size: var(--text-sm);
  color: oklch(32% 0.07 242);
}
.tip-banner__icon    { flex-shrink: 0; color: var(--s-new); margin-top: 0.1rem; }
.tip-banner__text    { flex: 1; line-height: 1.5; }
.tip-banner__dismiss {
  background: none;
  border: none;
  cursor: pointer;
  color: oklch(48% 0.06 242);
  font-size: 1rem;
  padding: 0;
  line-height: 1;
  flex-shrink: 0;
  border-radius: var(--radius-sm);
  transition: color var(--dur-fast) var(--ease);
}
.tip-banner__dismiss:hover { color: oklch(32% 0.07 242); }

/* ── Empty States ─────────────────────────────────────────── */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 3.5rem 2rem;
  text-align: center;
  gap: 0.5rem;
}
.empty-state--panel { padding: 4rem 2rem; min-height: 280px; }
.empty-state__icon {
  font-size: 2rem;
  color: var(--ink-tertiary);
  opacity: 0.45;
  margin-bottom: 0.35rem;
}
.empty-state__title {
  font-family: var(--pt-font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--ink);
  margin: 0;
  letter-spacing: -0.02em;
}
.empty-state__subtitle {
  font-size: var(--text-sm);
  color: var(--ink-secondary);
  margin: 0;
  max-width: 300px;
  line-height: 1.5;
}

/* ── Print ────────────────────────────────────────────────── */
@media print {
  .page__sidebar, .topbar, .page-header .btn, .toast-host { display: none !important; }
  main { margin-left: 0 !important; }

  /* Page-level, not component-scoped: it sets the physical paper margin, not the state of any
     one element, so it belongs here rather than in a Blazor-scoped .razor.css file (QrCodes'
     print sheet, Task 2, relies on this). */
  @page { margin: 12mm; }
}

/* ── Shell chrome on a dark screen ────────────────────────────────────────────────────────
   The top bar and the notification centre are siblings of the page content, not children of
   it, so a screen cannot restyle them from its own scoped stylesheet — and a scoped rule
   would out-specify a global one here anyway, because the isolation bundle loads after this
   file. Custom properties are the seam that works in both directions: this rule re-declares
   the chrome tokens on the branch that holds a dark board, and the chrome's own scoped rules
   pick them up by inheritance.

   :has() rather than a route check in MainLayout: the condition is "this screen paints its
   own surface", which is exactly what the presence of .kds says. A second dark screen opts in
   by adding its root class to the selector, with no C# involved.

   Values are Capy Cocina.dc.html's own — #10241A for the header band, #16281D for a card,
   rgba(185,199,182,·) for its hairlines — so the bar reads as the board's own top edge
   instead of a white strip pasted over it. They are literals rather than var(--kds-*): those
   are declared on .kds itself, which is a descendant here and therefore out of reach. */
.page__main:has(.kds) {
  --pt-chrome-bar: #10241A;
  --pt-chrome-surface: #16281D;
  --pt-chrome-inset: #10241A;
  --pt-chrome-line: rgba(185,199,182,.18);
  --pt-chrome-divider: rgba(185,199,182,.12);
  --pt-chrome-hairline: rgba(185,199,182,.10);
  --pt-chrome-hover: rgba(232,239,230,.06);
  --pt-chrome-inset-hover: rgba(232,239,230,.07);
  --pt-chrome-title: #F3F7F1;
  --pt-chrome-strong: #E8EFE6;
  --pt-chrome-text: #8FA893;
  --pt-chrome-faint: #6E8570;
  --pt-chrome-icon: #A9BBA6;
  --pt-chrome-accent: #2A5638;
  --pt-chrome-accent-fg: #FDFAF2;
  --pt-chrome-shadow: 0 18px 40px rgba(4,12,8,.5);
  --pt-chrome-link: #C6DCB0;
  --pt-chrome-dot: #7ED08F;
  --pt-chrome-unread: rgba(62,122,75,.16);
  --pt-chrome-danger: #FFD9CF;
  --pt-chrome-danger-tint: rgba(168,68,47,.24);
  --pt-chrome-warn: #F0D08A;
  --pt-chrome-warn-tint: rgba(201,154,60,.20);
  --pt-chrome-info: #B9D7EA;
  --pt-chrome-info-tint: rgba(59,110,143,.26);
}

/* Shared entrance for popovers and panels: the prototype's `capy-rise`. Declared globally
   because scoped .razor.css cannot share a keyframe, and three components need this one. */
@keyframes capy-rise {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  @keyframes capy-rise {
    from { opacity: 1; transform: none; }
    to { opacity: 1; transform: none; }
  }
}

.window-row {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 0.9fr auto;
  gap: 0.5rem;
  align-items: center;
  margin-bottom: 0.5rem;
  max-width: 620px;
}

/* ── Cambio de idioma del panel: el rail ──────────────────────────────────────────────────────
   Changing the panel language re-renders the whole application, the nav rail included: every link
   label, every group heading and the user's role are localized and all of them change. The screen
   being translated paints its own skeleton (Settings.razor.css); this is the rail's half.

   It lives in app.css rather than NavMenu.razor.css because the hook is `.lang-swapping`, a class
   Settings puts on its own roots — NavMenu is its sibling under MainLayout, not its descendant, so
   the rail cannot be reached by cascade and Settings cannot reach up to the layout without a state
   object plumbed through it for the sake of 600ms. `:has()` is that reach, and it is already the
   codebase's way of doing this (capy-forms.css's .capy-radio-card:has(input:checked)). Anchored on
   .page so the match is scoped to the layout root instead of the whole document.

   @keyframes are global whatever file declares them, and two stylesheets now name this one, so it
   is declared here — the global sheet — rather than inside a scoped component file.

   This used to be gated on (min-width: 821px), because below that NavMenu.razor.css clipped these
   same labels to 1px for the icon rail and shimmering a clipped element is wasted work. That rail
   is gone — phone and tablet now get the drawer, where the labels are real text — so the gate went
   with it and the shimmer applies wherever the labels are. */
@keyframes capy-shimmer {
  from { background-position: 200% 0; }
  to { background-position: -200% 0; }
}

.page:has(.lang-swapping) .nav__label,
.page:has(.lang-swapping) .nav__group,
.page:has(.lang-swapping) .nav__user-role {
  width: fit-content;
  border-radius: 6px;
  color: transparent;
  background-image: var(--pt-shimmer-inverse);
  background-size: 200% 100%;
  background-repeat: no-repeat;
  animation: var(--pt-shimmer-animation);
}

/* Deliberately untouched: .nav__brand-rest (the restaurant's name), .nav__user-name (the person's)
   and .nav__badge (live counts). None of them translate, so showing them as loading would be a lie
   about what is happening — the same rule the screen's own skeleton keeps. */

/* ── Skeletons wait before appearing ───────────────────────────────────────────────────────────
   Most screens finish loading in well under a quarter second, and a skeleton that paints for a
   few frames and is immediately replaced reads as flicker, not progress. Each screen's loading
   container stays transparent for its first 150ms and only then shows, so a fast load goes
   straight from the previous screen to content and a slow one still gets its skeleton, fading in
   so one that is replaced a few frames after appearing never pops. Only the
   containers are delayed; their bars keep their own shimmer. capy-tokens.css drops every
   animation under prefers-reduced-motion, which simply shows the skeleton at once, as before. */
@keyframes skeleton-reveal {
  from { opacity: 0; }
  to { opacity: 1; }
}

.orders-skeleton,
.waiter-skeleton,
.tables-skeleton,
.zones-skeleton,
.reports-skeleton,
.qr-detail__skeleton,
.reservations-loading {
  animation: skeleton-reveal 200ms var(--pt-ease-enter) 150ms both;
}

/* Drag reorder (primeTableSortable): the placeholder where the row will land, and the row while
   it is held. Shared by Menú (dishes, sections) and Mesas (edit cards). */
.sortable-ghost { opacity: .45; background: var(--pt-row-hover); }
.sortable-chosen { box-shadow: var(--pt-shadow-card); }
.sortable-drag { cursor: grabbing; }
[data-sortable-id] { cursor: grab; }
[data-sortable-id] :is(input, textarea, select, button, a) { cursor: auto; }
