/* Xway Collections — custom rules ported from src/index.css (React build). */

:root {
  --font-clean: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

* {
  font-family: var(--font-clean);
}

body {
  font-family: var(--font-clean);
  background-color: #f8fafc;
  color: #0f172a;
  overflow-x: hidden;
}

h1, h2, h3, h4, h5, h6, .font-heading {
  font-family: var(--font-clean);
}

.font-mono-spec {
  font-family: var(--font-clean);
}

footer, footer * {
  font-family: var(--font-clean) !important;
}

@keyframes xway-spin {
  to { transform: rotate(360deg); }
}

/* Global site styling — White theme, permanent (no dark mode). */

#xway-page-loader {
  background-color: #f8fafc !important;
}

/* Logo height is set directly on the <img> (h-10 md:h-14 in header.php) —
   md is this site's own mobile/desktop nav cutoff (see header.php's
   "flex md:hidden" mobile-menu-toggle button). Mobile also gets a near-zero
   header padding to keep the strip as compact as the "Get a Quote"/menu
   buttons beside it need. */
@media (max-width: 767px) {
  header#site-header {
    padding-top: 0 !important;
    padding-bottom: 0 !important;
  }
}

header {
  /* The unscrolled header uses Tailwind's bg-gradient-to-b/from-black/80
     utilities, which paint via background-image — background-color alone
     never touches that layer, so the black gradient kept rendering on top
     of this override, showing as a dark bar across the top of every page. */
  background-image: none !important;
  background-color: rgba(255, 255, 255, 0.95) !important;
  border-color: #cbd5e1 !important;
  /* Fixed padding regardless of nav.js's scroll-triggered py-3/py-2 toggle
     (Tailwind utility classes), which this needs !important to beat. */
  padding: 1px !important;
}

header .text-white,
header .text-neutral-300,
header .text-neutral-200 {
  color: #0f172a !important;
}

