/* Wulfinn FX — theme-independent motion layer (loaded from custom/header.tmpl).
 *
 * Rules of the road, so nothing ever overlaps:
 *  - Only uses theme variables (--color-*), never hardcoded palette colors.
 *  - Never puts transform / opacity / filter animations on containers that can hold popups
 *    (sections, tables, rows, cards, dropdown buttons). Those create stacking contexts and
 *    make later siblings paint over open menus. Motion lives on leaf elements and pseudo-elements.
 *  - Never adds overflow:hidden to anything that can contain a dropdown or sticky header.
 *  - Page entrance is done with View Transitions (snapshot-based, zero layout side effects).
 *  - Everything is short (90–260ms), ease-out, no bounce. All disabled under reduced motion. */

:root {
  --border-radius: 8px;
  --border-radius-medium: 10px;
  --wf-r: 8px;
  --wf-out: cubic-bezier(0.16, 1, 0.3, 1);      /* expo-out: fast start, silky settle */
  --wf-snap: cubic-bezier(0.2, 0, 0, 1);        /* material "emphasized" */
  --wf-t1: 90ms;
  --wf-t2: 160ms;
  --wf-t3: 260ms;
  --wf-accent: var(--color-primary);
  --wf-accent-soft: color-mix(in srgb, var(--color-primary) 22%, transparent);
  --wf-accent-faint: color-mix(in srgb, var(--color-primary) 9%, transparent);
  --wf-shine: color-mix(in srgb, var(--color-text) 16%, transparent);
}

/* =========================================================================
   Rounding (subtle). Attached groups keep flush joins; only outer corners round.
   ========================================================================= */
.ui.segment,
.ui.table,
.ui.grid.segment,
.ui.top.attached.segment:only-child,
.ui.segments:not(.horizontal) > .segment:only-child { border-radius: var(--wf-r); }
.ui.top.attached.header,
.ui[class*="top attached"].segment,
.ui.segment[class*="top attached"]:first-child { border-radius: var(--wf-r) var(--wf-r) 0 0; }
.ui.bottom.attached.header,
.ui.attached.segment:last-child,
.ui.segment[class*="bottom attached"]:last-child { border-radius: 0 0 var(--wf-r) var(--wf-r); }
.ui.table > thead > tr:first-child > th:first-child { border-top-left-radius: var(--wf-r); }
.ui.table > thead > tr:first-child > th:last-child { border-top-right-radius: var(--wf-r); }
.ui.label { border-radius: 6px; }
.ui.secondary.vertical.menu { border-radius: var(--wf-r) !important; }
.ui.modal { border-radius: 12px; }
.ui.modal > :first-child { border-top-left-radius: 12px; border-top-right-radius: 12px; }
.ui.modal > :last-child { border-bottom-left-radius: 12px; border-bottom-right-radius: 12px; }
.markup pre, .markup img, .markup blockquote { border-radius: var(--wf-r); }
.markup code { border-radius: 5px; }
.tippy-box { border-radius: var(--wf-r); }
img.avatar { border-radius: var(--wf-r); }

/* =========================================================================
   Ambient
   ========================================================================= */
* { scrollbar-color: var(--color-secondary-dark-2) transparent; }

/* =========================================================================
   Page transitions (cross-document View Transitions; Chromium/Safari, ignored elsewhere)
   ========================================================================= */
@view-transition { navigation: auto; }
#navbar { view-transition-name: wf-navbar; }
::view-transition-group(wf-navbar),
::view-transition-old(wf-navbar),
::view-transition-new(wf-navbar) { animation: none; }
::view-transition-old(root) { animation: wf-out var(--wf-t1) var(--wf-snap) both; }
::view-transition-new(root) { animation: wf-in var(--wf-t3) var(--wf-out) both; }

/* =========================================================================
   Global transitions (color-ish properties only — safe everywhere)
   ========================================================================= */
a, .item, .ui.button, .button, .ui.label, input, textarea, select, svg.svg,
.flex-item, .ui.card, .ui.segment, .repo-file-item, .repo-file-line {
  transition:
    color var(--wf-t2) var(--wf-out),
    background-color var(--wf-t2) var(--wf-out),
    border-color var(--wf-t2) var(--wf-out),
    box-shadow var(--wf-t3) var(--wf-out),
    opacity var(--wf-t2) var(--wf-out);
}

