/* ==========================================================================
   SPIE ANDC — GLIMPSES · Premium Interaction Layer
   Vanilla CSS only. All motion runs on transform / opacity / filter.
   Companion to script.js — see that file for the JS half of every
   effect below (scroll-reveal, ripple, parallax, channel switch, etc).
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. Custom easing + timing tokens
   Reused everywhere so every animation in the site shares one "feel".
   -------------------------------------------------------------------------- */
:root {
  --ease-premium: cubic-bezier(0.16, 1, 0.3, 1);      /* signature "settle" ease — decisive start, soft landing */
  --ease-out-soft: cubic-bezier(0.22, 0.61, 0.36, 1);  /* gentler variant for large/slow elements */
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);    /* slight overshoot, used only for toast + tab indicator */

  --dur-instant: 120ms;
  --dur-fast: 200ms;
  --dur-base: 350ms;
  --dur-slow: 600ms;
  --dur-cinematic: 900ms;
}

/* --------------------------------------------------------------------------
   1. Page-load choreography
   Elements start hidden via [data-intro] and are released by script.js
   adding .intro-ready to <body> a tick after DOMContentLoaded. Doing the
   "hidden" state in CSS (not inline style) means content is still there
   for no-JS / slow-JS cases — it just visibly settles in a beat later
   instead of popping.
   -------------------------------------------------------------------------- */
[data-intro] {
  opacity: 0;
  will-change: transform, opacity, filter;
}

[data-intro="hero-eyebrow"] {
  transform: translateY(10px);
  transition: opacity 600ms var(--ease-premium) 120ms, transform 600ms var(--ease-premium) 120ms;
}

[data-intro="hero-heading"] {
  transform: translateY(18px);
  filter: blur(6px);
  transition: opacity 750ms var(--ease-premium) 200ms,
              transform 750ms var(--ease-premium) 200ms,
              filter 750ms var(--ease-premium) 200ms;
}

[data-intro="hero-desc"] {
  transform: translateY(14px);
  transition: opacity 650ms var(--ease-premium) 340ms, transform 650ms var(--ease-premium) 340ms;
}

[data-intro="hero-badges"] {
  transform: translateY(12px);
  transition: opacity 550ms var(--ease-premium) 460ms, transform 550ms var(--ease-premium) 460ms;
}

/* Individual badge chips stagger inside the badges container via --delay.
   Scoped to .hero-badge-chip (added by script.js) rather than every
   direct child, so the thin divider lines between chips stay visible
   immediately instead of popping in as their own separate beat. */
[data-intro="hero-badges"] .hero-badge-chip {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 450ms var(--ease-premium), transform 450ms var(--ease-premium);
  transition-delay: calc(560ms + (var(--delay, 0) * 1ms));
}

[data-intro="main"] {
  transform: translateY(10px);
  transition: opacity 600ms var(--ease-premium) 260ms, transform 600ms var(--ease-premium) 260ms;
}

body.intro-ready [data-intro],
body.intro-ready [data-intro] .hero-badge-chip {
  opacity: 1;
  transform: translateY(0) translateX(0) scale(1);
  filter: blur(0);
}

/* If JS never runs (blocked/broken), don't leave the page invisible */
body.no-js-fallback [data-intro],
body.no-js-fallback [data-intro] .hero-badge-chip {
  opacity: 1;
  transform: none;
  filter: none;
}

/* Header offset for fixed navbar (.header has height 90px, 70px on mobile <= 575px) */
.glimpses-page-main {
  padding-top: 90px;
}

@media (max-width: 575px) {
  .glimpses-page-main {
    padding-top: 70px;
  }
}

/* --------------------------------------------------------------------------
   2. Hero optics — laser beam, diffraction rings, ambient glow
   All the SVG elements already exist in the markup; these rules only add
   motion to them. Selectors are scoped to the hero section wrapper.
   -------------------------------------------------------------------------- */
.hero-optics-svg {
  will-change: transform;
}

.hero-optics-svg .laser-line {
  stroke-dasharray: 8 6;
  animation: laser-flow 5.5s linear infinite;
}

.hero-optics-svg .laser-line-secondary {
  stroke-dasharray: 4 10;
  animation: laser-flow 7.5s linear infinite reverse;
}