.bg-\[\#0c0c0c\],
.bg-\[\#080808\],
.bg-\[\#111\],
.bg-\[\#111111\],
.bg-\[\#101010\],
.bg-\[\#0e0e0e\],
.bg-\[\#121212\],
.bg-black,
.bg-neutral-950,
.bg-neutral-900 {
  background-color: #ffffff !important;
  color: #0f172a !important;
}

.bg-\[\#141414\],
.bg-\[\#181818\],
.bg-\[\#161616\],
.bg-neutral-900\/50,
.bg-neutral-900\/60,
.bg-neutral-900\/90,
.industrial-card {
  background-color: #f1f5f9 !important;
  border-color: #cbd5e1 !important;
  color: #0f172a !important;
}

.border-neutral-800,
.border-neutral-900,
.border-neutral-700,
.border-\[\#222\],
.border-\[\#222222\],
.border-white\/10,
.border-white\/5 {
  border-color: #cbd5e1 !important;
}

.text-white,
.text-neutral-100,
.text-neutral-200 {
  color: #0f172a !important;
}

/* hover:text-white is a DIFFERENT compiled selector (.hover\:text-white:hover)
   from plain .text-white, so the rule above never touches it — every button/
   label across the admin panel (Edit, Delete, Cancel, Save, nav items, etc.)
   uses this on a background that's already been turned white by the rules
   below, so hovering made the text vanish (white-on-white). Same fix, same
   color, just scoped to the hover state too. */
.hover\:text-white:hover {
  color: #0f172a !important;
}

/* Same split-selector problem as above, but for backgrounds: hover:bg-neutral-900
   (nav items, modal close buttons, table-row hover) is a different compiled
   selector from plain bg-neutral-900, so the base-state override above never
   touches it — hovering painted a dark background behind text that's already
   forced dark (either by the rule above or by the static .text-white rule),
   making it unreadable. */
.hover\:bg-neutral-900:hover,
.hover\:bg-neutral-900\/50:hover,
.hover\:bg-neutral-800:hover {
  background-color: #f1f5f9 !important;
}

.text-neutral-300,
.text-neutral-400 {
  color: #334155 !important;
}

.text-neutral-500,
.text-neutral-600 {
  color: #64748b !important;
}

/* Decorative dark overlays (image badges/captions, checkbox group
   backgrounds) are deliberately kept dark for contrast against photos —
   restore the original light neutral text color the rules above would
   otherwise incorrectly darken to match the page's light background, which
   left this text unreadable against its own still-dark container. Scoped to
   :not(.fixed) because every modal/dialog backdrop in this codebase also
   uses bg-black/NN (as a dimming overlay) but is always .fixed — without
   this exclusion, the selector would match the backdrop and force every
   heading/label inside the modal to stay light-colored even after the modal
   panel itself correctly turns white. Decorative badges are always
   .absolute, never .fixed, so this cleanly tells the two apart. */
[class*="bg-black/"]:not(.fixed).text-white,
[class*="bg-black/"]:not(.fixed) .text-white {
  color: #ffffff !important;
}

[class*="bg-black/"]:not(.fixed).text-neutral-300,
[class*="bg-black/"]:not(.fixed) .text-neutral-300 {
  color: #d4d4d4 !important;
}

[class*="bg-black/"]:not(.fixed).text-neutral-400,
[class*="bg-black/"]:not(.fixed) .text-neutral-400 {
  color: #a3a3a3 !important;
}

[class*="bg-black/"]:not(.fixed).text-neutral-500,
[class*="bg-black/"]:not(.fixed) .text-neutral-500 {
  color: #737373 !important;
}

/* Home hero: the copy column sits directly over a background photo behind a
   hardcoded dark gradient (bg-gradient-to-b from-[#080808]/60 ... to-[#080808])
   — that gradient exists to keep light text legible against the photo and
   isn't meant to lighten with the page theme. .bg-grid-pattern only appears
   on this one section, so it safely scopes the exception to just the hero's
   text column (lg:col-span-7) without touching the card beside it, whose own
   solid bg-black/bg-neutral-900 backgrounds already turn light correctly. */
.bg-grid-pattern .lg\:col-span-7 .text-white:not(.bg-neutral-900) {
  color: #ffffff !important;
}
.bg-grid-pattern .lg\:col-span-7 .text-neutral-300 {
  color: #d4d4d4 !important;
}
.bg-grid-pattern .lg\:col-span-7 .text-neutral-500 {
  color: #737373 !important;
}
/* ...except sub-containers within that column that have their own light
   background (e.g. the status pill, bg-neutral-900/90) — those should use
   normal dark text like everywhere else, not the gradient-restoring color
   above, which would otherwise be light-on-light. */
.bg-grid-pattern .lg\:col-span-7 [class*="bg-neutral-900"] .text-neutral-300 {
  color: #334155 !important;
}
.bg-grid-pattern .lg\:col-span-7 [class*="bg-neutral-900"] .text-neutral-500 {
  color: #64748b !important;
}

.bg-grid-pattern {
  background-image:
    linear-gradient(to right, rgba(0, 0, 0, 0.06) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(0, 0, 0, 0.06) 1px, transparent 1px) !important;
}

.bg-dots-pattern {
  background-image: radial-gradient(rgba(0, 0, 0, 0.12) 1px, transparent 1px) !important;
}

/* Modals & Dialogs */
.fixed .bg-\[\#121212\],
.fixed .bg-\[\#141414\],
.fixed .bg-\[\#111\],
.fixed .bg-\[\#0c0c0c\] {
  background-color: #ffffff !important;
  border-color: #cbd5e1 !important;
  color: #0f172a !important;
}

/* Inputs & Form Controls */
input,
select,
textarea {
  background-color: #f8fafc !important;
  color: #0f172a !important;
  border-color: #cbd5e1 !important;
}

input::placeholder,
textarea::placeholder {
  color: #94a3b8 !important;
}

/* Custom Industrial Accent Colors */
.accent-orange {
  color: #CA2927;
}

.bg-accent-orange {
  background-color: #CA2927;
}

.border-accent-orange {
  border-color: #CA2927;
}

/* Custom Scrollbar */
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
::-webkit-scrollbar-track {
  background: #f1f5f9;
}
::-webkit-scrollbar-thumb {
  background: #cbd5e1;
}
::-webkit-scrollbar-thumb:hover {
  background: #CA2927;
}

/* Marquee Animation */
@keyframes marquee {
  0% { transform: translateX(0%); }
  100% { transform: translateX(-50%); }
}

.animate-marquee {
  display: flex;
  width: max-content;
  animation: marquee 25s linear infinite;
}

.animate-marquee:hover {
  animation-play-state: paused;
}

/* Subtle Glass / Industrial Borders */
.industrial-border {
  border: 1px solid rgba(255, 255, 255, 0.08);
}

.industrial-card {
  background: #121212;
  border: 1px solid #222222;
  transition: border-color 0.2s ease, transform 0.25s ease, box-shadow 0.25s ease;
}

@media (prefers-reduced-motion: no-preference) {
  .industrial-card:hover {
    border-color: #CA2927;
    transform: translateY(-4px);
    box-shadow: 0 16px 32px -14px rgba(15, 23, 42, .16);
  }
}

@media (prefers-reduced-motion: reduce) {
  .industrial-card:hover {
    border-color: #CA2927;
  }
}

/* ============================================================
   Motion & micro-interactions
   - .reveal / .reveal-up / .reveal-left / .reveal-right / .reveal-scale:
     scroll-triggered entrances, driven by assets/js/reveal.js
     (IntersectionObserver adds .is-visible once, then stops watching —
     content only animates in once, never re-hides on scroll-back).
   - .reveal-delay-1..4: stagger siblings in a grid/row so a set of
     cards doesn't all pop in at the exact same instant.
   - .hero-enter / .hero-pop: same visual language but for above-the-fold
     content, which is already in view on load so it can't rely on the
     scroll observer — these just play immediately via CSS animation.
   - .hover-lift: a small, consistent hover treatment for card-style
     containers that aren't already using .industrial-card.
   Every rule here is skipped under prefers-reduced-motion: reduce —
   content simply appears in its final state, no motion at all.
   ============================================================ */
@media (prefers-reduced-motion: no-preference) {
  .reveal {
    opacity: 0;
    transition: opacity .6s ease, transform .6s cubic-bezier(.22, .61, .36, 1);
  }
  .reveal-up { transform: translateY(28px); }
  .reveal-left { transform: translateX(-36px); }
  .reveal-right { transform: translateX(36px); }
  .reveal-scale { transform: scale(.95); }
  .reveal.is-visible {
    opacity: 1;
    transform: none;
  }

  .reveal-delay-1 { transition-delay: .08s; }
  .reveal-delay-2 { transition-delay: .16s; }
  .reveal-delay-3 { transition-delay: .24s; }
  .reveal-delay-4 { transition-delay: .32s; }

  @keyframes hero-enter {
    from { opacity: 0; transform: translateY(18px); }
    to { opacity: 1; transform: translateY(0); }
  }
  .hero-enter {
    opacity: 0;
    animation: hero-enter .7s cubic-bezier(.22, .61, .36, 1) forwards;
  }
  .hero-enter-1 { animation-delay: .05s; }
  .hero-enter-2 { animation-delay: .15s; }
  .hero-enter-3 { animation-delay: .25s; }
  .hero-enter-4 { animation-delay: .35s; }
  .hero-enter-5 { animation-delay: .45s; }
  .hero-enter-6 { animation-delay: .55s; }

  @keyframes hero-pop {
    from { opacity: 0; transform: scale(.9); }
    to { opacity: 1; transform: scale(1); }
  }
  .hero-pop {
    opacity: 0;
    animation: hero-pop .5s cubic-bezier(.22, .61, .36, 1) forwards;
  }

  /* Fade-only (no transform): the live-camera and journey-timeline selector
     buttons are rebuilt by JS on every click/render (fixed nth-child delays
     below), and the active button among them carries its own Tailwind
     `scale-105` class. Tailwind v4 emits that via the standalone CSS
     `scale` property rather than `transform`, so it isn't actually clobbered
     by an entrance animation on `transform` with fill-mode `both` — but
     keeping this animation opacity-only avoids relying on that property
     split and keeps a small UI control's entrance to a plain fade. */
  @keyframes fade-in-fast {
    from { opacity: 0; }
    to { opacity: 1; }
  }
  #cam-selector .cam-btn,
  #journey-selector .step-btn {
    animation: fade-in-fast .4s cubic-bezier(.22, .61, .36, 1) both;
  }
  #cam-selector .cam-btn:nth-child(1), #journey-selector .step-btn:nth-child(1) { animation-delay: .04s; }
  #cam-selector .cam-btn:nth-child(2), #journey-selector .step-btn:nth-child(2) { animation-delay: .09s; }
  #cam-selector .cam-btn:nth-child(3), #journey-selector .step-btn:nth-child(3) { animation-delay: .14s; }
  #cam-selector .cam-btn:nth-child(4), #journey-selector .step-btn:nth-child(4) { animation-delay: .19s; }
  #journey-selector .step-btn:nth-child(5) { animation-delay: .24s; }
  #journey-selector .step-btn:nth-child(6) { animation-delay: .29s; }
  #journey-selector .step-btn:nth-child(7) { animation-delay: .34s; }
  #journey-selector .step-btn:nth-child(8) { animation-delay: .39s; }
  #journey-selector .step-btn:nth-child(9) { animation-delay: .44s; }
  #journey-selector .step-btn:nth-child(10) { animation-delay: .49s; }

  .hover-lift {
    transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease;
  }
  .hover-lift:hover {
    transform: translateY(-6px);
    box-shadow: 0 16px 32px -12px rgba(15, 23, 42, .18);
  }
}

@media (prefers-reduced-motion: reduce) {
  .reveal, .hero-enter, .hero-pop {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
  }
}

/* Buttons/pills with a solid red background always need white text,
   regardless of the sitewide text-white -> dark-navy override near the top
   of this file — that override exists for body copy that used to assume a
   dark PAGE background; it's wrong for text sitting on the brand-red button
   background, which is plenty dark on its own and needs white text
   unconditionally. The home hero's .bg-grid-pattern .lg\:col-span-7
   .text-white:not(.bg-neutral-900) exception (also !important) is actually
   4-class specificity — :not()'s argument counts toward specificity too —
   so .bg-\[\#CA2927\] repeated below isn't decorative padding, it's what
   makes these rules match that same 4-class specificity outright rather
   than depending on source order (still placed last as a second safety
   net). */
.bg-\[\#CA2927\].bg-\[\#CA2927\].text-white,
.bg-\[\#CA2927\].bg-\[\#CA2927\] .text-white {
  color: #ffffff !important;
}
/* ...and once hover flips that background to white (the common pattern on
   these buttons), the text needs to flip to black to stay readable — same
   split-selector problem as .hover\:text-white near the top of this file,
   scoped to these buttons so it wins over the rule immediately above it. */
.bg-\[\#CA2927\].bg-\[\#CA2927\].hover\:text-black:hover {
  color: #000000 !important;
}