/* =========================================================================
   Top bars: navigation loader + scroll progress
   ========================================================================= */
html::before {
  /* loading bar, toggled by wulfinn-fx.js via html.wf-busy */
  content: "";
  position: fixed;
  z-index: 10000;
  inset: 0 0 auto 0;
  height: 3px;
  pointer-events: none;
  background: var(--wf-accent);
  transform-origin: left;
  transform: scaleX(0);
  opacity: 0;
  transition: transform 1.6s cubic-bezier(0.1, 0.7, 0.2, 1), opacity 0.3s ease 0.15s;
}
html.wf-busy::before {
  transform: scaleX(0.85);
  opacity: 1;
  transition: transform 6s cubic-bezier(0.05, 0.8, 0.1, 1), opacity var(--wf-t1) linear;
}
html.wf-done::before {
  transform: scaleX(1);
  opacity: 0;
  transition: transform var(--wf-t2) var(--wf-out), opacity 0.25s ease 0.12s;
}
@supports (animation-timeline: scroll()) {
  html::after {
    content: "";
    position: fixed;
    z-index: 9999;
    inset: 0 0 auto 0;
    height: 2px;
    pointer-events: none;
    background: color-mix(in srgb, var(--wf-accent) 70%, transparent);
    transform-origin: left;
    animation: wf-progress linear both;
    animation-timeline: scroll(root block);
  }
}

/* =========================================================================
   Navbar
   ========================================================================= */
#navbar { position: relative; z-index: 30; } /* stacking context (view-transition-name) must sit above content so its menus are never covered */
#navbar::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 1px;
  pointer-events: none;
  background: color-mix(in srgb, var(--wf-accent) 55%, transparent);
  opacity: 0.8;
}
#navbar .item { border-radius: var(--wf-r); }
#navbar-logo img { transition: transform var(--wf-t3) var(--wf-out), filter var(--wf-t3) var(--wf-out); }
#navbar-logo:hover img { transform: rotate(-10deg) scale(1.1); }
#navbar-logo:active img { transform: rotate(-10deg) scale(0.95); transition-duration: var(--wf-t1); }
/* top-level nav links: underline grows in (menu items inside navbar dropdowns are untouched) */
#navbar > .navbar-left > a.item:not(#navbar-logo),
#navbar > .navbar-right > a.item { position: relative; }
#navbar > .navbar-left > a.item:not(#navbar-logo)::after,
#navbar > .navbar-right > a.item::after {
  content: "";
  position: absolute;
  inset: auto 25% 3px 25%;
  height: 2px;
  border-radius: 2px;
  background: var(--wf-accent);
  transform: scaleX(0);
  transition: transform var(--wf-t2) var(--wf-out);
  pointer-events: none;
}
#navbar > .navbar-left > a.item:not(#navbar-logo):hover::after,
#navbar > .navbar-left > a.item.active::after,
#navbar > .navbar-right > a.item:hover::after { transform: scaleX(1); }

/* =========================================================================
   Buttons — leaf buttons only (dropdown buttons hold menus, so they never transform)
   ========================================================================= */
.ui.button:not(.dropdown, .disabled, .is-loading):hover { transform: translateY(-1px); }
.ui.button:not(.dropdown, .disabled, .is-loading):active { transform: translateY(0) scale(0.97); }
.ui.button:not(.dropdown) {
  transition:
    color var(--wf-t2) var(--wf-out), background-color var(--wf-t2) var(--wf-out),
    border-color var(--wf-t2) var(--wf-out), box-shadow var(--wf-t3) var(--wf-out),
    transform var(--wf-t2) var(--wf-out), background-position 0.55s var(--wf-out);
}
.ui.button:not(.dropdown):active { transition-duration: var(--wf-t1); }
/* dropdown buttons: accent border instead of motion */
.ui.dropdown.button:hover { border-color: var(--wf-accent) !important; }
/* dropdown caret flips when open */
.ui.dropdown > .dropdown.icon { transition: transform var(--wf-t2) var(--wf-out); }
.ui.dropdown.active > .dropdown.icon { transform: rotate(180deg); }