@keyframes laser-flow {
  to { stroke-dashoffset: -140; }
}

.hero-optics-svg .diffraction-ring {
  transform-origin: center;
  transform-box: fill-box;
  animation: ring-breathe 9s var(--ease-out-soft) infinite;
}

.hero-optics-svg .diffraction-ring.ring-outer {
  animation-duration: 12s;
  animation-delay: -3s; /* negative delay = starts partway through, avoids synced pulsing */
}

@keyframes ring-breathe {
  0%, 100% { transform: scale(1) rotate(0deg); opacity: 0.85; }
  50% { transform: scale(1.06) rotate(1.5deg); opacity: 1; }
}

.hero-glow {
  will-change: transform, opacity;
  animation: glow-drift 14s var(--ease-out-soft) infinite;
}

.hero-glow.glow-crimson {
  animation-duration: 17s;
  animation-direction: reverse;
}

@keyframes glow-drift {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); opacity: 0.4; }
  50% { transform: translate3d(14px, -10px, 0) scale(1.08); opacity: 0.55; }
}

/* Mouse parallax targets — script.js writes --px / --py (in px) per element.
   Kept as a separate transform layer via translate3d so it composites with
   the drift animation above rather than fighting it. */
.parallax-target {
  transform: translate3d(calc(var(--px, 0px)), calc(var(--py, 0px)), 0);
  transition: transform 700ms var(--ease-out-soft);
}

/* --------------------------------------------------------------------------
   3. Scroll reveal system
   .reveal-* sets the hidden state; .is-visible (added by IntersectionObserver
   in script.js) releases it. Fires once — script.js unobserves after reveal.
   -------------------------------------------------------------------------- */
.reveal-up, .reveal-down, .reveal-left, .reveal-right, .reveal-scale, .reveal-blur {
  opacity: 0;
  will-change: transform, opacity, filter;
  transition: opacity var(--dur-slow) var(--ease-premium),
              transform var(--dur-slow) var(--ease-premium),
              filter var(--dur-slow) var(--ease-premium);
  transition-delay: calc(var(--delay, 0) * 1ms);
}

.reveal-up { transform: translateY(30px); }
.reveal-down { transform: translateY(-30px); }
.reveal-left { transform: translateX(-30px); }
.reveal-right { transform: translateX(30px); }
.reveal-scale { transform: scale(0.94); }
.reveal-blur { filter: blur(10px); }

.reveal-up.is-visible,
.reveal-down.is-visible,
.reveal-left.is-visible,
.reveal-right.is-visible,
.reveal-scale.is-visible,
.reveal-blur.is-visible {
  opacity: 1;
  transform: translateY(0) translateX(0) scale(1);
  filter: blur(0);
}

/* --------------------------------------------------------------------------
   4. Staggered card grids
   Applied alongside .reveal-up on card collections; JS sets --delay per
   card (index * 80ms) so no per-card class is needed.
   -------------------------------------------------------------------------- */
.stagger-item {
  transition-delay: calc(var(--delay, 0) * 1ms);
}

/* --------------------------------------------------------------------------
   5. Blog card premium hover
   Existing markup already has group-hover image scale + shadow transition
   via Tailwind. These rules layer the lift, badge nudge, arrow shift, and
   top highlight on top without touching the Tailwind classes.
   -------------------------------------------------------------------------- */
.blog-card {
  transition: transform var(--dur-base) var(--ease-premium), box-shadow var(--dur-base) var(--ease-premium);
  position: relative;
}

.blog-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--laser-cyan, #CE1211), transparent);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-premium);
  pointer-events: none;
  z-index: 1;
}

.blog-card:hover {
  transform: translateY(-6px);
}

.blog-card:hover::before {
  opacity: 0.7;
}

.blog-card .category-badge {
  transition: transform var(--dur-fast) var(--ease-premium);
}

.blog-card:hover .category-badge {
  transform: translate(2px, -1px);
}

.blog-card .read-arrow-btn {
  transition: transform var(--dur-fast) var(--ease-premium), background-color var(--dur-fast) ease;
}

