/* Opterra PH CRM — design tokens matched to the client's Monday.com
   workspace screenshots, with the accent color tied to Opterra's own brand
   orange (client request 2026-08-20) instead of Monday's default blue. The
   dark sidebar stays a neutral structural color, same reasoning as the
   marketing site's navy/orange split — it's the accent that carries brand
   identity, not the structural chrome. */
:root {
  --sidebar-bg: #292f4c;
  --sidebar-bg-hover: #383a62;
  --sidebar-text: #c5c7d0;
  --sidebar-text-dim: #9699a6;
  --sidebar-active: #4a4f7a;
  --sidebar-border: #383a62;

  --page-bg: #f6f7fb;
  --content-bg: #ffffff;
  --border: #e6e9ef;
  --border-strong: #d0d4e0;

  --text-primary: #323338;
  --text-secondary: #676879;
  --text-dim: #9699a6;

  --accent: #FE6D02;
  --accent-hover: #E35D00;
  --accent-light: #FFF1E4;

  --danger: #e2445c;
  --success: #00c875;

  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.06);
  --shadow-md: 0 4px 16px rgba(0,0,0,0.12);
  --shadow-lg: 0 12px 32px rgba(0,0,0,0.18);

  font-size: 15px;
}

/* Dark mode — toggled via the sidebar settings popover, persisted in
   localStorage, applied as data-theme on <html> (set by an inline script
   in partials/header.php's <head> before first paint, so there's no
   flash of the light theme on load). Sidebar/topbar/table-header stay
   solid orange/navy in both themes — those are the fixed brand chrome,
   not part of this token set — only the page/content surfaces and text
   change. Almost everything else in the app already reads these
   variables rather than hardcoding colors, so redefining them here is
   enough to re-theme the whole app without touching individual rules. */
:root[data-theme="dark"] {
  /* Tells the browser to render native form widgets (checkboxes, scroll-
     bars) with their dark variant instead of the light-mode-only default —
     without this, an unchecked <input type="checkbox"> stays a plain white
     box regardless of any CSS background/border set on it, since that part
     of its rendering is controlled by color-scheme, not by background. */
  color-scheme: dark;
  --page-bg: #1b1e30;
  --content-bg: #262a42;
  --border: #383c58;
  --border-strong: #4a4f70;

  --text-primary: #eef0f7;
  --text-secondary: #b7bad0;
  --text-dim: #8388a6;

  --accent-light: #3d2a18;
}

/* Full-page boot loading screen (partials/header.php) — shown for a
   minimum time then faded out by the inline script right after it in the
   markup, regardless of which page loaded. Was a single spinning logo;
   now a splash-shaped burst of teardrop petals + droplets (modeled on a
   client-supplied water-splash reference, recolored to the brand accent
   instead of blue) blooming outward behind the cube logo while it
   assembles itself from scattered tile pieces (boot-tile below), plus a
   real progress bar — all plain CSS transitions/keyframes, no animation
   library, kept theme-aware (background/petal colors are the existing
   --page-bg/--accent/--accent-hover tokens, so this looks right in dark
   mode too without a separate dark-mode override). */
.app-loading-screen {
  position: fixed; inset: 0; z-index: 500;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 56px;
  background: var(--page-bg);
  opacity: 1; transition: opacity .3s ease;
}
.app-loading-screen.is-hidden { opacity: 0; pointer-events: none; }

/* The stage is deliberately bigger than the logo/tile square (below) so
   the splash burst has room to radiate around the logo rather than
   getting buried behind it — matching the reference image's "void in
   the middle of the splash" composition. */
.boot-loader-stage { position: relative; width: 220px; height: 220px; }
/* z-index pins the splash strictly behind the logo tiles regardless of
   any radius jitter/petal-length overlap at the tile square's corners —
   the burst should read as something happening around/behind the logo,
   never as flecks sitting on top of it. */
.boot-burst { position: absolute; inset: 0; z-index: 1; }
/* top/left/width/height are set per-petal/drop in JS (centered on the
   stage for its own size), so the transform below only has to express
   the outward radiate + spin + grow — no percentage self-centering
   mixed into it. opacity/transform end states are also set directly by
   JS (the "reveal" pass), not by a class toggle, so the two never fall
   out of sync. The teardrop shape is one rounded-square corner (border-
   radius: 0 on one corner, 50% on the rest) rotated per-petal to point
   outward, echoing the reference splash's elongated petal shapes. */
.boot-burst-petal {
  position: absolute; border-radius: 0 50% 50% 50%;
  background: linear-gradient(135deg, var(--accent-hover), var(--accent));
  opacity: 0;
  transition: transform .55s cubic-bezier(.34,1.56,.64,1), opacity .35s ease;
}
.boot-burst-drop {
  position: absolute; border-radius: 50%;
  background: var(--accent);
  opacity: 0;
  transition: transform .5s cubic-bezier(.34,1.56,.64,1), opacity .35s ease;
}