/* ripple (spawned by wulfinn-fx.js) */
.wf-ripple-host { position: absolute; inset: 0; overflow: hidden; border-radius: inherit; pointer-events: none; }
.wf-ripple {
  position: absolute;
  width: 8px; height: 8px;
  margin: -4px 0 0 -4px;
  border-radius: 50%;
  background: currentcolor;
  opacity: 0.28;
  animation: wf-ripple 0.5s var(--wf-out) forwards;
}

/* =========================================================================
   Inputs
   ========================================================================= */
input:not([type="checkbox"], [type="radio"], [type="range"]):focus,
textarea:focus,
.ui.selection.dropdown.active {
  box-shadow: 0 0 0 3px var(--wf-accent-soft) !important;
  border-color: var(--wf-accent) !important;
}
:focus-visible { outline-color: var(--wf-accent); outline-offset: 2px; transition: outline-offset var(--wf-t1) var(--wf-out); }
.ui.checkbox input:checked ~ label::after, .ui.toggle.checkbox label::before { transition: all var(--wf-t2) var(--wf-out); }
.ui.checkbox input:checked ~ label::after { animation: wf-pop var(--wf-t2) var(--wf-out); }

/* =========================================================================
   Labels, avatars, icons (leaves: safe to move)
   ========================================================================= */
img.avatar { transition: transform var(--wf-t2) var(--wf-out), box-shadow var(--wf-t2) var(--wf-out); }
a:hover > img.avatar, a.avatar:hover img, img.avatar:hover {
  transform: scale(1.07);
  box-shadow: 0 0 0 2px var(--wf-accent-soft);
}
a:hover > svg.svg, .item:hover > svg.svg, .button:hover > svg.svg { transition: transform var(--wf-t2) var(--wf-out); }

/* =========================================================================
   Lists & rows: soft background highlight only (no transform, no side bars)
   ========================================================================= */
.flex-list > .flex-item:hover,
#repo-files-table > .repo-file-item:hover,
#repo-files-table > .repo-file-line:hover,
.ui.table.selectable > tbody > tr:hover {
  background-color: var(--wf-accent-faint);
}
#repo-files-table .repo-file-cell.name svg { transition: transform var(--wf-t2) var(--wf-out); }
#repo-files-table .repo-file-item:hover .repo-file-cell.name svg { transform: translateX(2px) scale(1.1); }
.ui.card:hover, .ui.cards > .card:hover { box-shadow: 0 0 0 1px var(--wf-accent-soft); }

/* =========================================================================
   Menus, dropdowns, tabs, tooltips
   ========================================================================= */
.ui.secondary.menu .item, .ui.tabular.menu .item { border-radius: var(--wf-r); }
.ui.secondary.pointing.menu .item, .ui.tabular.menu .item { position: relative; }
.ui.secondary.pointing.menu .item::after {
  content: "";
  position: absolute;
  inset: auto 10% -1px 10%;
  height: 2px;
  border-radius: 2px;
  background: var(--wf-accent);
  transform: scaleX(0);
  transition: transform var(--wf-t2) var(--wf-out);
}
.ui.secondary.pointing.menu .item:hover::after { transform: scaleX(0.5); }
.ui.secondary.pointing.menu .active.item::after { transform: scaleX(1); }

/* dropdown menus: clip reveal + item cascade (menu itself is a leaf popup — safe) */
.ui.dropdown .menu.visible,
.ui.dropdown.active > .menu {
  animation: wf-reveal var(--wf-t2) var(--wf-out) backwards;
}
.ui.dropdown .menu.visible > .item,
.ui.dropdown.active > .menu > .item { animation: wf-item var(--wf-t3) var(--wf-out) backwards; }
.ui.dropdown .menu > .item:nth-child(2) { animation-delay: 15ms; }
.ui.dropdown .menu > .item:nth-child(3) { animation-delay: 30ms; }
.ui.dropdown .menu > .item:nth-child(4) { animation-delay: 45ms; }
.ui.dropdown .menu > .item:nth-child(5) { animation-delay: 60ms; }
.ui.dropdown .menu > .item:nth-child(n+6) { animation-delay: 75ms; }

