/* ============================================================
 * Touch-friendly defaults (Apple HIG 44pt, Material 48dp targets)
 * ============================================================ */

/* Bump base font slightly so rem-sized things scale across the app */
html {
  font-size: 17px;
  -webkit-text-size-adjust: 100%;
}

/* No flash on tap — we have our own ripple */
* {
  -webkit-tap-highlight-color: transparent;
}

/* Smooth momentum scrolling on iOS Safari for any scroll container */
html, body, .scrollbar-thin, [class*="overflow-"] {
  -webkit-overflow-scrolling: touch;
}

/* Don't double-tap-to-zoom on interactive elements */
button, a, label, input[type="button"], input[type="submit"], [role="button"] {
  touch-action: manipulation;
}

/* Prevent iOS Safari from auto-zooming when focusing form fields. iOS only
 * triggers the zoom when the input's font-size is below 16px. Keep inputs
 * comfortably above that. */
input, textarea, select {
  font-size: 16px;
}

/* Minimum tap-target utility — apply to anything that needs guaranteed 44px */
.tap-target { min-width: 44px; min-height: 44px; }

/* Material Symbols default sizing */
.material-symbols-rounded {
  font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 24;
  user-select: none;
  vertical-align: middle;
  line-height: 1;
}

/* An icon inside a button is decoration — the button owns the click. Making
 * it transparent to pointers means mousedown and mouseup always resolve to
 * the button itself, so a glyph that changes mid-press (play/pause, mute)
 * can't cost you the click. Safari drops a click when the node under the
 * cursor is swapped between press and release; Chromium doesn't, which is
 * why this only showed up in Safari. */
button > .material-symbols-rounded { pointer-events: none; }

/* Material elevation utility — works alongside Tailwind shadows */
.elev-1 { box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); }
.elev-2 { box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); }
.elev-3 { box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); }
.elev-4 { box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); }

/* Material-style ripple via animation on tap */
.btn-material {
  position: relative;
  overflow: hidden;
  transition: background-color 150ms ease, box-shadow 150ms ease, transform 60ms ease;
}
.btn-material:active {
  transform: scale(0.98);
}
.btn-material::after {
  content: '';
  position: absolute;
  inset: 0;
  background: currentColor;
  opacity: 0;
  transition: opacity 200ms ease;
  pointer-events: none;
}
.btn-material:hover::after {
  opacity: 0.05;
}
.btn-material:active::after {
  opacity: 0.12;
}

/* Hide scrollbars but keep scrolling */
.scrollbar-thin {
  scrollbar-width: thin;
  scrollbar-color: rgb(148 163 184) transparent;
}
.scrollbar-thin::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
.scrollbar-thin::-webkit-scrollbar-track {
  background: transparent;
}
.scrollbar-thin::-webkit-scrollbar-thumb {
  background-color: rgb(148 163 184);
  border-radius: 3px;
}

/* Slide-up modal animation */
@keyframes slide-up {
  from { transform: translateY(100%); opacity: 0; }
  to   { transform: translateY(0); opacity: 1; }
}
.anim-slide-up {
  animation: slide-up 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

@keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
.anim-fade-in {
  animation: fade-in 180ms ease-out;
}

/* Toast */
.toast {
  pointer-events: auto;
  animation: slide-up 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* Hierarchical step row indents */
.step-depth-0 { padding-left: 14px; }
.step-depth-1 { padding-left: 32px; }
.step-depth-2 { padding-left: 50px; }
.step-depth-3 { padding-left: 68px; }

/* Video player styles */
.video-shell {
  background: #000;
}
.video-shell video {
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #000;
}

/* Range input styling for seek bar */
input[type="range"].seek {
  -webkit-appearance: none;
  appearance: none;
  height: 6px;
  /* Explicit frosted "groove" so the full draggable track is always visible,
     in keeping with the frosted-glass control surfaces. The inset shadow +
     hairline give it channel depth; the thumb rides along it. */
  background: rgba(255, 255, 255, 0.13);
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 3px;
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.35);
  outline: none;
}
input[type="range"].seek::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}
input[type="range"].seek::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  cursor: pointer;
  border: none;
}

/* ============================================================
 * Dark-theme overrides
 * ----------------------------------------------------------------
 * The whole app is built with light Tailwind utility classes
 * (bg-white, bg-slate-50, text-slate-900, etc). Rather than rewrite
 * every view, we force `class="dark"` on <html> in index.html and
 * remap each light class to its dark equivalent here.
 *
 * Specificity: `html.dark .x` (0,2,1) beats plain `.x` (0,1,0), so
 * these rules win over the Tailwind utilities without !important.
 * Form elements use !important since the browser UA stylesheet can
 * be aggressive on iOS / Android.
 * ============================================================ */

/* Pin the light scheme when .dark is absent. Without this, the meta's
 * "light dark" lets NATIVE form controls (textarea, input, select) follow
 * the OS preference — a dark-OS user in light app mode got dark textareas
 * with unreadable input text (seen in the issue-report sheet). The CSS
 * color-scheme property overrides the meta. */