.blog-card:hover .read-arrow-btn {
  transform: translateX(2px);
}

/* --------------------------------------------------------------------------
   6. Image hover — article / magazine imagery
   -------------------------------------------------------------------------- */
.img-premium-hover {
  overflow: hidden;
}

.img-premium-hover img {
  transform-origin: center;
  transition: transform 700ms var(--ease-out-soft), filter 700ms var(--ease-out-soft);
}

.img-premium-hover:hover img {
  transform: scale(1.045);
  filter: brightness(1.03);
}

/* --------------------------------------------------------------------------
   7. Featured article — light sweep
   A thin diagonal highlight that travels across the image on hover, like a
   laser scan line. Pseudo-element on the image wrapper so it never
   interferes with the existing gradient overlays already in the markup.
   -------------------------------------------------------------------------- */
.feature-sweep-wrap {
  position: relative;
  overflow: hidden;
}

.feature-sweep-wrap::after {
  content: "";
  position: absolute;
  top: 0;
  left: -60%;
  width: 35%;
  height: 100%;
  background: linear-gradient(
    100deg,
    transparent 0%,
    rgba(206, 18, 17, 0.16) 45%,
    rgba(255, 255, 255, 0.22) 50%,
    rgba(206, 18, 17, 0.16) 55%,
    transparent 100%
  );
  transform: skewX(-15deg);
  transition: left 900ms var(--ease-premium);
  pointer-events: none;
  z-index: 2;
}

.blog-card:hover .feature-sweep-wrap::after {
  left: 130%;
}

.feature-badge-glow {
  transition: box-shadow var(--dur-slow) var(--ease-premium);
}

.blog-card:hover .feature-badge-glow {
  box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.12), 0 0 18px rgba(206, 18, 17, 0.35);
}

/* --------------------------------------------------------------------------
   8. Channel view transitions
   script.js toggles .channel-enter on the incoming view for one animation
   cycle, then removes it. The old "hidden" toggling logic is untouched —
   this only animates the moment a view becomes visible.
   -------------------------------------------------------------------------- */


.channel-view.channel-enter {
  animation: channel-in var(--dur-cinematic) var(--ease-premium);
}

@keyframes channel-in {
  0% { opacity: 0; transform: translateY(16px); filter: blur(4px); }
  100% { opacity: 1; transform: translateY(0); filter: blur(0); }
}

/* --------------------------------------------------------------------------
   9. Channel tab buttons — active indicator + hover nudge
   -------------------------------------------------------------------------- */
.tab-btn {
  position: relative;
  transition: transform var(--dur-fast) var(--ease-premium), box-shadow var(--dur-fast) var(--ease-premium),
              background-color var(--dur-fast) ease;
}

.tab-btn.active {
  transform: translateY(-1px);
}

.tab-btn:not(.active):hover {
  transform: translateY(-1px);
}

.tab-btn:not(.active):hover .material-symbols-outlined {
  transform: translateX(2px);
}

.tab-btn .material-symbols-outlined {
  transition: transform var(--dur-fast) var(--ease-premium);
}

.tab-indicator {
  position: absolute;
  bottom: -13px;
  left: 8px;
  right: 8px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--laser-cyan, #CE1211), var(--primary-container, #B91010));
  opacity: 0;
  transform: scaleX(0.4);
  transition: opacity var(--dur-base) var(--ease-spring), transform var(--dur-base) var(--ease-spring);
}

.tab-btn.active .tab-indicator {
  opacity: 1;
  transform: scaleX(1);
}

/* --------------------------------------------------------------------------
   10. Filtering — blog + inshort cards animate out/in on filter change
   script.js toggles these classes instead of setting display directly;
   display:none is still applied, but only after the fade-out finishes.
   -------------------------------------------------------------------------- */
.blog-card, .inshort-card {
  transition: opacity var(--dur-base) var(--ease-premium), transform var(--dur-base) var(--ease-premium);
}

.filter-hide {
  opacity: 0;
  transform: scale(0.96) translateY(6px);
  pointer-events: none;
}

.filter-show {
  animation: filter-in var(--dur-slow) var(--ease-premium);
}