.boot-tiles { position: absolute; top: 45px; left: 45px; width: 130px; height: 130px; z-index: 2; }
/* No border-radius here on purpose — a rounded corner on every tile
   leaves a tiny diamond-shaped gap at each 4-tile intersection once the
   grid is fully assembled, showing the page background through as a
   speckle of "dots" over the finished logo. Square corners butt the
   tiles together with no seam. */
.boot-tile {
  position: absolute; background-repeat: no-repeat;
  transition: transform .6s cubic-bezier(.34,1.56,.64,1), opacity .35s ease;
}

.boot-bar { width: 120px; height: 2px; border-radius: 2px; background: var(--border); overflow: hidden; }
.boot-bar-fill { height: 100%; width: 0%; background: var(--accent); transition: width .9s cubic-bezier(.22,.61,.36,1); }

/* Swivel left/right a few times, settle, then one full counterclockwise
   spin, looping — used for both the full-page boot screen and the item
   detail panel's loading state. Ends each cycle at rotate(-360deg), which
   renders identically to 0deg, so the infinite loop wraps with no visible
   snap back to start. */
@keyframes cube-swivel-spin {
  0%   { transform: rotate(0deg); }
  6%   { transform: rotate(-20deg); }
  12%  { transform: rotate(16deg); }
  18%  { transform: rotate(-12deg); }
  24%  { transform: rotate(8deg); }
  30%  { transform: rotate(0deg); }
  55%  { transform: rotate(0deg); }
  100% { transform: rotate(-360deg); }
}
.cube-swivel-spin { animation: cube-swivel-spin 3.2s ease-in-out infinite; }

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  color: var(--text-primary);
  background: var(--page-bg);
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; }
input, select, textarea { font-family: inherit; font-size: inherit; }

/* Global <select> styling — every dropdown in the app gets the same
   custom chevron instead of raw OS chrome, regardless of which (if any)
   context class it also carries (.user-role-select, .prompt-modal-input,
   etc). padding-right and every background-* sub-property here are
   !important specifically because a LOT of existing per-context select
   rules across this codebase (.automation-field select, .user-role-select,
   .kanban-toolbar select, .calendar-column-picker select, etc.) set
   `background: var(--page-bg)` as a shorthand — which silently resets
   background-image/repeat/position/size back to their initial values
   even though those rules only meant to set the color. Without
   !important here, the chevron either vanished or tiled repeatedly
   across the whole select (both actually happened before this was
   caught). background-color itself is deliberately left alone (no
   !important) so those context rules still control the fill color as
   before — only the arrow-related sub-properties are pinned. */
select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  padding-right: 32px !important;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23676879' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") !important;
  background-repeat: no-repeat !important;
  background-position: right 10px center !important;
  background-size: 14px !important;
  cursor: pointer;
}
select::-ms-expand { display: none; }
select:disabled { cursor: not-allowed; opacity: 0.55; }
:root[data-theme="dark"] select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23b7bad0' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") !important;
}

/* Number inputs — hide the native up/down stepper everywhere. These are
   typed values (hourly rates, expected hours), not something anyone
   increments by clicking tiny arrows, and the default browser chrome
   looked inconsistent next to every other plain-bordered input. */
input[type="number"] { -moz-appearance: textfield; }
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none; margin: 0;
}

.btn-primary {
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: var(--radius-sm);
  padding: 10px 18px;
  font-size: 0.92rem;
  font-weight: 600;
  transition: background .15s ease;
}
.btn-primary:hover { background: var(--accent-hover); }
.btn-secondary {
  background: var(--content-bg);
  color: var(--text-primary);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 9px 16px;
  font-size: 0.92rem;
  font-weight: 600;
  transition: border-color .15s ease, background .15s ease;
}
.btn-secondary:hover { border-color: var(--accent); background: var(--accent-light); }

.avatar-circle {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  color: #fff;
  font-weight: 700;
  flex-shrink: 0;
  overflow: hidden;
  background-size: cover;
  background-position: center;
}

/* Thin orange rounded-pill thumb on a visible light track, everywhere in
   the app — matches the client-supplied reference look (colored rounded
   sliders on a thin gray track), within what a real scrollbar can do
   (thumb and track share one width; a thumb literally wider than its own
   track isn't achievable with native scrollbars). 6px (was 10px) to read
   as a slim overlay-style bar rather than a thick page-chrome one.
   scrollbar-color/-width cover Firefox, which ignores ::-webkit-* rules
   entirely. Any element-specific ::-webkit-scrollbar rule elsewhere
   should stay consistent with this width unless it has a real reason to
   differ. */
html { scrollbar-width: thin; scrollbar-color: var(--accent) var(--page-bg); }
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: var(--page-bg); border-radius: 10px; }
::-webkit-scrollbar-thumb { background: var(--accent); border-radius: 10px; }
::-webkit-scrollbar-thumb:hover { background: var(--accent-hover); }