html { color-scheme: light; }
html.dark { color-scheme: dark; background-color: #0f172a; }
html.dark body { background-color: #0f172a; color: #f1f5f9; }

/* ---- Role-accent text that must stay readable in light mode ----
 * Coordinated member pills write each role's accent color inline via the
 * --role-accent custom property. Bright accents (teal / amber) work on the
 * dark theme but wash out on light backgrounds — light mode overrides the
 * text to near-black while the avatar chip keeps carrying the role color. */
.role-pill-text { color: var(--role-accent, #2dd4bf); }
html:not(.dark) .role-pill-text { color: #0f172a; }

/* ---- Task progress rings (Assigned Tasks) ----
 * Teal ring + teal % on the amber overdue cards is unreadable in light
 * mode; recolor to near-black there (dark keeps the teal accent). */
.task-ring { border-color: #2dd4bf; color: #2dd4bf; }
html:not(.dark) .task-ring { border-color: #0f172a; color: #0f172a; }

/* ---- Task panel status borders (light mode) ----
 * Faint border color coding so a panel's status reads at a glance:
 * pale blue = regular, forest green = completed. The other statuses
 * already carry their own coding in both themes — amber outline
 * (overdue, inline), lime ring (for review), red ring (halted),
 * mint/emerald ring (reviewed). Same inside-outline technique as the
 * overdue treatment; inline outlines (unread orange, overdue amber)
 * override these since inline style wins. Light-only — the dark theme
 * codes status through panel backgrounds instead. */
html:not(.dark) .task-status-regular   { outline: 1.5px solid #bfdbfe; outline-offset: -1.5px; }
html:not(.dark) .task-status-completed { outline: 1.5px solid #15803d; outline-offset: -1.5px; }

/* ============================================================
 * Login screen — split blueprint canvas (mockup port)
 * The canvas half is a FIXED dark surface in both themes (like the
 * mockup's login), so everything here uses concrete colors rather
 * than remappable Tailwind utilities. The form half stays theme-aware
 * through the normal utility classes.
 * ============================================================ */
.login-mono { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; }
.login-canvas {
  background-color: #0b1220;
  background-image:
    linear-gradient(rgba(59,130,246,.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(59,130,246,.05) 1px, transparent 1px),
    linear-gradient(rgba(59,130,246,.025) 1px, transparent 1px),
    linear-gradient(90deg, rgba(59,130,246,.025) 1px, transparent 1px);
  background-size: 180px 180px, 180px 180px, 36px 36px, 36px 36px;
  border-right: 1px solid #1a2438;
}
/* Miniature run-interface card (cascade node) */
.login-mini {
  position: absolute; width: 150px; background: #0d1626;
  border: 1px solid #2a3752; border-radius: 3px; overflow: hidden;
  box-shadow: 0 16px 34px rgba(0, 0, 0, .55);
}
.login-mini .mh {
  display: flex; gap: 6px; align-items: center; padding: 4px 8px;
  background: #121d33; border-bottom: 1px solid #223049;
  font: 600 8px ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  letter-spacing: .1em; color: #8fa4c4; white-space: nowrap;
}
.login-mini .mh .dot { width: 5px; height: 5px; border-radius: 50%; background: #22c55e; flex-shrink: 0; }
.login-mini .mv { height: 60px; background-size: 230%; background-repeat: no-repeat; }
.login-mini .mf {
  display: flex; justify-content: space-between; align-items: center; padding: 3.5px 8px;
  background: #16213a;
  font: 600 7.5px ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  letter-spacing: .08em; color: #64748b; white-space: nowrap;
}
.login-mini.na { opacity: .5; filter: saturate(.35); }
.login-mini.dvg { border-color: #3b82f6; }
.login-pathlab {
  position: absolute;
  font: 600 8.5px ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  letter-spacing: .16em;
}
.login-frame-hero  { background-image: url(/assets/login-frame-hero.jpg); }
.login-frame-guide { background-image: url(/assets/login-frame-guide.jpg); }

/* ============================================================
 * Login canvas animation (see js/views/login-canvas.js)
 * Tuned in /login-lab.html — keep the two in sync if retuning.
 *
 * Theming lives entirely here so toggling the theme costs no JS:
 * light mode flips the node labels to pale panels and the comp's blend
 * mode to overlay. The GRID is deliberately not recoloured — its crosses
 * are a raster PNG inside the SVG, so there is no fill to change.
 * ============================================================ */
.login-canvas { --lc-blend: normal; --lc-edge: 27%; --lc-blur: 11px; }
html:not(.dark) .login-canvas { --lc-blend: overlay; }

/* ---- EPSILON wordmark ----
 * Baloo Bhai 2 (rounded), subset to A-Z/a-z/0-9 + a little punctuation:
 * 577KB variable TTF -> 9.9KB woff2, weight axis 400-800 preserved.
 * font-display:swap so the brand text paints immediately in a fallback
 * rather than leaving a hole in the top bar while the font loads. */
@font-face {
  font-family: 'Epsilon Wordmark';
  src: url('/assets/fonts/epsilon-wordmark.woff2') format('woff2-variations'),
       url('/assets/fonts/epsilon-wordmark.woff2') format('woff2');
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
}
.epsilon-wordmark {
  font-family: 'Epsilon Wordmark', ui-rounded, system-ui, sans-serif;
  font-weight: 700;
  letter-spacing: .1em;
  line-height: 1;
  text-transform: uppercase;
  white-space: nowrap;
  color: #fff;
}

/* Brand sub-line on the canvas ("SOP INFORMATION MANAGEMENT SYSTEM",
 * under the S·I·M·S wordmark). White in BOTH themes: the canvas sits on
 * footage in either mode, and the muted slate it used to be lost contrast
 * — against the brightened overlay blend in light mode especially. */
.login-brand-sub { color: #fff; }

/* Tagline, bottom-left of the canvas. Same reasoning as the brand line —
 * both sat on muted slate that vanished against the footage. The eyebrow
 * keeps a little transparency so it stays subordinate to the statement
 * beneath it rather than two equal blocks of white. */
.login-tagline-k { color: rgba(255, 255, 255, 0.72); }
.login-tagline-p { color: #fff; }

.login-backdrop { position: absolute; inset: 0; }
.login-backdrop video { width: 100%; height: 100%; object-fit: cover; display: block; }

/* The blend goes on the WRAPPER, not the two stacks: they composite
 * normally with each other first so the vignette crossfade stays exact,
 * then the finished comp blends onto the footage once. */
.login-gridcomp { position: absolute; inset: 0; mix-blend-mode: var(--lc-blend); }
.login-stack { position: absolute; inset: 0; }
.login-stack.sharp {
  -webkit-mask-image: radial-gradient(ellipse at center, #000 var(--lc-edge), transparent 100%);
          mask-image: radial-gradient(ellipse at center, #000 var(--lc-edge), transparent 100%);
}
.login-stack.blur {
  -webkit-mask-image: radial-gradient(ellipse at center, transparent var(--lc-edge), #000 100%);
          mask-image: radial-gradient(ellipse at center, transparent var(--lc-edge), #000 100%);
}
.login-stack.blur .login-gridlayer { filter: blur(var(--lc-blur)); }

.login-gridx { position: absolute; top: 0; bottom: 0; pointer-events: none; will-change: transform; }
.login-gridlayer {
  position: absolute; left: 0; width: 100%;
  background-image: url(/assets/login-grid-cross.svg);
  background-repeat: repeat;
  pointer-events: none;
  will-change: transform;
}
.login-gridlayer.front { opacity: 0.5; }
.login-gridlayer.back  { opacity: 0.4; }

/* ---- flow: wire + step nodes ---- */
.login-flow  { position: absolute; inset: 0; pointer-events: none; }
.login-world { position: absolute; left: 50%; top: 46%; will-change: transform; }
.login-wire  { position: absolute; left: 0; top: 0; width: 1px; height: 1px; overflow: visible; }
.login-wire path { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.login-wire .ghost { stroke: #24344f; stroke-width: 2; }
.login-wire .alt   { stroke: #24344f; stroke-width: 1.5; stroke-dasharray: 5 6; }
.login-wire .live  { stroke: #2dd4bf; stroke-width: 2.5; filter: drop-shadow(0 0 5px rgba(45,212,191,.55)); }

.login-node {
  position: absolute;
  transform: translate(-50%, -50%);
  display: flex; align-items: center; gap: 9px;
  padding: 7px 12px;
  background: #0d1626;
  border: 1px solid #2a3752;
  border-radius: 3px;
  font: 600 10.5px ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  letter-spacing: .1em;
  white-space: nowrap;
  box-shadow: 0 12px 30px rgba(0,0,0,.55);
}
.login-node .num { color: #5b7191; }
.login-node .lab { color: #cbd5e1; }
.login-node.done { border-color: rgba(45,212,191,.55); }
.login-node.done .num { color: #2dd4bf; }
.login-node.alt {
  opacity: .4; border-style: dashed;
  background: rgba(13,22,38,.75); box-shadow: none;
}
.login-node.alt .lab { color: #64748b; text-decoration: line-through; }

/* Light mode: pale label panels with dark text (the canvas itself stays
 * dark in both themes, so these read as lit cards on the footage). */
html:not(.dark) .login-node {
  background: #f8fafc;
  border-color: #cbd5e1;
  box-shadow: 0 12px 30px rgba(0,0,0,.45);
}
html:not(.dark) .login-node .num { color: #64748b; }
html:not(.dark) .login-node .lab { color: #0f172a; }
html:not(.dark) .login-node.done { border-color: #0d9488; }
html:not(.dark) .login-node.done .num { color: #0d9488; }
html:not(.dark) .login-node.alt { background: rgba(248,250,252,.8); }
html:not(.dark) .login-node.alt .lab { color: #64748b; }

/* ---- Assigned Tasks micro-calendar (mockup "SCHEDULE" panel) ----
 * Lanes + labeled chips. Chip palette follows the mockup's dark values;
 * light mode flips chip text to near-black for readability (per spec)
 * and softens the fills. The lane is darker than the panel in dark
 * mode (mockup) and a soft blue-grey in light. */
.callane { position: relative; flex: 1; border-radius: 2px; background: #e9eff7; }
html.dark .callane { background: #101b30; }
.calrow-today .callane { outline: 1px solid rgba(101, 163, 13, .45); }
html.dark .calrow-today .callane { outline: 1px solid rgba(163, 230, 53, .35); }
.calday-today { color: #65a30d; }
html.dark .calday-today { color: #a3e635; }
.calblk {
  position: absolute; top: 3px; bottom: 3px; border-radius: 2px;
  display: flex; align-items: center; padding: 0 6px;
  overflow: hidden; white-space: nowrap; cursor: default;
  font: 600 8.5px ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  letter-spacing: .04em;
}
.calblk.own  { background: rgba(37, 99, 235, .5);   border: 1px solid rgba(96, 165, 250, .6);  color: #dbeafe; }
.calblk.sub  { background: rgba(45, 212, 191, .14); border: 1px dashed rgba(45, 212, 191, .6); color: #8ff0e2; }
.calblk.done { background: rgba(148, 163, 184, .18); border: 1px solid rgba(148, 163, 184, .3); color: #a9b8cd; }
.calblk.late { background: rgba(220, 38, 38, .35);  border: 1px solid rgba(248, 113, 113, .6); color: #fecaca; }
/* In-flow chip variant for the dashboard's month grid — same look, but
 * stacked inside a day cell instead of positioned on a time lane. */
.calblk.flow { position: relative; top: auto; bottom: auto; height: 16px; width: 100%; flex-shrink: 0; cursor: pointer; text-align: left; }
/* Month-grid day cell (dashboard SCHEDULE). Same surface family as the
 * lanes; out-of-month cells recede, today gets the lime outline. */
.calcell { background: #e9eff7; border-radius: 2px; }
html.dark .calcell { background: #101b30; }
.calcell.out { background: rgba(148, 163, 184, 0.08); }
html.dark .calcell.out { background: rgba(15, 23, 42, 0.35); }
.calcell.today { outline: 1px solid rgba(101, 163, 13, .5); }
html.dark .calcell.today { outline: 1px solid rgba(163, 230, 53, .4); }
html:not(.dark) .calblk { color: #0f172a; }
html:not(.dark) .calblk.own  { background: rgba(37, 99, 235, .22); }
html:not(.dark) .calblk.sub  { background: rgba(13, 148, 136, .14); border-color: #0d9488; }
html:not(.dark) .calblk.done { background: rgba(100, 116, 139, .16); }
html:not(.dark) .calblk.late { background: rgba(220, 38, 38, .16); border-color: #dc2626; }

/* ---- "Run in flight" marker (supervisor's Scheduled-by-you rows) ----
 * Sits in the slot a normal user's progress ring occupies, just before the
 * chevron. Only rendered when the task's run is actually live, so the
 * motion always means something is happening right now. */
.run-live { color: #0d9488; }
html.dark .run-live { color: #2dd4bf; }
.run-live .material-symbols-rounded {
  display: block;
  animation: run-live-spin 1.8s linear infinite;
}
@keyframes run-live-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .run-live .material-symbols-rounded { animation: none; }
}

/* ---- Day pop-out (Assigned Tasks micro-calendar) --------------------
 * A day lane is 22px tall, so several tasks at nearby times overlap into
 * an unreadable smear. Clicking the day label opens this panel, which
 * relays the same tasks down an hour column where they have room.
 * The day label pulses when its chips actually collide (measured, see
 * markCrowdedDays) so the affordance shows up exactly where it's needed. */
.calday-crowded {
  cursor: pointer;
  border-radius: 3px;
  animation: calday-flash 2.1s ease-in-out infinite;
}
@keyframes calday-flash {
  0%, 100% { background: transparent; box-shadow: none; }
  50%      { background: rgba(56, 189, 248, .16); box-shadow: 0 0 0 2px rgba(56, 189, 248, .3); }
}
[data-cal-day] { cursor: pointer; }
[data-cal-day]:hover { background: rgba(56, 189, 248, .14); border-radius: 3px; }

.daypop {
  position: fixed; z-index: 60; width: 280px;
  display: flex; flex-direction: column;
  background: #ffffff; color: #0f172a;
  border: 1px solid #cbd5e1; border-radius: 10px;
  box-shadow: 0 12px 32px rgba(15, 23, 42, .22);
  animation: daypop-in .14s ease-out;
}
html.dark .daypop {
  background: #16233c; color: #e2e8f0;
  border-color: #2b3d5e; box-shadow: 0 12px 32px rgba(0, 0, 0, .5);
}
@keyframes daypop-in { from { opacity: 0; transform: translateX(-6px); } to { opacity: 1; transform: none; } }

.daypop-head {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 8px 8px 11px; border-bottom: 1px solid #e2e8f0;
}
html.dark .daypop-head { border-bottom-color: #2b3d5e; }
.daypop-title {
  font: 600 11px ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  letter-spacing: .08em; flex: 1;
}
.daypop-count { font-size: 10px; color: #64748b; }
html.dark .daypop-count { color: #94a3b8; }
.daypop-x {
  width: 24px; height: 24px; border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  color: #64748b; flex-shrink: 0;
}
.daypop-x:hover { background: rgba(100, 116, 139, .16); }
html.dark .daypop-x { color: #94a3b8; }

.daypop-anytime { padding: 7px 9px; border-bottom: 1px solid #e2e8f0; }
html.dark .daypop-anytime { border-bottom-color: #2b3d5e; }
.daypop-anytime-label {
  font: 600 8.5px ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  letter-spacing: .12em; color: #94a3b8; margin-bottom: 4px;
}

/* The scroll box is sized to ~6 hour rows; the arrows overlay its top and
 * bottom edges with a fade so partially-scrolled rows read as continuing
 * rather than being clipped. */
.daypop-scrollwrap { position: relative; }
.daypop-scroll { max-height: 240px; overflow-y: auto; overscroll-behavior: contain; }

.daypop-row { display: flex; align-items: stretch; gap: 8px; padding: 2px 9px; }
.daypop-row + .daypop-row { border-top: 1px dashed rgba(100, 116, 139, .18); }
html.dark .daypop-row + .daypop-row { border-top-color: rgba(148, 163, 184, .14); }
.daypop-row.has { background: rgba(56, 189, 248, .06); }
html.dark .daypop-row.has { background: rgba(56, 189, 248, .05); }
.daypop-hour {
  width: 20px; flex-shrink: 0; padding-top: 5px;
  font: 600 9.5px ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  color: #94a3b8; text-align: right; font-variant-numeric: tabular-nums;
}
.daypop-row.has .daypop-hour { color: #0f172a; }
html.dark .daypop-row.has .daypop-hour { color: #e2e8f0; }
.daypop-slot { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; justify-content: center; padding: 3px 0; }

/* Task cards reuse the lane chips' colour language (own / sub / done /
 * late) so a chip and its expanded row are recognisably the same thing —
 * but laid out to be read rather than to fit in 22px. */
.daypop-task {
  display: flex; gap: 7px; align-items: flex-start;
  padding: 4px 7px; border-radius: 4px;
  border: 1px solid transparent; min-width: 0;
}
.daypop-task.clickable { cursor: pointer; }
.daypop-task.clickable:hover { filter: brightness(1.06); }
.daypop-task.own  { background: rgba(37, 99, 235, .16); border-color: rgba(96, 165, 250, .5); }
.daypop-task.sub  { background: rgba(13, 148, 136, .12); border: 1px dashed rgba(45, 212, 191, .6); }
.daypop-task.done { background: rgba(100, 116, 139, .14); border-color: rgba(148, 163, 184, .35); }
.daypop-task.late { background: rgba(220, 38, 38, .14); border-color: rgba(248, 113, 113, .55); }
html.dark .daypop-task.own  { background: rgba(37, 99, 235, .32); }
html.dark .daypop-task.done { background: rgba(148, 163, 184, .16); }
html.dark .daypop-task.late { background: rgba(220, 38, 38, .3); }
.daypop-time {
  font: 600 9.5px ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-variant-numeric: tabular-nums; padding-top: 1px; flex-shrink: 0; opacity: .85;
}
.daypop-task-body { min-width: 0; flex: 1; }
.daypop-task-label { font-size: 11px; font-weight: 500; line-height: 1.3; overflow-wrap: anywhere; }
.daypop-task-sub { font-size: 9.5px; line-height: 1.3; opacity: .75; margin-top: 1px; overflow-wrap: anywhere; }

.daypop-arrow {
  position: absolute; left: 0; right: 0; height: 22px; z-index: 2;
  display: flex; align-items: center; justify-content: center;
  color: #38bdf8; pointer-events: none;
  animation: daypop-bob 1.5s ease-in-out infinite;
}
.daypop-arrow.hidden { display: none; }
.daypop-arrow.up   { top: 0;    background: linear-gradient(to bottom, #ffffff 30%, rgba(255,255,255,0)); }
.daypop-arrow.down { bottom: 0; background: linear-gradient(to top,    #ffffff 30%, rgba(255,255,255,0)); }
html.dark .daypop-arrow.up   { background: linear-gradient(to bottom, #16233c 30%, rgba(22,35,60,0)); }
html.dark .daypop-arrow.down { background: linear-gradient(to top,    #16233c 30%, rgba(22,35,60,0)); }
@keyframes daypop-bob {
  0%, 100% { opacity: .35; }
  50%      { opacity: 1; }
}
.daypop-arrow.up   { animation-name: daypop-bob-up; }
.daypop-arrow.down { animation-name: daypop-bob-down; }
@keyframes daypop-bob-up {
  0%, 100% { opacity: .35; transform: translateY(1px); }
  50%      { opacity: 1;   transform: translateY(-1px); }
}
@keyframes daypop-bob-down {
  0%, 100% { opacity: .35; transform: translateY(-1px); }
  50%      { opacity: 1;   transform: translateY(1px); }
}

@media (prefers-reduced-motion: reduce) {
  .calday-crowded,
  .daypop,
  .daypop-arrow { animation: none; }
  .calday-crowded { background: rgba(56, 189, 248, .16); box-shadow: 0 0 0 2px rgba(56, 189, 248, .3); }
  .daypop-arrow { opacity: .9; }
}

/* ---- Current-step highlight (run player sidebars, light mode) ----
 * The mockup's current-step marker is a deep, very cool (nearly blue)
 * grey — bg-blue-50 was too faint in light mode. The row text is
 * authored in dark slate utilities, so flip it light for contrast.
 * Dark mode is untouched (bg-blue-50 remaps to its navy tint there).
 * Applies to every player variant: solo/training/group rows come from
 * step-row.js, coordinated rows from coordinated-execution-view. */
html:not(.dark) .step-current { background-color: #4a5670; }
html:not(.dark) .step-current .text-slate-900,
html:not(.dark) .step-current .text-slate-700 { color: #f8fafc; }
html:not(.dark) .step-current .text-slate-500,
html:not(.dark) .step-current .text-slate-400 { color: #cbd5e1; }
html:not(.dark) .step-current:hover { background-color: #4a5670; }

/* ---- Surface backgrounds ---- */
html.dark .bg-slate-50  { background-color: #0f172a; }   /* page bg → slate-900 */
html.dark .bg-slate-100 { background-color: #334155; }   /* hovers / chips → slate-700 */
html.dark .bg-slate-200 { background-color: #475569; }   /* slate-600 */
html.dark .bg-white     { background-color: #1e293b; }   /* cards, modals, headers → slate-800 */

/* The login screen's page gradient — replace pastel with subtle dark */
html.dark .from-slate-50 { --tw-gradient-from: #0f172a var(--tw-gradient-from-position); --tw-gradient-to: rgb(15 23 42 / 0); --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); }
html.dark .to-blue-50    { --tw-gradient-to: #1e3a8a var(--tw-gradient-to-position); }   /* blue-900 */

/* ---- Borders ---- */
html.dark .border-slate-100 { border-color: #334155; }
html.dark .border-slate-200 { border-color: #334155; }
html.dark .border-slate-300 { border-color: #475569; }
html.dark .divide-slate-200 > :not([hidden]) ~ :not([hidden]) { border-color: #334155; }

/* ---- Text ---- */
html.dark .text-slate-900 { color: #f1f5f9; }
html.dark .text-slate-800 { color: #e2e8f0; }
html.dark .text-slate-700 { color: #cbd5e1; }
html.dark .text-slate-600 { color: #94a3b8; }
html.dark .text-slate-500 { color: #94a3b8; }
html.dark .text-slate-400 { color: #64748b; }
html.dark .text-slate-300 { color: #475569; }

/* ---- Hover states ---- */
html.dark .hover\:bg-slate-50:hover  { background-color: #334155; }
html.dark .hover\:bg-slate-100:hover { background-color: #334155; }
html.dark .hover\:bg-blue-50:hover   { background-color: rgba(37, 99, 235, 0.18); }
html.dark .hover\:bg-red-50:hover    { background-color: rgba(220, 38, 38, 0.18); }
html.dark .hover\:bg-orange-50:hover { background-color: rgba(249, 115, 22, 0.18); }
html.dark .hover\:elev-3:hover { box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.6), 0 2px 4px -2px rgb(0 0 0 / 0.5); }

/* ---- Pastel chip backgrounds — toned-down translucent versions ---- */
html.dark .bg-blue-50    { background-color: rgba(37, 99, 235, 0.18); }
html.dark .bg-blue-100   { background-color: rgba(37, 99, 235, 0.25); }
html.dark .bg-green-100  { background-color: rgba(22, 163, 74, 0.22); }
html.dark .bg-amber-100  { background-color: rgba(245, 158, 11, 0.22); }
html.dark .bg-orange-100 { background-color: rgba(249, 115, 22, 0.22); }
html.dark .bg-purple-100 { background-color: rgba(168, 85, 247, 0.22); }
html.dark .bg-teal-100   { background-color: rgba(20, 184, 166, 0.22); }
html.dark .bg-red-100    { background-color: rgba(220, 38, 38, 0.22); }
html.dark .bg-red-50     { background-color: rgba(220, 38, 38, 0.18); }
html.dark .bg-amber-50   { background-color: rgba(245, 158, 11, 0.15); }
html.dark .bg-orange-50  { background-color: rgba(249, 115, 22, 0.15); }

/* ---- Pastel chip text — bumped up in lightness for legibility on dark ---- */
html.dark .text-blue-700   { color: #93c5fd; }
html.dark .text-blue-800   { color: #93c5fd; }
html.dark .text-green-700  { color: #86efac; }
html.dark .text-green-600  { color: #4ade80; }
html.dark .text-amber-700  { color: #fcd34d; }
html.dark .text-amber-600  { color: #fbbf24; }
html.dark .text-orange-700 { color: #fdba74; }
html.dark .text-orange-600 { color: #fb923c; }
html.dark .text-orange-800 { color: #fdba74; }
html.dark .text-purple-800 { color: #d8b4fe; }
html.dark .text-teal-800   { color: #5eead4; }
html.dark .text-red-700    { color: #fca5a5; }
html.dark .text-red-600    { color: #f87171; }
html.dark .text-red-500    { color: #f87171; }

/* Role-badge borders (the tinted outlines around the chip text) */
html.dark .border-teal-300   { border-color: rgba(20, 184, 166, 0.5); }
html.dark .border-orange-300 { border-color: rgba(249, 115, 22, 0.5); }
html.dark .border-purple-300 { border-color: rgba(168, 85, 247, 0.5); }
html.dark .border-amber-300  { border-color: rgba(245, 158, 11, 0.5); }
html.dark .border-blue-300   { border-color: rgba(37, 99, 235, 0.5); }
html.dark .border-orange-500 { border-color: #f97316; }   /* keep — used as a strong accent */

/* ---- Additions surfaced by scripts/check-dark-colors.mjs ----
   Dark equivalents for every remaining color class the views use.
   When a NEW color class is needed, add its remap here (the checker
   fails the build until you do, or until the line is marked dark-ok). */
html.dark .bg-teal-50     { background-color: rgba(20, 184, 166, 0.12); }
html.dark .bg-emerald-50  { background-color: rgba(16, 185, 129, 0.12); }
html.dark .bg-emerald-100 { background-color: rgba(16, 185, 129, 0.22); }
html.dark .bg-lime-50     { background-color: rgba(132, 204, 22, 0.12); }
html.dark .bg-lime-100    { background-color: rgba(132, 204, 22, 0.22); }
html.dark .text-lime-700  { color: #bef264; }
html.dark .text-blue-600    { color: #60a5fa; }
html.dark .text-teal-600    { color: #2dd4bf; }
html.dark .text-emerald-600 { color: #34d399; }
html.dark .text-emerald-700 { color: #6ee7b7; }
html.dark .text-emerald-800 { color: #6ee7b7; }
html.dark .text-lime-600    { color: #a3e635; }
html.dark .text-amber-800   { color: #fcd34d; }
html.dark .text-red-800     { color: #fca5a5; }
html.dark .text-red-900     { color: #fecaca; }
html.dark .border-red-100   { border-color: rgba(220, 38, 38, 0.25); }
html.dark .border-red-300   { border-color: rgba(220, 38, 38, 0.5); }
html.dark .border-amber-200 { border-color: rgba(245, 158, 11, 0.35); }
html.dark .border-teal-200  { border-color: rgba(20, 184, 166, 0.35); }
html.dark .divide-slate-50  > :not([hidden]) ~ :not([hidden]) { border-color: #334155; }
html.dark .divide-slate-100 > :not([hidden]) ~ :not([hidden]) { border-color: #334155; }
/* Interaction variants (base classes are remapped above / earlier) */
html.dark .hover\:text-slate-700:hover  { color: #cbd5e1; }
html.dark .hover\:text-red-600:hover    { color: #f87171; }
html.dark .hover\:bg-green-50:hover     { background-color: rgba(22, 163, 74, 0.15); }
html.dark .hover\:border-amber-300:hover { border-color: rgba(245, 158, 11, 0.5); }
html.dark .hover\:border-red-300:hover  { border-color: rgba(220, 38, 38, 0.5); }
html.dark .active\:bg-slate-100:active  { background-color: #334155; }

/* ---- Form elements ---- */
html.dark input,
html.dark textarea,
html.dark select {
  background-color: #1e293b !important;
  color: #f1f5f9 !important;
  border-color: #475569 !important;
}
html.dark input::placeholder,
html.dark textarea::placeholder { color: #64748b !important; }
html.dark input[type="file"] { color: #cbd5e1 !important; }
html.dark input[type="range"] { background: transparent !important; }

/* Focus rings stay blue — already legible on dark */

/* ---- Custom scrollbar (Firefox + WebKit) ---- */
html.dark .scrollbar-thin { scrollbar-color: #475569 transparent; }
html.dark .scrollbar-thin::-webkit-scrollbar-thumb { background-color: #475569; }
html.dark .scrollbar-thin::-webkit-scrollbar-thumb:hover { background-color: #64748b; }

/* ---- Material elevation shadows are darker on dark surfaces ---- */
html.dark .elev-1 { box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.5); }
html.dark .elev-2 { box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.55), 0 1px 2px -1px rgb(0 0 0 / 0.45); }
html.dark .elev-3 { box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.6), 0 2px 4px -2px rgb(0 0 0 / 0.5); }
html.dark .elev-4 { box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.65), 0 4px 6px -4px rgb(0 0 0 / 0.5); }

/* ---- Sidebar selected-row left bar ---- */
html.dark .border-blue-600 { border-color: #3b82f6; }   /* keep — accent stays the same */

/* ---- Modal backdrop is already black/40-60 — keep ---- */

/* ============================================================
 * SIMS brand top bar — Epsilon-style full-width bar, anchored on the
 * SIMS blue #0092FF. Deliberately theme-INDEPENDENT: the same frosted
 * blue in both light and dark (like the reference). Contents are forced
 * light so they read on the blue regardless of theme.
 * ============================================================ */
.sims-topbar {
  background: linear-gradient(180deg,
    rgba(24,160,255,0.96) 0%, rgba(0,146,255,0.96) 45%, rgba(0,124,226,0.96) 100%);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(255,255,255,0.25);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.3), 0 6px 20px rgba(0,116,214,0.30);
  color: #ffffff;
  position: relative;
  z-index: 5;
}
/* Toggle + any icon button living on the blue bar */
.sims-topbar-btn { color: #eaf6ff; transition: background-color 150ms ease, color 150ms ease; }
.sims-topbar-btn:hover { background: rgba(255,255,255,0.18); color: #ffffff; }
.sims-clock {
  font-variant-numeric: tabular-nums;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

/* ------------------------------------------------------------------
 * Vendor chrome. Epsilon's own accounts get a graphite bar instead of
 * the SIMS blue, so it is never ambiguous whether you are looking at
 * the product as a client sees it or at the tool that manages clients.
 * Same frosted treatment, different material — deliberately not a
 * different design language, just a different surface.
 * ------------------------------------------------------------------ */
.sims-topbar.is-vendor {
  background: linear-gradient(180deg,
    rgba(58,64,74,0.92) 0%, rgba(42,47,56,0.94) 45%, rgba(31,35,42,0.96) 100%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  backdrop-filter: blur(18px) saturate(140%);
  border-bottom: 1px solid rgba(255,255,255,0.14);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.14), 0 6px 22px rgba(0,0,0,0.32);
}
/* The console label sits where a client's company name would. */
.vendor-console-label {
  color: rgba(255,255,255,0.92);
  letter-spacing: 0.16em;
}
.vendor-console-label .vendor-dot {
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 999px;
  background: #fbbf24;
  margin-right: 8px;
  vertical-align: middle;
  box-shadow: 0 0 0 3px rgba(251,191,36,0.18);
}

/* Organisation switcher in the dock. */
.org-switcher {
  background: rgba(100,116,139,0.10);
  border: 1px solid rgba(100,116,139,0.22);
}
.org-switcher:hover { background: rgba(100,116,139,0.18); }
html.dark .org-switcher {
  background: rgba(148,163,184,0.12);
  border-color: rgba(148,163,184,0.24);
}
html.dark .org-switcher:hover { background: rgba(148,163,184,0.20); }

.org-popout {
  position: absolute;
  z-index: 60;
  width: 19rem;
  max-height: 24rem;
  display: flex;
  flex-direction: column;
  background: #ffffff;
  border: 1px solid rgb(203,213,225);
  border-radius: 12px;
  box-shadow: 0 18px 48px rgba(15,23,42,0.22);
  overflow: hidden;
}
html.dark .org-popout {
  background: #1b2230;
  border-color: rgba(148,163,184,0.26);
  box-shadow: 0 18px 48px rgba(0,0,0,0.55);
}


/* ============================================================
 * SIMS sharp restyle (Phase 3) — applied as ONE global layer so the
 * ~350 rounded-* sites need no hand-editing and the whole look is
 * reversible by deleting this block.
 * ============================================================ */

/* Tighten corners on panels / cards / buttons. rounded-full is left
   alone ON PURPOSE — avatars, status dots, %-rings, pills/chips, and the
   coordinated return chip stay circular. !important so we win regardless
   of the Tailwind Play CDN's runtime injection order. */
.rounded-2xl { border-radius: 5px !important; }
.rounded-xl  { border-radius: 4px !important; }
.rounded-lg  { border-radius: 3px !important; }
.rounded-md  { border-radius: 3px !important; }
.rounded-sm  { border-radius: 2px !important; }

/* Technical mono micro-labels — the app already writes section labels,
   stat labels, metadata labels, and chips as uppercase + tracked; a
   monospace face gives them the control-room feel. Selector specificity
   (0,2,0) beats the Tailwind font utilities. Run codes are unaffected —
   they're already font-mono. */
.uppercase.tracking-wide {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

/* Theme-aware logo swap: light-ground variant by default, dark-ground
   variant under html.dark. Render both; CSS shows the right one live so it
   follows the theme toggle without a re-render. */
.logo-theme-light { display: block; }
.logo-theme-dark  { display: none; }
html.dark .logo-theme-light { display: none; }
html.dark .logo-theme-dark  { display: block; }

/* Loading spinner */
.spinner {
  width: 20px;
  height: 20px;
  border: 2px solid currentColor;
  border-bottom-color: transparent;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
@keyframes spin {
  to { transform: rotate(360deg); }
}

/* Avatar circle */
.avatar {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 500;
  font-size: 22px;
  color: white;
}