@keyframes filter-in {
  from { opacity: 0; transform: scale(0.96) translateY(6px); }
  to { opacity: 1; transform: scale(1) translateY(0); }
}

/* --------------------------------------------------------------------------
   11. Search box focus state
   -------------------------------------------------------------------------- */
.search-wrap {
  transition: transform var(--dur-base) var(--ease-premium), box-shadow var(--dur-base) var(--ease-premium);
}

.search-wrap.search-focused {
  transform: scale(1.02);
  box-shadow: 0 0 0 3px rgba(206, 18, 17, 0.22), 0 4px 14px rgba(15, 23, 42, 0.08);
}

.search-wrap .material-symbols-outlined {
  transition: color var(--dur-fast) ease, transform var(--dur-fast) var(--ease-premium);
}

.search-wrap.search-focused .material-symbols-outlined {
  color: var(--laser-cyan, #CE1211);
  transform: scale(1.08);
}

/* --------------------------------------------------------------------------
   12. Magazine cover — physical tilt
   JS sets --tiltX / --tiltY from cursor position within the cover bounds.
   -------------------------------------------------------------------------- */
.magazine-cover-wrap {
  perspective: 1000px;
}

.magazine-cover {
  transform-style: preserve-3d;
  transform: rotateX(var(--tiltY, 0deg)) rotateY(var(--tiltX, 0deg)) translateZ(0);
  transition: transform var(--dur-base) var(--ease-out-soft), box-shadow var(--dur-base) ease;
  position: relative;
  overflow: hidden;
}

.magazine-cover-wrap:hover .magazine-cover {
  box-shadow: 0 24px 48px -12px rgba(15, 23, 42, 0.35);
}

.magazine-cover::after {
  content: "";
  position: absolute;
  top: -50%;
  left: -60%;
  width: 40%;
  height: 200%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.18), transparent);
  transform: rotate(20deg);
  transition: left 800ms var(--ease-premium);
  pointer-events: none;
}

.magazine-cover-wrap:hover .magazine-cover::after {
  left: 130%;
}

/* --------------------------------------------------------------------------
   13. Archive cards — hover lift + download nudge
   -------------------------------------------------------------------------- */
.archive-card {
  transition: transform var(--dur-base) var(--ease-premium), box-shadow var(--dur-base) var(--ease-premium);
}

.archive-card:hover {
  transform: translateY(-4px);
}

.archive-card .download-arrow {
  display: inline-block;
  transition: transform var(--dur-fast) var(--ease-premium);
}

.archive-card:hover .download-arrow {
  transform: translateX(3px);
}

/* --------------------------------------------------------------------------
   14. SmartBriefs feed — hover lift + left accent
   -------------------------------------------------------------------------- */
.inshort-card {
  position: relative;
  border-left: 2px solid transparent;
  transition: transform var(--dur-base) var(--ease-premium), box-shadow var(--dur-base) var(--ease-premium),
              border-color var(--dur-base) ease;
}

.inshort-card:hover {
  transform: translateY(-3px);
  border-left-color: var(--primary-container, #B91010);
}

.inshort-card .inshort-timestamp {
  transition: opacity var(--dur-fast) ease;
  opacity: 0.75;
}

.inshort-card:hover .inshort-timestamp {
  opacity: 1;
}

.inshort-card .inshort-action-icon {
  transition: transform var(--dur-fast) var(--ease-premium);
}

.inshort-card:hover .inshort-action-icon {
  transform: scale(1.08);
}

.live-pulse-dot {
  position: relative;
}

.live-pulse-dot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 9999px;
  background: inherit;
  animation: live-ripple 2.2s ease-out infinite;
}

@keyframes live-ripple {
  0% { transform: scale(1); opacity: 0.6; }
  100% { transform: scale(2.6); opacity: 0; }
}

/* --------------------------------------------------------------------------
   15. Button micro-interactions
   -------------------------------------------------------------------------- */
.btn-premium {
  position: relative;
  overflow: hidden;
  transition: transform var(--dur-instant) var(--ease-premium), box-shadow var(--dur-fast) ease;
}

.btn-premium:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 16px -4px rgba(15, 23, 42, 0.18);
}

.btn-premium:active {
  transform: translateY(0) scale(0.98);
}