.tippy-box[data-state="visible"] { animation: wf-pop var(--wf-t2) var(--wf-out); }

/* modals */
.ui.modal { animation: wf-modal var(--wf-t3) var(--wf-out); }
.ui.dimmer.visible, .ui.dimmer.active { animation: wf-fade var(--wf-t2) linear; }

/* =========================================================================
   Content
   ========================================================================= */
.markup a:not(.anchor, .label, .button) {
  text-decoration: none;
  background: linear-gradient(currentcolor, currentcolor) 0 100% / 0 1px no-repeat;
  transition: background-size var(--wf-t3) var(--wf-out), color var(--wf-t2);
}
.markup a:not(.anchor, .label, .button):hover { background-size: 100% 1px; }
.markup img.wf-pending { opacity: 0; }
.markup img.wf-loaded { animation: wf-fade var(--wf-t3) var(--wf-out); }
.code-view .lines-code:hover, .code-view .lines-num:hover { background-color: var(--wf-accent-faint); }
.diff-file-box:hover { box-shadow: 0 0 0 1px var(--wf-accent-soft); }
.timeline-item .ui.segment:hover, .comment .content > .ui.segment:hover { box-shadow: 0 0 0 1px var(--wf-accent-soft); }
details > summary::marker { transition: color var(--wf-t2); }
.page-content.home .logo { animation: wf-float 5s ease-in-out infinite; }

/* notification badge: pulse ring (box-shadow only) */
.notification_count:not(.tw-hidden) { animation: wf-ping 2.4s var(--wf-out) infinite; }

/* =========================================================================
   Loaders: conic spinner + shimmer, replaces Forgejo's .is-loading ring
   ========================================================================= */
lazy-webc::after,
.is-loading::after {
  border: 3px solid var(--color-secondary) !important;
  border-top-color: var(--wf-accent) !important;
  border-right-color: var(--wf-accent) !important;
  animation: isloadingspin 0.6s linear infinite !important;
}
.is-loading.loading-icon-2px::after { border-width: 2px !important; }
lazy-webc::before,
.is-loading:not(.button, .btn)::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(100deg, transparent 30%, color-mix(in srgb, var(--color-text) 7%, transparent) 50%, transparent 70%) 0 0 / 250% 100% no-repeat;
  animation: wf-shimmer 1.1s linear infinite;
}
/* generic skeleton helper: <div class="wf-skeleton"></div> */
.wf-skeleton {
  border-radius: var(--wf-r);
  background: linear-gradient(100deg, var(--color-secondary) 30%, var(--color-secondary-light-1) 50%, var(--color-secondary) 70%) 0 0 / 250% 100%;
  animation: wf-shimmer 1.1s linear infinite;
}

/* =========================================================================
   Keyframes
   ========================================================================= */
@keyframes wf-in { from { opacity: 0; transform: translateY(6px); } }
@keyframes wf-out { to { opacity: 0; } }
@keyframes wf-fade { from { opacity: 0; } }
@keyframes wf-pop { from { opacity: 0; transform: scale(0.94); } }
@keyframes wf-modal { from { opacity: 0; transform: translateY(8px) scale(0.98); } }
@keyframes wf-reveal { from { opacity: 0; clip-path: inset(0 0 100% 0 round var(--wf-r)); } to { clip-path: inset(0 0 0 0 round var(--wf-r)); } }
@keyframes wf-item { from { opacity: 0; transform: translateY(-4px); } }
@keyframes wf-ripple { to { transform: scale(60); opacity: 0; } }
@keyframes wf-flow { to { background-position: -200% 0; } }
@keyframes wf-sweep { from { background-position: -30% 0, 0 0; } to { background-position: 130% 0, 0 0; } }
@keyframes wf-progress { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes wf-shimmer { from { background-position: 100% 0; } to { background-position: -100% 0; } }
@keyframes wf-float { 50% { transform: translateY(-8px); } }
@keyframes wf-ping {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-red) 60%, transparent); }
  70%, 100% { box-shadow: 0 0 0 6px transparent; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after,
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) {
    animation: none !important;
    transition: none !important;
  }
}