.btn-premium:focus-visible {
  outline: 2px solid var(--laser-cyan, #CE1211);
  outline-offset: 2px;
}

.btn-premium .material-symbols-outlined {
  transition: transform var(--dur-fast) var(--ease-premium);
}

.btn-premium:hover .material-symbols-outlined {
  transform: translateX(2px);
}

/* Primary CTA light sweep */
.btn-sweep::before {
  content: "";
  position: absolute;
  top: 0;
  left: -75%;
  width: 50%;
  height: 100%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.25), transparent);
  transform: skewX(-20deg);
  transition: left 650ms var(--ease-premium);
  pointer-events: none;
}

.btn-sweep:hover::before {
  left: 125%;
}

/* --------------------------------------------------------------------------
   16. Ripple effect
   Generated span.ripple-el is inserted by script.js at click coordinates.
   -------------------------------------------------------------------------- */
.ripple-host {
  position: relative;
  overflow: hidden;
}

.ripple-el {
  position: absolute;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.45);
  transform: scale(0);
  animation: ripple-expand 600ms var(--ease-out-soft);
  pointer-events: none;
}

@keyframes ripple-expand {
  to { transform: scale(1); opacity: 0; }
}

/* --------------------------------------------------------------------------
   17. Blog modal
   -------------------------------------------------------------------------- */
#blog-modal {
  transition: opacity var(--dur-base) var(--ease-premium);
}

#blog-modal .modal-panel {
  transform: translateY(25px) scale(0.97);
  opacity: 0;
  transition: transform var(--dur-base) var(--ease-premium), opacity var(--dur-base) var(--ease-premium);
}

#blog-modal.modal-open .modal-panel {
  transform: translateY(0) scale(1);
  opacity: 1;
}

/* --------------------------------------------------------------------------
   17.5. Scroll Lock
   -------------------------------------------------------------------------- */
html.scroll-lock,
body.scroll-lock {
  overflow: hidden !important;
}

/* --------------------------------------------------------------------------
   18. Toast notification
   Existing showToast() API (translate-y-20/opacity-0 <-> translate-y-0/
   opacity-100 class toggling) is left completely intact in script.js.
   These rules only add the spring easing + icon entrance + progress bar
   as a layer on top, keyed off the same classes it already toggles.
   -------------------------------------------------------------------------- */
#glimpses-toast {
  transition: transform 550ms var(--ease-spring), opacity 300ms ease !important;
  overflow: hidden;
}

#glimpses-toast #toast-icon {
  display: inline-block;
  transition: transform 400ms var(--ease-spring), opacity 300ms ease;
  transform: rotate(-30deg) scale(0.7);
  opacity: 0;
}

#glimpses-toast.translate-y-0 #toast-icon {
  transform: rotate(0deg) scale(1);
  opacity: 1;
  transition-delay: 80ms;
}

.toast-progress {
  position: absolute;
  bottom: 0;
  left: 0;
  height: 2px;
  background: var(--laser-cyan, #CE1211);
  width: 100%;
  transform-origin: left;
  animation: toast-shrink 3s linear forwards;
}

@keyframes toast-shrink {
  from { transform: scaleX(1); }
  to { transform: scaleX(0); }
}

/* --------------------------------------------------------------------------
   19. Science element hover glow (wavelength labels, research badges, etc.)
   -------------------------------------------------------------------------- */
.science-glow {
  transition: text-shadow var(--dur-base) ease, filter var(--dur-base) ease;
}

.science-glow:hover {
  filter: drop-shadow(0 0 6px rgba(206, 18, 17, 0.45));
}

/* --------------------------------------------------------------------------
   22. Hero heading text reveal (letter-level blur-to-sharp on load)
   Handled primarily via [data-intro="hero-heading"] above; this adds a
   finishing touch — a very subtle letter-spacing settle.
   -------------------------------------------------------------------------- */
.hero-heading-reveal {
  letter-spacing: 0.01em;
  transition: letter-spacing 750ms var(--ease-premium) 200ms;
}

body.intro-ready .hero-heading-reveal {
  letter-spacing: normal;
}

/* --------------------------------------------------------------------------
   23. Custom cursor (desktop only, opt-in via body.custom-cursor-active)
   -------------------------------------------------------------------------- */
.custom-cursor-active {
  cursor: none;
}

#custom-cursor-dot {
  position: fixed;
  top: 0;
  left: 0;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--primary-container, #B91010);
  pointer-events: none;
  z-index: 9999;
  transform: translate3d(-50%, -50%, 0);
  transition: width 200ms var(--ease-premium), height 200ms var(--ease-premium),
              background-color 200ms ease, opacity 200ms ease;
  will-change: transform;
}

#custom-cursor-dot.cursor-expand {
  width: 32px;
  height: 32px;
  background: rgba(206, 18, 17, 0.35);
}

/* Never show the custom cursor on touch devices even if JS mistakenly runs */
@media (hover: none) and (pointer: coarse) {
  #custom-cursor-dot { display: none !important; }
  .custom-cursor-active { cursor: auto !important; }
}

/* --------------------------------------------------------------------------
   23.5. Filtering Animations
   -------------------------------------------------------------------------- */
.filter-hide {
  opacity: 0 !important;
  transform: scale(0.95) translateY(10px) !important;
  transition: opacity 300ms var(--ease-premium), transform 300ms var(--ease-premium) !important;
  pointer-events: none;
}

.filter-show {
  animation: filter-in 400ms var(--ease-premium) forwards;
  animation-delay: calc(var(--delay, 0) * 1ms);
  opacity: 0;
}

@keyframes filter-in {
  from {
    opacity: 0;
    transform: scale(0.95) translateY(10px);
  }
  to {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

/* --------------------------------------------------------------------------
   24. Blog Modal — open/close transitions
   The JS toggles .modal-open on #blog-modal. The backdrop and panel
   each transition opacity + transform so the close button's transitionend
   handler fires reliably.
   -------------------------------------------------------------------------- */
html.scroll-lock,
body.scroll-lock {
  overflow: hidden !important;
}

#blog-modal,
#inshort-modal,
#archive-modal,
#lightbox-modal {
  transition: opacity var(--dur-base, 350ms) var(--ease-premium, ease);
}

#blog-modal:not(.modal-open) {
  opacity: 0;
}

#blog-modal.modal-open {
  opacity: 1;
}

#blog-modal .modal-panel {
  transform: translateY(24px) scale(0.97);
  opacity: 0;
  transition: transform var(--dur-base, 350ms) var(--ease-premium, ease),
              opacity var(--dur-base, 350ms) var(--ease-premium, ease);
}

#blog-modal.modal-open .modal-panel {
  transform: translateY(0) scale(1);
  opacity: 1;
}

/* --------------------------------------------------------------------------
   24.5. Inshort Modal — viewport positioning, containment & animations
   The JS toggles .inshort-modal-open on #inshort-modal. The backdrop fades
   in while the panel scales up from below with a spring-like settle.
   -------------------------------------------------------------------------- */
#inshort-modal {
  position: fixed !important;
  inset: 0 !important;
  top: 0 !important;
  left: 0 !important;
  width: 100% !important;
  height: 100% !important;
  height: 100dvh !important;
  z-index: 1050 !important;
  box-sizing: border-box;
  overscroll-behavior: contain;
  transition: opacity 400ms var(--ease-premium, ease),
              backdrop-filter 400ms ease;
}

#inshort-modal:not(.inshort-modal-open) {
  opacity: 0;
  pointer-events: none;
}

#inshort-modal.inshort-modal-open {
  opacity: 1;
  pointer-events: auto;
}

#inshort-modal .modal-panel {
  max-height: 90vh;
  max-height: 90dvh;
  display: flex;
  flex-direction: column;
  overscroll-behavior: contain;
  transform: translateY(40px) scale(0.92);
  opacity: 0;
  transition: transform 450ms var(--ease-premium, cubic-bezier(0.16, 1, 0.3, 1)),
              opacity 350ms var(--ease-premium, ease);
}

#inshort-modal.inshort-modal-open .modal-panel {
  transform: translateY(0) scale(1);
  opacity: 1;
}

#inshort-modal #inshort-modal-scroll {
  overscroll-behavior: contain;
}

/* --------------------------------------------------------------------------
   25. Reduced motion — the single source of truth for "calm mode"
   This block intentionally comes last so it wins the cascade for anyone
   with prefers-reduced-motion set, without needing !important scattered
   everywhere above. Functional transitions (things that communicate
   state, like the modal opening or a filter applying) are shortened, not
   removed outright, since an instant modal pop is jarring. Purely
   decorative infinite animations are killed entirely.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  [data-intro],
  [data-intro] > * {
    transition-duration: 1ms !important;
    transition-delay: 0ms !important;
  }

  .hero-optics-svg .laser-line,
  .hero-optics-svg .laser-line-secondary,
  .hero-optics-svg .diffraction-ring,
  .hero-glow,
  .live-pulse-dot::after {
    animation: none !important;
  }

  .parallax-target {
    transform: none !important;
    transition: none !important;
  }

  .reveal-up, .reveal-down, .reveal-left, .reveal-right, .reveal-scale, .reveal-blur {
    transition-duration: 150ms !important;
    transition-delay: 0ms !important;
  }

  .channel-view.channel-enter {
    animation-duration: 150ms !important;
  }

  .blog-card:hover,
  .archive-card:hover,
  .inshort-card:hover,
  .tab-btn.active,
  .tab-btn:not(.active):hover,
  .btn-premium:hover {
    transform: none !important;
  }

  .magazine-cover {
    transform: none !important;
  }

  .feature-sweep-wrap::after,
  .magazine-cover::after,
  .btn-sweep::before {
    display: none !important;
  }

  .ripple-el {
    animation-duration: 200ms !important;
  }

  #glimpses-toast {
    transition-duration: 150ms !important;
  }

  #glimpses-toast #toast-icon {
    transition: opacity 150ms ease !important;
    transform: none !important;
  }

  .toast-progress {
    animation-duration: 3s !important;
  }

  #custom-cursor-dot {
    display: none !important;
  }

  .custom-cursor-active {
    cursor: auto !important;
  }
}
section {
  overflow: hidden;
  padding: 80px 0;
  scroll-margin-top: 90px;
  overflow: clip;
}

.section-bg {
  background-color: #eee;
}

.section-header {
  text-align: center;
  padding-bottom: 30px;
}

.section-header h2 {
  font-size: 13px;
  letter-spacing: 1px;
  font-weight: 400;
  margin: 0;
  padding: 0;
  color: #7f7f90;
  text-transform: uppercase;
  font-family: var(--font-default);
}

.section-header p {
  margin: 0;
  font-size: 48px;
  font-weight: 400;
  font-family: var(--font-primary);
}

.section-header p span {
  color: var(--color-primary);
}

/*--------------------------------------------------------------
# Breadcrumbs
--------------------------------------------------------------*/
.breadcrumbs {
  padding: 15px 0;
  background: rgba(55, 55, 63, 0.05);
  margin-top: 90px;
}

@media (max-width: 575px) {
  .breadcrumbs {
    margin-top: 70px;
  }
}

.breadcrumbs h2 {
  font-size: 24px;
  font-weight: 400;
  margin: 0;
}

.breadcrumbs ol {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
  padding: 0;
  margin: 0;
  font-size: 14px;
}

.breadcrumbs ol li+li {
  padding-left: 10px;
}

.breadcrumbs ol li+li::before {
  display: inline-block;
  padding-right: 10px;
  color: #676775;
  content: "/";
}

@media (max-width: 992px) {
  .breadcrumbs .d-flex {
    display: block !important;
  }

  .breadcrumbs h2 {
    margin-bottom: 10px;
  }

  .breadcrumbs ol {
    display: block;
  }

  .breadcrumbs ol li {
    display: inline-block;
  }
}

/* --------------------------------------------------------------------------
   26. Scrollbar Utilities & Overflow Prevention
   -------------------------------------------------------------------------- */
.no-scrollbar {
  -ms-overflow-style: none !important;
  scrollbar-width: none !important;
}
.no-scrollbar::-webkit-scrollbar {
  display: none !important;
  width: 0 !important;
  height: 0 !important;
}

html, body {
  max-width: 100%;
  overflow-x: clip;
}

